Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Key State

This thread is locked; no one can reply to it. rss feed Print
 1   2 
Key State
AceBlkwell
Member #13,038
July 2011
avatar

I'm working with the directional key state macros "key[KEY_UP]" type thing. It works well if you are moving a bit map around the screen. However, not so good if you just want to read which cell a person is moving to. I won't bore everyone with the details of the game. but here is a rough idea of what I'm doing

1)Player has a board (like checkers, sorta) with a current status.
2) The player can move Up, Down, L/R, one square.
3) Once direction is decided, the player's piece is moved
4) Board redrawn
5) continue at step 1

Anyways, my problem is when the up (in this case) arrow is hit, it actually buffers several times and I've got no way of emptying the buffer. I've tried clear_buf but didn't do anything. I've tried a while(keypressed); loop thinking it would run through the loop until a key press wasn't detected but it locks in the loop. I know I can use readkey() and use letters like a,s,d,w, but would rather use the arrow keys. Unless there is a way I haven't found yet, I can't get readkey to do anything with arrow key scans.

In short, is there a way of emptying the key buffer using arrow keys or is there a difference key scan that works with readkey()/clear_buf and arrow keys.

Thanks in advance for the attention.
Ace

Dizzy Egg
Member #10,824
March 2009
avatar

Wouldn't something like this help?

bool allowUp = true;

if (upKey) {
 //Up Key Pressed 
  allowUp = false;
}
else if(!upKey){
  allowUp = true;
}

----------------------------------------------------
Please check out my songs:
https://soundcloud.com/dont-rob-the-machina

Niunio
Member #1,975
March 2002
avatar

You can change the "key" array content. For example:
key[KEY_UP] = 0;
Or you can use an auxiliar variable:

  if (key[KEY_UP]) {
    MoveUp ();
    KeyUpPressed = TRUE;
    KeyDownPressed = KeyLeftPressed = KeyRightPressed = FALSE;
  }

[edit] I'm so so slow...:-[

-----------------
Current projects: Allegro.pas | MinGRo

AceBlkwell
Member #13,038
July 2011
avatar

The problem with changing the key up value or using a secondary value, is it doesn't eliminate the scanned keys. IE

User its key up,the buffer reads
keyup
keyup
keyup
keyup
keyup

So if I change the keyup to read false (0) then the second scan key up comes back and says true. Key in mind, when running a key[XXX] while loop, the loop runs continously. So changing the internal key[UP] to 0 , only works for that one trip through the loop. The next time through the loop and it scans the key board, it's going to see there are more key[ups] in waiting and will react accordingly. I have to empty the buffer some how.

However, I will trial these just to make sure my understanding of the process isn't wrong.

Thanks guys,
Ace

gnolam
Member #2,030
March 2002
avatar

Niunio said:

You can change the "key" array content.

Bad Niunio! Bad! The key array should be treated as read-only. >:(

Anyway. Solution:

#SelectExpand
1char keyBuffer[KEY_MAX]; 2 3void input(void) 4{ 5 // Do something once when KEY_UP is pressed 6 if (key[KEY_UP] && !keyBuffer[KEY_UP]) { 7 foo(); 8 } 9 10 // Do something once when KEY_UP is released 11 if (!key[KEY_UP] && keyBuffer[KEY_UP]) { 12 bar(); 13 } 14 15 // Do something every cycle while KEY_UP is down 16 if (key[KEY_UP]) { 17 baz(); 18 } 19 20 for (int i = 0; i < KEY_MAX; i++) { 21 keyBuffer[i] = key[i]; 22 } 23}

--
Move to the Democratic People's Republic of Vivendi Universal (formerly known as Sweden) - officially democracy- and privacy-free since 2008-06-18!

Arthur Kalliokoski
Second in Command
February 2005
avatar

gnolam said:

Bad Niunio! Bad! The key array should be treated as read-only. >:(

It looked to me like he had cloned variables that he was altering, not the actual Allegro key array.

They all watch too much MSNBC... they get ideas.

David Sopala
Member #5,056
September 2004

Check for release and not for press.

#SelectExpand
1bool keyrel(int k) 2{ 3 static bool initialized = false; 4 static bool keyp[KEY_MAX]; 5 6 if(!initialized) 7 { 8 // Set the keyp (key pressed) flags to false 9 for(int i = 0; i < KEY_MAX; i++) keyp[i] = false; 10 initialized = true; 11 } 12 13 // Now for the checking 14 // Check if the key was pressed 15 if(key[k] && !keyp[k]) 16 { 17 // Set the flag and return 18 keyp[k] = true; 19 return false; 20 } 21 else if(!key[k] && keyp[k]) 22 { 23 // The key was released 24 keyp[k] = false; 25 return true; 26 } 27 // Nothing happened? 28 return false; 29}

AceBlkwell
Member #13,038
July 2011
avatar

Thanks all, I'll give it a try.

Sorry if my paraphrasing of the actual KEY array command confused those trying to help.

The whole key pressed Vs key released may give me a work around as you guys have shown. I did have one concern however, if the Player hits up and then releases, how many times will the combination Up and press be true before the player can release the key?

I'm hoping the solution will allow me...
1)to read an up key.
2)Stop the player input / involvement
3) Correct board according to direction chosen.
4) Return to a clean buffer / condition
5) await next directional move.

Again, the only potential issue I can see from the solution, not having tried them, would be if the up and pressed conditions are read 5-6 times before the player turns loose of the key. I guess I could add a third condition that starts false and trues the first time through the if statment. Then when I get key released scan, can falsify it again.

Just thinking out loud.

Thanks again to all and I'll update the page once I try the solution.

Ace

Dizzy Egg
Member #10,824
March 2009
avatar

The key can't hit 5 times in one pass of a loop, it's impossible. Show your code, somethings wrong.

----------------------------------------------------
Please check out my songs:
https://soundcloud.com/dont-rob-the-machina

Specter Phoenix
Member #1,425
July 2001
avatar

I used to get the same feedback when I did keypress for debugging. I made it so that when a key was pressed it would output debug info to a file. When I opened the file it would have about 5 or so for each key press. Not sure if that is what he is talking about but the code I used was the code from Tomasu's wiki tutorials.

I did if (keys[KEY_UP]){ outfile << "Debug coords:" << x << ", " << y << "\n";}

Output would be like:

Debug coords: 3, 4
Debug coords: 3, 4
Debug coords: 3, 4
....
....

AceBlkwell
Member #13,038
July 2011
avatar

Specter Phoenix is correct, When I print something out, it shows the key to hit 4-5 times.

I won't bore everyone with the entire code given I'm just testing different aspects until I have all the components working. But here is essentially what I have (I'm just including one key for the sake of demonstration.

while(key[ESC]){

if(key[KEY_UP])
printf("Yo!");
}

this is a little skeleton compared to what I have but the issue is the same. And yes I know I can't see the print out until I drop out of graphics mode. But when I do I see 4-5 "Yo"s when I actually only hit the up arrow for a second. This tells me one of two things have to be true.
1) Either the loop runs so fast that in just touching the up arrow once it hold the condition "if(key[KEY_UP]" true for 4-5 times though the loop,
or
2) the key buffer holds 3-4 more up arrow keys so that each time through the loop the condition is true, until the buffer runs out.

So now I either need to either change the condition of #1 to look for a key release (as suggested above) after the first key[UP] is true or if #2 is true I need a way of depleting the key buffer given I can't find a way to clear on command.

Thanks for the suggestions
Ace

David Sopala
Member #5,056
September 2004

The loop runs fast use key_rel instead of checking if the key is pressed.

your checking a bool very quickly here and it will input 5 if not more times

#SelectExpand
1#include <allegro.h> 2#include <conio.h> 3 4using namespace std; 5 6 7bool keyrel(int k); 8 9int main() 10{ 11 //ini allegro kb and such 12 while(!key[KEY_ESC]) 13 { 14 if(keyrel(KEY_UP)) 15 { 16 cout<<"Yo!"<<endl; 17 } 18 } 19} 20END_OF_MAIN() 21 22bool keyrel(int k) 23{ 24 static bool initialized = false; 25 static bool keyp[KEY_MAX]; 26 27 if(!initialized) 28 { 29 // Set the keyp (key pressed) flags to false 30 for(int i = 0; i < KEY_MAX; i++) keyp[i] = false; 31 initialized = true; 32 } 33 34 // Now for the checking 35 // Check if the key was pressed 36 if(key[k] && !keyp[k]) 37 { 38 // Set the flag and return 39 keyp[k] = true; 40 return false; 41 } 42 else if(!key[k] && keyp[k]) 43 { 44 // The key was released 45 keyp[k] = false; 46 return true; 47 } 48 // Nothing happened? 49 return false; 50}

Specter Phoenix
Member #1,425
July 2001
avatar

I'll paste code from the movement code and the output file.
Movement Code

if(key[KEY_UP] && cell_y >= 4.0)
{
     cell_y -= 4.0;
     outfile << "KEY_UP == X: " << cell_x << ", Y: " << cell_y << "\n";
}

Sample Output

KEY_RIGHT == X: 208, Y: 148
KEY_RIGHT == X: 212, Y: 148
KEY_RIGHT == X: 216, Y: 148
KEY_RIGHT == X: 220, Y: 148
KEY_DOWN == X: 220, Y: 152
KEY_DOWN == X: 220, Y: 156
KEY_DOWN == X: 220, Y: 160
KEY_LEFT == X: 216, Y: 160
KEY_LEFT == X: 212, Y: 160
KEY_LEFT == X: 208, Y: 160
KEY_UP == X: 208, Y: 156
KEY_UP == X: 208, Y: 152
KEY_UP == X: 208, Y: 148

That is just a quick press on each key.

gnolam
Member #2,030
March 2002
avatar

And this is why people get disillusioned with helping people code.

--
Move to the Democratic People's Republic of Vivendi Universal (formerly known as Sweden) - officially democracy- and privacy-free since 2008-06-18!

Specter Phoenix
Member #1,425
July 2001
avatar

gnolam said:

And this is why people get disillusioned with helping people code.

Yeah, but I'm not asking for help, just illustrating what is happening. I've learned asking for help is a waste because you get too many varied answers and normally none of them are close to your coding style so you end up still lost.

I got to the point, over the years, to where I just act like I had a clue what they said and then skip what I was getting help with and come up with something else to code. I was doing an address book, and got stuck on something, so moved on to pong, got stuck on pong and moved to learning perl, got stuck on perl and learned ruby, got stuck their and went back to coding simple apps that I knew how to do.

Dizzy Egg
Member #10,824
March 2009
avatar

WE'VE ALREADY SAID 100 TIMES, FLAG THE KEY AS BEING PRESSED UP ON THE FIRST PASS OF THE LOOP AND DON'T RESET THE FLAG UNTIL THE KEY IS RELEASED >:(

----------------------------------------------------
Please check out my songs:
https://soundcloud.com/dont-rob-the-machina

Specter Phoenix
Member #1,425
July 2001
avatar

Dizzy Egg said:

WE'VE ALREADY SAID 100 TIMES, FLAG THE KEY AS BEING PRESSED UP ON THE FIRST PASS OF THE LOOP AND DON'T RESET THE FLAG UNTIL THE KEY IS RELEASED >:(

So this is wrong (from Tomasu's Movement Tutorial):

enum MYKEYS{KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT};
bool key[4] = {false, false, false, false};
while(!doexit)
{
     else if(ev.type == ALLEGRO_EVENT_KEY_DOWN)
     {
     }
     else if(ev.type == ALLEGRO_EVENT_KEY_UP)
     {
     }
}

Which brings up the question: What is the point of a wiki if the examples are wrong and never corrected with the "100 times" repeat so you didn't have to say it 100 times?

[REVISION]
Tomasu, not attacking your code or anything. Just pointing out the idiocy of "we have said it 100 times" and yet if the topic has been addressed that much you would think they would have done a fix or posted a new page. Then instead of "we said it 100 times" the can say "look here <wiki url>" or even sig them :P.

LennyLen
Member #5,313
December 2004
avatar

So this is wrong (from Tomasu's Movement Tutorial):

No, because you've failed to understand the code. What it does is set a flag for each direction if a specific key is being pressed, and then unset it when the key is released. If the flags are set, then various things happen, otherwise they don't.

The key[] array in Tomasu's example is not the same as the key[] array in A4.

Specter Phoenix
Member #1,425
July 2001
avatar

LennyLen: I understand the code, but I was trying to point out that even with Tomasu's A5 code it still prints out multiple lines with one press. I simply copied and pasted the code, added file i/o to each key, and when I just pressed it once I got the 3 or 4 lines per press.

LennyLen
Member #5,313
December 2004
avatar

LennyLen: I understand the code, but I was trying to point out that even with Tomasu's A5 code it still prints out multiple lines with one press. I simply copied and pasted the code, added file i/o to each key, and when I just pressed it once I got the 3 or 4 lines per press.

That's how it's supposed to work with the Wiki example. It's a movement example, so it's supposed to continue to move for as long as the key is held down.

Specter Phoenix
Member #1,425
July 2001
avatar

LennyLen said:

That's how it's supposed to work with the Wiki example. It's a movement example, so it's supposed to continue to move for as long as the key is held down.

Yeah but I'm not holding it down. I just do one quick keypress of say left and the file io shows 3 or 4 outputs for just one quick keypress. Like if I press 'a' to make a and had file io attached to that key that outputs say "Hello", I would have an output file that would have Hello Hello Hello Hello just for one press of a.

Niunio
Member #1,975
March 2002
avatar

gnolam said:

Bad Niunio! Bad!

I know. It's bad because it will be changed by "key repetition". :-[

Anyway, my second approach (using auxiliary variables or an array as you suggest) would work here.

-----------------
Current projects: Allegro.pas | MinGRo

LennyLen
Member #5,313
December 2004
avatar

Yeah but I'm not holding it down. I just do one quick keypress of say left and the file io shows 3 or 4 outputs for just one quick keypress.

As far as the hardware is concerned, that is holding it down. It's a lot quicker than you are.

Specter Phoenix
Member #1,425
July 2001
avatar

LennyLen said:

As far as the hardware is concerned, that is holding it down. It's a lot quicker than you are.

Is there a way to fix it? Rather annoying to sift through a file of 100 lines of debug data when each one has 3 unneeded duplicates.

Arvidsson
Member #4,603
May 2004
avatar

Is there a way to fix it?

Fix what exactly? If you want something to be logged when you press a key you check for a pressed key, and not if it's held down or not.

 1   2 


Go to: