I'm new in allegro and trying to make a small, very basic painting program. I want this program to stop painting when in the area from A(0, 0) to B(100, 600) on 800x600 plane. When I hover my cursor in this area the program suddenly closes itself. Here is the code:
#include <allegro5/allegro.h>
#include <allegro5/allegro_native_dialog.h>
#include <allegro5/allegro_primitives.h>
#define screen_width 800
#define screen_height 600
int main()
{
al_init();
ALLEGRO_DISPLAY* display = al_create_display(screen_width, screen_height);
al_install_mouse();
al_install_keyboard();
al_init_primitives_addon();
ALLEGRO_EVENT_QUEUE* event_que = al_create_event_queue();
al_register_event_source(event_que, al_get_display_event_source(display));
al_register_event_source(event_que, al_get_keyboard_event_source());
al_register_event_source(event_que, al_get_mouse_event_source());
bool game_over = false, hold = false;
int x = 10, y = 10;
while (!game_over){
ALLEGRO_EVENT event;
al_wait_for_event(event_que, &event);
if (event.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN){
hold = true;
}
if (event.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP){
hold = false;
}
if (event.keyboard.keycode == ALLEGRO_KEY_ESCAPE){
game_over = true;
}
if (hold){
x = event.mouse.x;
y = event.mouse.y;
if (x > 100){
al_draw_filled_circle(x, y, 4, al_map_rgb(210, 0, 0));
}
}
al_flip_display();
}
al_destroy_event_queue(event_que);
al_destroy_display(display);
return 0;
}
Edit:
I've found that whenever i hover in that area from (0, 0) to (100, 600) this if statement is being executed:
if (event.keyboard.keycode == ALLEGRO_KEY_ESCAPE)
I don't know why it is executing.
Let's look at what ALLEGRO_EVENT event
is, via the docs:
An
ALLEGRO_EVENT
is a union of all builtin event structures, i.e. it is an object large enough to hold the data of any event type. All events have the following fields in common:
type
(ALLEGRO_EVENT_TYPE
)Indicates the type of event.
[...]
By examining the
type
field you can then access type-specific fields
You can't do stuff that accesses event.keyboard
members if the event.type
is not a keyboard event, because then you're reading from an inactive union member. That is undefined behaviour, so speculation is not very useful - but in this case, it looks like you read some bit of a mouse coordinate as if it were a key, but it's not. Results due to UB are meaningless, but it seems that, in this case, they correlated with coordinates to make your code think Esc was pressed.
Check you have a keyboard event type
before reading the keyboard
members:
if (event.type == ALLEGRO_EVENT_KEY_DOWN &&
event.keyboard.keycode == ALLEGRO_KEY_ESCAPE)
{
game_over = true;
}
You need to be extremely careful, anywhere you use a union
, to know any member is valid when you read from it. About the only real way to be sure is to tag it with a type - and even that requires that you remember to check the type first!
A superior way is std::variant
, which lets you check the currently held type or, if casting to it, throws if it doesn't hold that. Of course, you can't use that here, unless someone creates a wrapper for ALLEGRO_EVENT
- which you might have time for! - but I mention it to replace union
s in your own code.