SUGGESTION: IsKeyPressed and OnKeyPress (or something)

Started by Kinoko, Thu 03/03/2005 01:56:38

Previous topic - Next topic

Kinoko

There are a lot of times I've come across where having IsKeyPressed work the way that it does is a problem. There are a lot of situations where, instead of having the game check to see if the key is pressed right now, I'd like it to act when the key is actually pressed down. ie, the game only acts if the key goes from not being pressed, to pressed. Maybe as if there was a line of code submitted once when a key is pressed, and the action only occurs when that code is received.

Well, I don't know how it actually works, obviously, but having a function seperate to IsKeyPressed that works that way would be really handy I think. I know there are workarounds, and I use a lot of them, but it would mean I wouldn't get a headache each time I have to work around this.

Is this possible at all?

Gilbert

I don't know if this is what you want, I think you can make a variable (say, int currentkey; on top of the global script) to hold the keycode of key pressed and record it in onkeypress, something like:

function on_key_press(int keycode){
Ã,  currentkey=keycode; //record it
Ã,  blahblabla...
}

Then in repeated_execute() add something like:

if (currentkey) { //if a key is previously pressed
Ã,  if (IsKeyPressed(currentkey)) { //if the key is still being pressed
Ã,  Ã,  blahblahbla...
Ã,  } else { //released
Ã,  Ã,  currentkey=0;
Ã,  Ã,  blahblabla...
Ã,  }
}

Kinoko

If I'm understanding your code correctly (and my history predicts I may not be), it's not quite what I mean.

The other point being that, if its possible to simply make a function out of this, I'd prefer not do have a work around. For the sake of not having to use this kind of scripting everytime I want a keypress to be recognised just once and only when actually being pressed down, not held down.

I'll tell you one of my situations anyway. Basically, I have a GUI with items all lined up, and below them, a button called "DELETE". This game doesn't use the mouse, so it's all navigated with the arrow keys, a cancel button (z) and a confirm button (x).

You use the arrow keys to move from item to item, or down to highlight the DELETE button. If you're currently on the DELETE button and press x, the cursor will change to 'delete' mode and automatically move up to the first item. From here, you can either press z to cancel the delete mode, or move the arrow keys to the item you want, then press x to delete it.

Currently, when DELETE is highlighted, if you press x to go into delete mode, it will do so but then automatically delete the first item because technically, x was still pressed down when the cursor was on the first item. Even for a normal, swift button press.

Code: ags

...
    else if (cursormenu==26) { // if the cursor is over the DELETE button
      if (IsKeyPressed(keyx)) { //if you press X
        del=1; //go into DELETE mode
        cursormenu=10; 
        CursorPos(4); //cursor goes over item #1
        }
    }
  if ((del==1) && (IsKeyPressed(keyz))) { //if in DELETE mode and press Z
    del=0; //cancel DELETE mode
    }
  else if ((del==1) && (IsKeyPressed(keyx))) DeleteItem(); //in DELETE mode and X is pressed, delete item


I tried a number of workarounds including one this (which works):

Code: ags

...
    else if (cursormenu==26) { // if the cursor is over the DELETE button
      if (IsKeyPressed(keyx)) { //if you press X
        del=2;
        }
    }
    if ((del==1) && (IsKeyPressed(keyz))) {
      del=0;
      SetButtonPic(3, 16, 1, 0);
      cursormenu=26;
      CursorPos(15);
      }
    else if ((del==1) && (IsKeyPressed(keyx))) DeleteItem();


and in repeatedly_execute:
Code: ags

    if ((del==2) && (IsKeyPressed(keyx)==0)) {
      del=1;
      cursormenu=10;
      SetButtonPic(15, 2, 1, 0);
      CursorPos(3);
      }


...but I'm no doubt going to have to do this sort of thing quite a bit, and it's getting a little code-heavy.

Either way, it just seems to me that a simple function like IsKeyPressed that just works once and only when the key is first pressed down would make things a lot easier. I have to come up with some convoluted code for it everytime. I don't mind if that's the way it has to be, but if it's possible to include a function like this in AGS itself, it'd make things a lot neater and easier.

Gilbert

I haven't read all of the post yet, but shouldn't the on_key_press() function better suited for this kind of situation?

Anyway, I think my code would work for this kind of situation.

Acompanying the stuff I mentioned (BUT move the currentkey=keycode; line to the bottom of on_key_press() ) , just in on_key_press() (del same as you originally mentioned for holding the delete mode status):

if (keycode==keyx){
  if (del==1) {//in del mode
     if (currentkey!=keyx) {//if the key pressed last game loop is not x, delete, otherwise ignore
       deletecodeblahbla...
    }
  } else { //not in del mode
    gotodeletemodecodeblahbla...
  }
}


}

Kinoko

Quote from: Gilbot V7000a on Thu 03/03/2005 04:30:51
I haven't read all of the post yet, but shouldn't the on_key_press() function better suited for this kind of situation?

All of this code is in the on_key_press section... is that what you mean?

RickJ

Kiniko,

I think you are having some confusion so let me see if I can help clarify things a bit.  Allow me to explain from the beginning, though you may know much of this already. 

Frist the on_key_press() function is only called when a key is pressed.  The next thing to do is to find out which key is pressed.  The parameter "keycode" contains the ASCII code of the key that was pressed as a decimal value.   This parameter is used the same as you would use any other integer variable (i.e. int).  It's value is set by the game engine before on_key_pres() is called.   So you don't need to use the function IsKeyPressed() inside the on_key_press() function.  Do something like the following instead.

int prevkey=0;
function on_key_press(int keycode){

   if (keycode==keyx) {
      DoSomething(STATE, keycode);
   }
   else if (keycode==keyy) {
      DoSomethingElse(STATE, keycode);
   {
   prevkey = keycode;
}


If you want to know when a key changes from one thing to another you must create a variable outside of the the bounds of the function.  Variables declared within the bounds of a function are created when the function is called and then destroyed when it completes. Destroyed means that the variable's assigned memory is reclaimed and can be reassigned when other functions are called.  Variables declared outside the bounds of any functions are persistent and retain their values throughout the game.  I believe that game save and restore operations preseve the values of such variables.

Ok! But what are those DoSomething() and DoSomethingElse() thingies?  Obviously they are functions, functions that you have previously created and that contain the rest of your logic.  They must appear in the gloabl script before the on_key_press() function.  They would look something like this

#define THIS                       -100
#define THAT                       -101
#define THE_OTHER_THING -102

function DoSomething(int state, int keycode) {
   if (state==THIS) {
      if (keycode==42) {
      }
      else {
      }
   }
   else if (state==THAT) {
   }
   else if (state==THE_OTHER_THING) {
   }
   else {
      Display("*** Error, undefined state");
   }
}


I think you will find it easier to work with if you get your logic out of the on_key_press function and split up your logic in to one or more functions of your own name and design.   

If you need more help just ask, of course...  ;)

SMF spam blocked by CleanTalk