Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Key Delay And Turn-Based Movement

This thread is locked; no one can reply to it. rss feed Print
Key Delay And Turn-Based Movement
Gatleos
Member #12,534
January 2011

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
Major Reynaldo
May 2007
avatar

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
Member #2,030
March 2002
avatar

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

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

Gatleos
Member #12,534
January 2011

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

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

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
Member #12,534
January 2011

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
Major Reynaldo
May 2007
avatar

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
Member #12,534
January 2011

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
Member #476
June 2000
avatar

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.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Thomas Fjellstrom
Member #476
June 2000
avatar

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...

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Go to: