0

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.

  • Is any error logged to console? Have you tried running it under a debugger to get more info on where/how it fails? – underscore_d Jul 22 '20 at 14:42
  • There are no errors in the code it compiles and runs successfully as long as I dont hover the cursor over the area [from (0, 0) to (100, 600)] it works fine. Hovering over that area causes program to close suddenly. – Mr. Developer Jul 23 '20 at 10:25
  • I meant any error at runtime, if you run the program from a terminal. That also doesn't answer whether you tried running it under a debugger to get more info on where/how it closes suddenly – underscore_d Jul 23 '20 at 10:41
  • Yes I ran it under a debugger and it gives me no errors. There are no errors at runtime – Mr. Developer Jul 25 '20 at 09:45

1 Answers1

1

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 unions in your own code.

underscore_d
  • 6,309
  • 3
  • 38
  • 64