简体   繁体   English

为什么当我 hover cursor 在快板的 x 轴上从 0 到 100 区域时程序突然关闭

[英]Why the program suddenly closes when I hover the cursor in area from 0 to 100 on x axis in allegro

I'm new in allegro and trying to make a small, very basic painting program.我是 allegro 的新手,正在尝试制作一个非常基本的小型绘画程序。 I want this program to stop painting when in the area from A(0, 0) to B(100, 600) on 800x600 plane.我希望这个程序在 800x600 平面上从 A(0, 0) 到 B(100, 600) 的区域中停止绘画。 When I hover my cursor in this area the program suddenly closes itself.当我 hover 我的 cursor 在这个区域时,程序突然自行关闭。 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:我发现每当我 hover 在从 (0, 0) 到 (100, 600) 的那个区域中执行这个 if 语句时:

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 :让我们看看ALLEGRO_EVENT event是什么,通过文档

An ALLEGRO_EVENT is a union of all builtin event structures, ie it is an object large enough to hold the data of any event type. ALLEGRO_EVENT是所有内置事件结构的联合,即它是一个足够大的 object 以容纳任何事件类型的数据。 All events have the following fields in common:所有事件都具有以下共同字段:

type ( ALLEGRO_EVENT_TYPE ) typeALLEGRO_EVENT_TYPE

Indicates the type of event.表示事件的类型。

[...] [...]

By examining the type field you can then access type-specific fields通过检查type字段,您可以访问特定于类型的字段

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.如果event.type不是键盘事件,则不能执行访问event.keyboard成员的操作,因为那时您正在从非活动的联合成员中读取。 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. UB 导致的结果毫无意义,但似乎在这种情况下,它们与坐标相关,使您的代码认为 Esc 被按下。

Check you have a keyboard event type before reading the keyboard members:在阅读keyboard成员之前检查您是否有键盘事件type

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.在使用union的任何地方都需要非常小心,以了解任何成员在读取时都是有效的。 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.一种更好的方法是std::variant ,它可以让您检查当前持有的类型,或者,如果转换为它,则如果它不持有则抛出。 Of course, you can't use that here, unless someone creates a wrapper for ALLEGRO_EVENT - which you might have time for!当然,你不能在这里使用它,除非有人为ALLEGRO_EVENT创建了一个包装器——你可能有时间! - but I mention it to replace union s in your own code. - 但我提到它是为了替换您自己代码中的union

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM