[英]Why the program suddenly closes when I hover the cursor in area from 0 to 100 on x axis in allegro
我是 allegro 的新手,正在嘗試制作一個非常基本的小型繪畫程序。 我希望這個程序在 800x600 平面上從 A(0, 0) 到 B(100, 600) 的區域中停止繪畫。 當我 hover 我的 cursor 在這個區域時,程序突然自行關閉。 這是代碼:
#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;
}
編輯:
我發現每當我 hover 在從 (0, 0) 到 (100, 600) 的那個區域中執行這個 if 語句時:
if (event.keyboard.keycode == ALLEGRO_KEY_ESCAPE)
我不知道它為什么會執行。
讓我們看看ALLEGRO_EVENT event
是什么,通過文檔:
ALLEGRO_EVENT
是所有內置事件結構的聯合,即它是一個足夠大的 object 以容納任何事件類型的數據。 所有事件都具有以下共同字段:
type
(ALLEGRO_EVENT_TYPE
)表示事件的類型。
[...]
通過檢查
type
字段,您可以訪問特定於類型的字段
如果event.type
不是鍵盤事件,則不能執行訪問event.keyboard
成員的操作,因為那時您正在從非活動的聯合成員中讀取。 那是未定義的行為,所以推測不是很有用 - 但在這種情況下,看起來你讀取了一些鼠標坐標,就好像它是一個鍵一樣,但事實並非如此。 UB 導致的結果毫無意義,但似乎在這種情況下,它們與坐標相關,使您的代碼認為 Esc 被按下。
在閱讀keyboard
成員之前檢查您是否有鍵盤事件type
:
if (event.type == ALLEGRO_EVENT_KEY_DOWN &&
event.keyboard.keycode == ALLEGRO_KEY_ESCAPE)
{
game_over = true;
}
在使用union
的任何地方都需要非常小心,以了解任何成員在讀取時都是有效的。 唯一真正確定的方法是用類型標記它 - 甚至這要求你記得先檢查類型!
一種更好的方法是std::variant
,它可以讓您檢查當前持有的類型,或者,如果轉換為它,則如果它不持有則拋出。 當然,你不能在這里使用它,除非有人為ALLEGRO_EVENT
創建了一個包裝器——你可能有時間! - 但我提到它是為了替換您自己代碼中的union
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.