Key Delay And Turn-Based Movement
Gatleos

Before I start working with real-time sprite movement and timers, I decided to try something turn-based. So I programmed a simple set of functions to draw ASCII characters to the screen and am building a roguelike engine. But the main problem I keep running into is getting keyboard input. I can collect it just fine, the problem is that it's collected way too fast. Even tapping the key as lightly as possible detects two events at once! Is there a simple way to delay detection of key events?

Current game loop (The Draw functions near the bottom blit ASCII characters to the screen):

#SelectExpand
1while(game_is_running) 2{ 3al_wait_for_event(event_queue, &ev); 4//if(ev.type == ALLEGRO_EVENT_TIMER) 5if(key[KEY_DOWN]) 6{ 7//Game.y++; 8turn++; 9y++; 10} 11if(key[KEY_UP]) 12{ 13//Game.y--; 14turn++; 15y--; 16} 17if(key[KEY_LEFT]) 18{ 19//Game.x--; 20turn++; 21x--; 22} 23if(key[KEY_RIGHT]) 24{ 25//Game.x++; 26turn++; 27x++; 28} 29redraw = true; 30if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) 31{ 32break; 33} 34else if(ev.type == ALLEGRO_EVENT_KEY_DOWN) 35{ 36 switch(ev.keyboard.keycode) { 37 case ALLEGRO_KEY_UP: 38 key[KEY_UP] = true; 39 break; 40 41 case ALLEGRO_KEY_DOWN: 42 key[KEY_DOWN] = true; 43 break; 44 45 case ALLEGRO_KEY_LEFT: 46 key[KEY_LEFT] = true; 47 break; 48 49 case ALLEGRO_KEY_RIGHT: 50 key[KEY_RIGHT] = true; 51 break; 52 } 53} 54 else if(ev.type == ALLEGRO_EVENT_KEY_UP) { 55 switch(ev.keyboard.keycode) { 56 case ALLEGRO_KEY_UP: 57 key[KEY_UP] = false; 58 break; 59 60 case ALLEGRO_KEY_DOWN: 61 key[KEY_DOWN] = false; 62 break; 63 64 case ALLEGRO_KEY_LEFT: 65 key[KEY_LEFT] = false; 66 break; 67 68 case ALLEGRO_KEY_RIGHT: 69 key[KEY_RIGHT] = false; 70 break; 71 72 case ALLEGRO_KEY_ESCAPE: 73 game_is_running = false; 74 break; 75 } 76} 77if(redraw && al_is_event_queue_empty(event_queue)) 78{ 79redraw = false; 80 81al_clear_to_color(al_map_rgb(0,0,0)); 82Win_Fill(46,Game,"green","black"); 83Draw_Char(1,Game,x,y); 84//Draw_Str("Main Deck, Sector 7",Game,0,0,"white","blue",0); 85Win_Box(Game,219,"darkgrey","blue"); 86Win_Box(Info,219,"darkgrey","blue"); 87Win_Box(Message,219,"green","blue"); 88itoa(turn,yis,10); 89Draw_Str("Turn:",Info,0,0,0); 90Draw_Str(yis,Info,5,0,0); 91//Win_FillRand(Game); 92al_flip_display(); 93}

Edgar Reynaldo

It's not your fault, but I'm so tired of seeing people struggle with getting key input. Allegro 4 should have higher level input functions. You're welcome to use my keyboard_handler.

It's use is simple. Call SetupKeyHandler() near the beginning of your program. In your logic loop, call UpdateKeyHandler(time_passed), and then use :

if (key_press(KEY_DOWN)) {
   do_stuff();
}

It also has support for key release, key holds, keys open, key double clicks, and key_held_for(duration) as well as extending allegro's key codes to support various combinations of SHIFT, CTRL, and ALT.

gnolam

[EDIT]
Didn't see that the OP was using Allegro 5.

Gatleos

Looks great! Where is KEY_MAX defined, though? I keep getting undefined errors.

Edgar Reynaldo

You confused me. Without scrolling down to see the rest of your code I thought you were using Allegro 4 because you are checking if (key[KEY_DOWN]) {/*...*/}. Now that I look further down, you are using Allegro 5 and are trying to emulate A4 with it. My keyboard_handler is for Allegro 4 only at this point.

So now, my advice is to drop use of your key array, and simply use the key press and release events that Allegro 5 provides for you. Ie... move the code for if (key[KEY_*]) {DoStuff();} into

else if(ev.type == ALLEGRO_EVENT_KEY_DOWN)
{
         switch(ev.keyboard.keycode) {
            case ALLEGRO_KEY_UP:
//               key[KEY_UP] = true;
DoStuff();
break;

The problem is that an entry from your key array will be true for several logic loops at a time. It takes at least a certain amount of time between key press and key release.

Gatleos

Someone really needs to update that input tutorial if it's using jury-rigged code like that. It works much better now. One more question: what about key holds, double-taps, etc.? Is there a separate event for that or will I just have to make them myself?

Edgar Reynaldo
Gatleos said:

Someone really needs to update that input tutorial if it's using jury-rigged code like that.

What input tutorial? What's the link to it?

Gatleos said:

One more question: what about key holds, double-taps, etc.? Is there a separate event for that or will I just have to make them myself?

There aren't any separate events for those, you'll have to track the state yourself. If you got a key down event, but haven't received a key up event then you have a key hold. For double clicks, you'll have to track the time of the last key down event and compare it to the time of the new key down event that matches it.

Gatleos

This one on the wiki.

Anyway, thanks for the help! Keyboard input is a lot easier than it seemed with that odd emulation of Allegro 4 the tutorial was trying to pull off.

Thomas Fjellstrom
Gatleos said:

Someone really needs to update that input tutorial if it's using jury-rigged code like that.

The code there is really only for really basic input needs. Something that only needs to know if a key is pressed at any given time. Trying to show something more complex would probably just confuse things more.

I'm open to a second Keyboard tutorial showing more advanced concepts though.

Edgar Reynaldo

Yes, it's odd that the Allegro 5 Input Tutorial uses a key array instead of checking the key state with the Allegro 5 functions al_get_keyboard_state and al_key_down.

Thomas Fjellstrom

Yes, it's odd that the Allegro 5 Input Tutorial uses a key array instead of checking the key state with the Allegro 5 functions al_get_keyboard_state and al_key_down.

Not really. The keystate stuff is a dirty hack, imo worse than storing your own key array. Also its far less efficient. The tutorial only stores keys it needs, where as the keystate stuff stores all of them regardless. and copies them...

Thread #606288. Printed from Allegro.cc