kbhit() vs. allegro equivalents
Dave Kovich

I'm sure about the details of kbhit() but im almost certain it isnt picking up every key press. The npcs in my game have the same walking speed as the character however they appear to move faster...i assume this is because every time through the loop, the npc moves or doesnt move based on whats its supposed to do while the character may not be moving during some loops because the kbhit function isnt picking up every key hit ( the player is holding the key down ). So my question is, should i use an allegro equivalent of kbhit() or wont it make a diffrence, and, is there a function i should use to test for the key being held down instead? Any help is appreciated.

Johan Peitz

For moving things like the player sprite, where the player will hold down keys, you shouldn't use kbhit() or allegro keypressed/readkey at all.

I suggest you read up on the keyboard functions in the allegro manual. There's an array key[..] that you can check for keypresses. Look it up, it is your friend.

Murray Bozinsky

Hey, this is rather another question than a reply, but as it concerns hitting keys, i'll post it here instead of starting a new thread.

Here it is:

Is there a way to "slow down" the keyboard? Well assume I have a menu and hitting ESC opens/closes this menu. If I use a simple if (key[KEY_ESC] && !menu_is_active) open_menu(); and if (key[KEY_ESC] && menu_is_active) close_menu(); hitting ESC once will open and close the menu a hundred times. Or assume I'm coding a text-input box. If I hit a character on the keyboard, this character will be added to the input-line 100x instead of once. I know I could either use a loop like if (key[KEY_ESC]) while (key[KEY_ESC]) or I could implent a timer that locks the keyboard for a certain time after each keypress. Using a loop will pause the game-logic and using a timer for this is a pain in the *ss. Isn't there a more simple and comfortable way?

Thanks in advance,

/Murray Bozinsky

gnolam
char keylog[KEY_MAX];

memcpy((void*)keylog,(void*)key,sizeof(keylog));

poll_keyboard();

if ((key[KEY_ESC]) && (!keylog[KEY_ESC]))
   {
    /* this will only be executed once per keypress */
    if (!menu_is_active)
       open_menu();
    else
       close_menu();
   }

BAF
if ( ( readkey() >> 8 ) == KEY_ESC && !menu_is_active ) open_menu();

//...//

Try that!

[edit]mine showed up first i edited and gnolam came on before me. !:'(

Murray Bozinsky

Hey gnolam, I think I understand. All I have to do is polling the keyboard and copying the keyboard-buffer to a temp-buffer say twice a second, right? that sounds easy, thank you!

/Murray Bozinsky

CGamesPlay

Nobody said anything about twice a second, btw.

Dave Kovich

Annnyyywayyy.......in reply to johan peitz, after i read your reply i looked through the keyboard section of the allegro manual and cant find what i think im supposed to be looking for ( which is a function that you use when a key is being held down, right? ). So whats the function, and how should i use it? Thanks.

Matthew Leverton
Johan Peitz said:

I suggest you read up on the keyboard functions in the allegro manual. There's an array key[..] that you can check for keypresses. Look it up, it is your friend.

Zaphos

readkey() reads at the OS-determined key_repeat_rate -- so if you hold down the key it will see the new key presses at about the same rate that a letter would appear if you held down that letter's key while in, say, notepad.

What you want is simply to read key[] buffer to see if a key is currently held or released:
http://www.allegro.cc/manual/view_function.php?_id=1121

If you really still think you want to use readkey, you can try to use allegro's set_keyboard_rate() function to a low, non-zero value -- don't set it to 0, though! I believe allegro interprets a value of 0 as infinity (no repeat) instead of infinite repeat (infinite repeat is sorta not possible, I think, so this actually makes sense).

Edit: Matthew beat me!

aybabtu

Can't you just clear_keybuf()
Or key[KEY_ESC]=false

gillius

No you can't do that. key is defined to be read-only I think. I don't think clear_keybuf clears the key array anymore with the latest Allegro versions -- I remember people complaining that it broke their code.

Sirocco
Quote:

No you can't do that. key is defined to be read-only I think.

Yep, the key[...] array is a state collection container, meaning that the values in it get updated at regular intervals. Which is basically a fancy way of saying writing to it will have no effect :)

Side note:

