How to press more than one key at the same time on Allegro 5?
Rederick Deathwill

I've posted my code and the question in details on Stack Overflow.

http://stackoverflow.com/questions/30066991/how-to-press-multiple-keys-at-the-same-time-using-events-in-real-time-allegro

I've tried al_wait_for_event(), I've tried al_get_keyboard_state(), I've even tried to create multiple event_queues and events. Still, when I press one arrow to move my image, and then I press another arrow, the image STOPS for a while, and when I press UP (for example), and keep holding it, and then I press LEFT (for example), and then I release LEFT while still holding UP, UP is down but the player stops.

I want to move my "character" in "real-time", without any key canceling each other. I've already stored the "states" manually in a vector of booleans (As you can see in my code), and it does not work.

Do you guys can explain me why this happens?

beoran

This is definitely possible, however, it requires you to think in terms of how event-based programming work. Also, your code is a bit "overwrought", tat is too complex for what you need to do.

There's normally no need to keep the key state yourself. In stead, you should keep track of the position and speed of the player.

What you want to do is, when you get a ALLEGRO_EVENT_KEY_DOWN, immediately set the speed of the player depending on the key pressed. When you get an ALLEGRO_EVENT_KEY_UP, modify the speed again accordingly. Both the speed and the position should be modeled as mathematical 2D vectors. (Not vector from C++, that's actually a badly named dynamic array).

Personally, seeing your code, I also think you should learn how to program in plain C before trying C++. C has much less features and forces you to think of simpler, more to the point solutions. Below are some ideas on how to do it in plain C. Untested code, may not compile, needs to be edited to integrate it in your program.

#SelectExpand
1struct Vec2d { float x; float y; }; 2typedef struct Vec2d Vec2d; 3 4struct Player { ALLEGRO_BITMAP * bitmap; Vec2d position; Vec2d speed; }; 5typedef struct Player Player; 6 7#define PLAYER_SPEED 5 8 9int player_on_key_up(Player * player, ALLEGRO_EVENT * event) { 10 switch (event.keyboard.keycode) { 11 case ALLEGRO_KEY_UP: player->speed.y = 0; return 1; 12 case ALLEGRO_KEY_DOWN: player->speed.y = 0; return 2; 13 case ALLEGRO_KEY_LEFT: player->speed.x = 0; return 3; 14 case ALLEGRO_KEY_RIGHT: player->speed.x = 0; return 4; 15 default: return 0; 16 } 17} 18 19int player_on_key_down(Player * player, ALLEGRO_EVENT * event) { 20 switch (event.keyboard.keycode) { 21 case ALLEGRO_KEY_UP: player->speed.y = -PLAYER_SPEED; return 1; 22 case ALLEGRO_KEY_DOWN: player->speed.y = PLAYER_SPEED; return 2; 23 case ALLEGRO_KEY_LEFT: player->speed.x = -PLAYER_SPEED; return 3; 24 case ALLEGRO_KEY_RIGHT: player->speed.x = PLAYER_SPEED; return 4; 25 default: return 0; 26 } 27} 28 29int player_on_event(Player * player, ALLEGRO_EVENT * event) { 30 switch(event.type) { 31 case ALLEGRO_EVENT_KEY_DOWN: return player_on_key_down(player, event); 32 case ALLEGRO_EVENT_KEY_UP: return player_on_key_up(player, event); 33 default: return 0; 34 } 35} 36 37void player_update(Player * player, float dt) { 38 float new_x = player->position.x + player->speed.x * dt; 39 float new_y = player->position.y + player->speed.y * dt; 40 player->position.x = new_x; 41 player->position.y = new_y; 42} 43 44void player_draw(Player * player, float dt) { 45 al_draw_bitmap(player->bitmap, player->position.x, player->position.y, 0); 46}

Audric

al_wait_for_event() waits until an event is triggered. In your case, the only reason it's not permanently "stuck" is the keyboard repetition: press and hold a key, after 500ms you start getting more keyboard events every 100ms. (these are typical delays)

You should not rely on keyboard repetition to make your game run.
See this example:
https://www.allegro.cc/forums/thread/613484

This adds a timer as a source of event. From this point on, every 16ms (60 times per second), Allegro triggers a custom timer event. Now notice this pattern:

#SelectExpand
1while (!DoExit) 2 { 3 ALLEGRO_EVENT Event; 4 al_wait_for_event(EventQueue, &Event); 5 if(Event.type == ALLEGRO_EVENT_TIMER) 6 { 7 // Perform the logic for the current "step" (every 1/60s) 8 if(KeyPresses[UP]) 9 { 10 // logic for current step, if the UP control is currently pressed 11 } 12 Redraw = true; 13 } 14 else if (Event.type == ALLEGRO_EVENT_KEY_DOWN) 15 { 16 // update the controller state for the right key, ex: 17 KeyPresses[UP] = true; 18 } 19 else if (Event.type == ALLEGRO_EVENT_KEY_UP) 20 { 21 // update the controller state for the right key, ex: 22 KeyPresses[UP] = false; 23 } 24 25 if(Redraw && al_is_event_queue_empty(EventQueue)) 26 { 27 Redraw = false; 28 (...) 29 // redraw screen ! 30 } 31 }

anto80

I'm using this code in Allegro 5.0.10.
I'm not using events.

// in your initialization:
ALLEGRO_KEYBOARD_STATE _keyboard_state;
al_get_keyboard_state(&_keyboard_state); // call this only once every frame

// in your loop:
if (al_key_down(&_keyboard_state, ALLEGRO_KEY_LCTRL)
    && al_key_down(&_keyboard_state, ALLEGRO_KEY_SPACE)
    && !al_key_down(&_keyboard_state, ALLEGRO_KEY_ALT))
{
    // LCTRL + SPACE are used, without using ALT
}

Rederick Deathwill

Thank you very much guys! Now I understand that I have to use a timer as a source.

Audric said:


You should not rely on keyboard repetition to make your game run.

I've started using it like this (Timer), and now it works like a charm. It wasn't that obvious when I started reading the Allegro Reference some 3 days ago (Well, probably something similar would solve a similar issue I was having on SDL 2 as well).

beoran said:


Personally, seeing your code, I also think you should learn how to program in plain C before trying C++. C has much less features and forces you to think of simpler, more to the point solutions. Below are some ideas on how to do it in plain C. Untested code, may not compile, needs to be edited to integrate it in your program.

Well, I come from Python, so it's really hard for me not to consider the high-level features of C++ (Especially because these features were one of major reasons why I've started to devote myself more to C++ instead of Python (The other one, is that there's no major port like Pygame to Allegro for Python, and Pygame uses SDL 1.2 instead 2.0)).

Elias

The other one, is that there's no major port like Pygame to Allegro for Python

Allegro 5 comes with Python bindings. (Not fully packaged though, you need to specify the path to the allegro DLL from python.)

beoran

Well then, in your case, I'd recommend you try to use use the Python bindings in stead of C++. Python gives you the advantages of a real high level language without the complexities and low level details of C++.

Thread #615345. Printed from Allegro.cc