Release pressed key / holding down key

Started by rongel, Wed 15/01/2020 10:45:11

Previous topic - Next topic

rongel

Hi!

This might be a very simple question, but I couldn't find an answer for it, and I want to do it right.

I have menu screen that comes up when I press "ESC" key. My code is simply something like this:

Code: ags
if(keycode ==eKeyEscape) {
  if(!gControl.Visible) gControl.Visible = true;
  else gControl.Visible = false;
}


Everything works, unless player holds down the ESC key. Then the menu screen constantly switches on and off, and I dont want that. The menu screen should appear when the player releases the ESC key. The player needs to press it again to close it. Holding down the key shouldn't have any effect, pressing it should be like when pressing a gui button, the action happens when the button is released.

What would be the simplest way to achieve this?  Thanks!
Dreams in the Witch House on Steam & GOG

Matti

Ha. I never noticed that behavior, because I never tried  :-D. But now that you mentioned it I'm very much interested in an answer too.

eri0o

On key press event triggers dependant on the OS configurations for your operating system, like when you hold a key in a input form and it inputs that key repeatedly. To avoid it, if undesired, you can instead detect the key press/release on a repeatedly_execute block (if you don't want to trigger during blocking events) or on a repeatedly_execute_always event.

you can use the following pattern:
Code: ags
bool was_key_A_pressed;
void repeatedly_execute_always(){
  if(!was_key_A_pressed && IsKeyPressed(eKeyCodeA)){
    // do stuff
  }
  was_key_A_pressed = IsKeyPressed(eKeyCodeA);
}


I typed from memory so you may have to fix the above code. You can invert the ! on the if to switch to a release transition or use exclusive or to trigger on any transition.

Crimson Wizard

Also, if you have several keys to track like this, there was a KeyListener module I once wrote: https://www.adventuregamestudio.co.uk/forums/index.php?topic=53226.0

rongel

Thanks for the answers! The module sounds really good Crimson Wizard, I might use that. But I want to get this working first, I have trouble to closing the gui...

So I don't use anymore on_key_press, my script is now in GlobalScript under repeatedly_execute(). The code looks like this:


Code: ags
if(!was_key_ESC_pressed && IsKeyPressed(eKeyEscape)) {
  gControl.Visible = true;
}
was_key_ESC_pressed = IsKeyPressed(eKeyEscape);


So this works fine, I tested it with another command, and it only gives one action like it should. But closing the gui is not working for me, I tried this under the previous script:

Code: ags
if(was_key_ESC_pressed && IsKeyPressed(eKeyEscape)) {
  gControl.Visible = false;
}


That causes the gui flicker on and off. What am I doing wrong?
Dreams in the Witch House on Steam & GOG

eri0o

gControl.Visible = !gControl.Visible;

on the first bit of code you posted.

rongel

Quote from: eri0o on Wed 15/01/2020 12:43:59
gControl.Visible = !gControl.Visible;

on the first bit of code you posted.

Sorry eri0o, still didn't get it, you need to spell it out for me... Did you mean that I add gControl.Visible = !gControl.Visible;  to this:

Code: ags
if(!was_key_ESC_pressed && IsKeyPressed(eKeyEscape)) {
  gControl.Visible = true;
}
was_key_ESC_pressed = IsKeyPressed(eKeyEscape);


I tried it and also tried adding it to the script on the first post, but got the on/off flicker again.
Dreams in the Witch House on Steam & GOG

eri0o

#7
Instead of setting to true, set to the inverse value it had before.

Boolean algebra 101:

! is the not operator
!0 == 1
!1 == 0

&& is the and operator
0&&0 == 0
0&&1 == 0
1&&0 == 0
1&&1 == 1

(1 is true, 0 is false)

__0__/””1”” -> we want to detect a up border transition

__was 0__/""" now 1

!was && now == true // condition we want to detect, a press

If it was a down border, then

was && !now == true // the release condition

Here is the code, the explanation is above.

Code: ags
bool was_key_ESC_pressed;
void repeatedly_execute_always(){
  if(!was_key_ESC_pressed && IsKeyPressed(eKeyEscape)) {
    gControl.Visible = !gControl.Visible;
  }
  was_key_ESC_pressed = IsKeyPressed(eKeyEscape);
}

rongel

Ok, got it:

Code: ags
if(!was_key_ESC_pressed && IsKeyPressed(eKeyEscape)) {
  gControl.Visible = !gControl.Visible;
}
was_key_ESC_pressed = IsKeyPressed(eKeyEscape);


It works now just the way I want it to, thanks! Yeah, I need to brush up my boolean algebra some day...  :-D
Dreams in the Witch House on Steam & GOG

SMF spam blocked by CleanTalk