The interesting thing about PLC programming (industrial motion controllers and such) is that they are mostly based on state collection containers, so you don't work with variables per se on a regular basis. It's really easy work, but it can be difficult to remember that you can't take input from a device (encoder, limit switch, pressure monitor, etc) and modify that input -- that just won't work for the same reason :)

Blah, I prefer PC programming, but there's more money in PLC work, so...

gnolam

Murray Bozinsky: Or whatever time interval you want - myself, I copy it before every poll. Wasteful? we don't need no steeenkin' memory bandwidth! ;)
(or rather, it's just 115 chars getting copied, so why worry?)

Sirocco: Heh, I actually got to do a bit of PLC programming for a group project last semester. I got away with doing the "difficult"* work with the PLC while my teammates did most of the "easy" paperwork ;D

* this project basically only required setting parameters for a PID regulator, adding a manual/automatic switch and an automatic cutoff when the input reached a certain value - all in all, about 7 variables and say, 2 or 3 conditionals to keep track of :)

StevenVI

You people are silly :P. This is how I always control the time between keypresses:

if(key[KEY_*]) // do thing that must be executed every frame

while(keypressed())
{
  int k = readkey() >> 8;
  switch(k)
  {
    case KEY_*: /* do thing that needs more time
in between hits, such as performing the
keychecking on a menu */
      break;
  }
}

That way, you can set the keyboard repeat rate, and that's the minimum amount of time that will exist between those keypresses where more than one frame is needed in between.

-Steve

Evert
Quote:

No you can't do that. key is defined to be read-only I think.

Technically, it's not, because you can't define variables as read-only from user code and writable from library code, but if you could, then it should be read-only.

Murray Bozinsky

@Harry Carey:

Quote:

You people are silly . This is how I always control the time between keypresses:

As I already said, a while loop pauses the game-logic. While the key is pressed, the loop is working, hence nothing else is updated.

/Murray Bozinsky

CGamesPlay

BUT, we realize this, and it's not like we're going to go loading any data during that loop.

By the same logic, every instruction pauses game logic, and while any instruction is being executed, no others can.

Dave Kovich

So can someone maybe give me a quick example of what a simple loop looks like...(is this right?):

while( loop > 0 )
{
if( key[KEY_W]) //assume W moves player up
{
do some logic type things;

}
loop--;
}
do drawing things here;

StevenVI

Dave:
Are you asking how to make a game loop to regulate the program's speed now? (It sounds like you are, if not, you can ignore the rest of my babbling) Check out the Allegro FAQ, it metions a (rather neanderthal) method of doing it. I always prefered getting the time in between the current frame and the frame before it, and updating according to the elapsed time. That way, your program can run at either 50 fps or 500 fps and it's not forced to any specific hard-coded framerate. I believe this is how all professional games do it ;).

Murray:
Yes? The while loop in my code doesn't stop the game action until a key is pressed, however. The code I posted will do the following:
1) Process all keys that need to be read every single frame, such as the keys to move the player.
2) Check if a key is waiting in the input buffer. If so, it takes the key out of the buffer and processes the switch, and then after processing that switch it goes back to the beginning of this step. If there isn't, then it just exists the keychecking phase of the game loop.

The key buffer works differently from the key[] array. Items are only added to it at the rate set by set_keyboard_rate -- meaning that if you set the delay and rate for key buffer repeats to say 250ms, then after you have pressed KEY_ESC the first time, it won't show up in the key buffer until 1/4 of a second later -- but the game loop still runs normally, totally unaware that there's another process counting the ticks between the last time KEY_ESC was enqueued in the buffer. Does that explain things a bit better?

-Steve

Dave Kovich

Isnt that basically what you're doing if you were to forget while loops all together, and call
vsync() before you blit the screen?? Am i right in thinking that all frames will be set to a concrete time length, no matter how fast the logic etc. is done on any specific frame? I know it wont be able to run at a variable speed, but it gets rid of the while loop right?

gnolam

vsync() timing == <u>EVIL</u> >:(
It won't give you the same speed on all computers. If you want to know how to make your game's speed hardware independant, check out the Allegro faq (in your allegro/docs folder, or online) under "How can I make my game run at the same speed on any computer?".

Thread #271030. Printed from Allegro.cc