![]() |
|
ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY fired outside edge of display |
OnlineCop
Member #7,919
October 2006
![]() |
Setup: Allegro 5.2.2.1 installed into Visual Studio 2015 via NuGet: https://www.nuget.org/packages/Allegro/ an a 64-bit Windows 7. TL;DR I believe that ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY is being incorrectly fired while the mouse is outside the window but is moving over its edge. I extended the tutorial code from https://wiki.allegro.cc/index.php?title=Allegro_5_Tutorial/Input to include both mouse-enter and mouse-leave functionality. Essentially, the bouncer will bounce from wall to wall while no mouse is over the window: When the mouse is inside the window, the ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY event is called, and the bouncer follows the mouse and its position is displayed on the 2nd line: Moving the mouse back off the window fires the ALLEGRO_EVENT_MOUSE_LEAVE_DISPLAY event, which allows the bouncer to wall-bounce again. Around the edge of the window is a 5-pixel "resize" edge. My screen is 800x600, and if my mouse is exactly x=800, ALLEGRO_EVENT_MOUSE_LEAVE_DISPLAY is fired. If my mouse moves anywhere between x=801 to x=805, the ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY event is fired a second time. But moving my mouse totally off the window (x=806 and further), no ALLEGRO_EVENT_MOUSE_LEAVE_DISPLAY is called a second time, meaning that my mouse is still "holding" the bouncer in place. 1#include <allegro5/allegro.h>
2#include <allegro5/allegro_font.h>
3#include <iostream>
4#include <string>
5#include <sstream>
6
7int InitializeAllegro(ALLEGRO_DISPLAY*&, ALLEGRO_FONT*&, ALLEGRO_TIMER*&, ALLEGRO_EVENT_QUEUE*&);
8
9const double FPS = 60.0;
10const int SCREEN_W = 800;
11const int SCREEN_H = 600;
12
13template<typename T>
14class TVector2
15{
16public:
17 TVector2() : x(T()), y(T()) {}
18 TVector2(T InX, T InY) : x(InX), y(InY) {}
19
20 TVector2 operator+=(const TVector2& other)
21 {
22 x += other.x;
23 y += other.y;
24 return *this;
25 }
26
27 T x;
28 T y;
29};
30
31class FBouncer
32{
33public:
34 FBouncer(const int Width, const int Height, const float StartingX, const float StartingY)
35 : _size(TVector2<int>(Width, Height))
36 , _position(TVector2<float>(StartingX - Width/2.0, StartingY - Height/2.0))
37 , _bitmap(nullptr)
38 , _bIsControlled(false)
39 { }
40
41 ~FBouncer()
42 {
43 al_destroy_bitmap(_bitmap);
44 _bitmap = nullptr;
45 }
46
47 TVector2<int> GetSize() const { return _size; }
48 TVector2<float> GetPosition() const { return _position; }
49 TVector2<float> GetDirection() const { return _direction; }
50 ALLEGRO_BITMAP* GetBitmap() { return _bitmap; }
51
52 void SetPosition(const TVector2<float>& InPosition)
53 {
54 _position.x = InPosition.x;
55 _position.y = InPosition.y;
56 }
57
58 void SetPositionCentered(const TVector2<float>& InPosition)
59 {
60 _position.x = InPosition.x - _size.x / 2.0;
61 _position.y = InPosition.y - _size.y / 2.0;
62 }
63
64 void SetDirection(const TVector2<float>& InDirection)
65 {
66 _direction.x = InDirection.x;
67 _direction.y = InDirection.y;
68 }
69
70 void SetControlled(bool bIsControlled)
71 {
72 if (_bIsControlled != bIsControlled)
73 {
74 _bIsControlled = bIsControlled;
75 }
76 }
77
78 void Move()
79 {
80 if (!_bIsControlled)
81 {
82 _position.x += _direction.x;
83 _position.y += _direction.y;
84 }
85 }
86
87 int Init(ALLEGRO_BITMAP* CurrentTargetBitmap)
88 {
89 _bitmap = al_create_bitmap(32, 32);
90 if (_bitmap == nullptr)
91 {
92 std::cout << "FBouncer is unable to create ALLEGRO_BITMAP." << std::endl;
93 return 1;
94 }
95
96 al_set_target_bitmap(_bitmap);
97 al_clear_to_color(al_map_rgb(255, 0, 255));
98 al_set_target_bitmap(CurrentTargetBitmap);
99
100 return 0;
101 }
102
103protected:
104 TVector2<int> _size;
105 TVector2<float> _position;
106 TVector2<float> _direction;
107 ALLEGRO_BITMAP* _bitmap;
108 bool _bIsControlled;
109};
110
111
112int main(int argc, char** argv)
113{
114 ALLEGRO_DISPLAY* display = nullptr;
115 ALLEGRO_FONT* font = nullptr;
116 ALLEGRO_TIMER* timer = nullptr;
117 ALLEGRO_EVENT_QUEUE* event_queue = nullptr;
118
119 int init_error = InitializeAllegro(display, font, timer, event_queue);
120 if (init_error != 0)
121 {
122 if (init_error <= -3)
123 {
124 al_destroy_display(display);
125 }
126 if (init_error <= -4)
127 {
128 al_destroy_font(font);
129 }
130 if (init_error <= -5)
131 {
132 al_destroy_timer(timer);
133 }
134 if (init_error <= -6)
135 {
136 al_destroy_event_queue(event_queue);
137 }
138 return init_error;
139 }
140
141 FBouncer bouncer(32, 32, SCREEN_W / 2, SCREEN_H / 2);
142 bouncer.SetDirection(TVector2<float>(-4.0, 4.0));
143 bouncer.Init(al_get_backbuffer(display));
144
145 al_register_event_source(event_queue, al_get_display_event_source(display));
146 al_register_event_source(event_queue, al_get_timer_event_source(timer));
147 al_register_event_source(event_queue, al_get_mouse_event_source());
148
149 al_clear_to_color(al_map_rgb(0, 0, 0));
150 al_flip_display();
151
152 al_start_timer(timer);
153
154 std::string mouse_pos_msg("");
155
156 bool b_needs_redraw = false;
157 while (1)
158 {
159 ALLEGRO_EVENT event;
160 al_wait_for_event(event_queue, &event);
161
162 if (event.type == ALLEGRO_EVENT_TIMER)
163 {
164 // Game logic goes in here
165
166 TVector2<float> direction = bouncer.GetDirection();
167 TVector2<float> current_pos = bouncer.GetPosition();
168
169 if ((current_pos.x < 0 && direction.x < 0) ||
170 (current_pos.x > SCREEN_W - bouncer.GetSize().x && direction.x > 0))
171 {
172 direction.x = -direction.x;
173 }
174
175 if ((current_pos.y < 0 && direction.y < 0) ||
176 (current_pos.y > SCREEN_H - bouncer.GetSize().y && direction.y > 0))
177 {
178 direction.y = -direction.y;
179 }
180
181 bouncer.SetDirection(direction);
182 bouncer.Move();
183 b_needs_redraw = true;
184 }
185 else if (event.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
186 {
187 break;
188 }
189 else if (event.type == ALLEGRO_EVENT_MOUSE_AXES ||
190 event.type == ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY)
191 {
192 bouncer.SetControlled(true);
193 TVector2<float> mouse_pos(event.mouse.x, event.mouse.y);
194 bouncer.SetPositionCentered(mouse_pos);
195 std::stringstream ss("Pos: ");
196 ss << event.mouse.x << "," << event.mouse.y;
197 mouse_pos_msg = ss.str();
198 }
199 else if (event.type == ALLEGRO_EVENT_MOUSE_LEAVE_DISPLAY)
200 {
201 bouncer.SetControlled(false);
202 mouse_pos_msg = "";
203 }
204 else if (event.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP)
205 {
206 break;
207 }
208
209 if (b_needs_redraw && al_is_event_queue_empty(event_queue))
210 {
211 // Redraw logic goes in here
212
213 al_clear_to_color(al_map_rgb(0, 0, 0));
214
215 al_draw_text(font, al_map_rgb(255, 255, 255), 400, 300, ALLEGRO_ALIGN_CENTER, "Welcome to Allegro 5!");
216 al_draw_text(font, al_map_rgb(255, 255, 255), 400, 300 + al_get_font_line_height(font), ALLEGRO_ALIGN_CENTER, mouse_pos_msg.c_str());
217 for (int i = 1; i < argc; i++)
218 {
219 std::cout << "argv[" << i << "] = " << argv[i] << std::endl;
220 al_draw_text(font, al_map_rgb(255, 255, 255), 400, 300 + i * al_get_font_line_height(font), ALLEGRO_ALIGN_CENTER, argv[i]);
221 }
222
223 al_draw_bitmap(bouncer.GetBitmap(), bouncer.GetPosition().x, bouncer.GetPosition().y, 0);
224
225 al_flip_display();
226
227 b_needs_redraw = false;
228 }
229 }
230
231 al_destroy_timer(timer);
232 al_destroy_event_queue(event_queue);
233 al_destroy_font(font);
234 al_destroy_display(display);
235
236 return 0;
237}
238
239
240int InitializeAllegro(ALLEGRO_DISPLAY*& display, ALLEGRO_FONT*& font, ALLEGRO_TIMER*& timer, ALLEGRO_EVENT_QUEUE*& queue)
241{
242 if (!al_init())
243 {
244 std::cout << "Unable to initialize Allegro 5. Shutting down." << std::endl;
245 return -1;
246 }
247
248 // Call all al_init_*_addon() before other functions.
249 al_init_font_addon();
250
251 if (!al_install_mouse())
252 {
253 std::cout << "Unable to install the mouse. Shutting down." << std::endl;
254 return -2;
255 }
256
257 display = al_create_display(SCREEN_W, SCREEN_H);
258 if (display == nullptr)
259 {
260 std::cout << "Unable to create ALLEGRO_DISPLAY. Shutting down." << std::endl;
261 return -3;
262 }
263
264 font = al_create_builtin_font();
265 if (font == nullptr)
266 {
267 std::cout << "Unable to create ALLEGRO_FONT. Shutting down." << std::endl;
268 return -4;
269 }
270
271 timer = al_create_timer(1.0 / FPS);
272 if (timer == nullptr)
273 {
274 std::cout << "Unable to create ALLEGRO_TIMER. Shutting down." << std::endl;
275 return -5;
276 }
277
278 queue = al_create_event_queue();
279 if (queue == nullptr)
280 {
281 std::cout << "Unable to create ALLEGRO_EVENT_QUEUE. Shutting down." << std::endl;
282 return -6;
283 }
284
285 return 0;
286}
Is this an engine issue, or should I deal with this in code and "simulate" a second ALLEGRO_EVENT_MOUSE_LEAVE_DISPLAY event by detecting the actual mouse position in relation to the screen's dimensions? EDIT: 189 else if (event.type == ALLEGRO_EVENT_MOUSE_AXES ||
190 event.type == ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY)
191 {
192 if (event.mouse.x < 0 || event.mouse.x > SCREEN_W ||
193 event.mouse.y < 0 || event.mouse.y > SCREEN_H)
194 {
195 // Ignore it
196 continue;
197 }
198 bouncer.SetControlled(true);
199 TVector2<float> mouse_pos(event.mouse.x, event.mouse.y);
200 bouncer.SetPositionCentered(mouse_pos);
201 std::stringstream ss("Pos: ");
202 ss << event.mouse.x << "," << event.mouse.y;
203 mouse_pos_msg = ss.str();
204 }
|
SiegeLord
Member #7,827
October 2006
![]() |
Bumping so it doesn't get locked. Haven't had time to look at this yet. "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
Neil Roy
Member #2,229
April 2002
![]() |
Part of the problem I see is this code current_pos.x > SCREEN_W. The right edge of the screen is SCREEN_W-1, not SCREEN_W. You should have something like current_pos.x >= SCREEN_W. I haven't examined your code too thuroughly, but that stood out for me. The screen goes from zero to SCREEN_W-1 in the X direction and zero to SCREEN_H-1 in the Y. In this case your screen goes from zero to 799 in the X, and zero to 599 in the Y. If you're testing to see if it is greater than 800, than what happens if it is on 800 in the X, or on 600 in the Y? --- |
OnlineCop
Member #7,919
October 2006
![]() |
Changing > SCREEN_W to >= SCREEN_W changes nothing about the issue with the allegro event being fired: all it does is make the cube bounce one pixel sooner. The mouse still fires off the ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY event when it moves over the window edge. Under the Windows 7 Control Panel: Control Panel\All Control Panel Items\Personalization I changed to another theme which had about a 2-pixel-thick window border. This event is NOT fired when I move around that border. The default Windows 7 theme (Aero), however, does have this 5-pixel-thick border. I tried to write this sample code above as platform-agnostic as possible so it could be tested on other systems (Linux, OS X, ...) to rule out whether this was platform and/or theme specific.
|
Neil Roy
Member #2,229
April 2002
![]() |
OnlineCop said: The mouse still fires off the ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY event when it moves over the window edge. Have you tried the example programs to see if they do the same thing? ex_mouse_focus.exe is a good test, it reports when the mouse goes outside the display and seems to work no problem for me. It only reports when the mouse is over the actual display and not the border. Also ex_mouse_events.exe also accurately reports the mouse outside the display. Edit: I noticed in this section of code a potential problem... else if (event.type == ALLEGRO_EVENT_MOUSE_AXES || event.type == ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY) { ...the ball will be mouse controlled under two conditions, entering the display OR ALLEGRO_EVENT_MOUSE_AXES triggers. So, is the mouse axes still firing while the mouse is outside the display? I would think so. --- |
OnlineCop
Member #7,919
October 2006
![]() |
ex_mouse_focus.exe turns from black to red when the mouse is over it. When the mouse is over that 5-pixel window edge, it displays "Outside either display", which is repeated as I drag my mouse around it. When I move completely off the window, all text output stops; when I move into the window, it becomes red and the console shows the "In display 1, x = ..., y = ..." properly. ex_mouse_events.exe only updates the mouse coordinates while over the window: it doesn't update anything while I drag over the window edges. I can separate the ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY from the ALLEGRO_EVENT_MOUSE_AXES events, although I probably need to detect on launch whether the mouse is already over the window, else the ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY event will not get initially fired. EDIT: I wasn't able to properly detect whether the mouse was over the window when the display is created, so a work-around had to be used instead. I introduced a b_mouse_in_window and check it, as well as whether the bouncer is controlled, when event.type == ALLEGRO_EVENT_MOUSE_AXES. I update that value when either event.type == ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY or event.type == ALLEGRO_EVENT_MOUSE_LEAVE_DISPLAY. That seems to get rid of the problem with the window borders. Code below if anyone wanted to see the changes to the events. 1#include <allegro5/allegro.h>
2#include <allegro5/allegro_font.h>
3#include <iostream>
4#include <string>
5#include <sstream>
6
7int main(int argc, char ** argv);
8
9/** Initialize all Allegro 5 stuff. Returns 0 on success, or a negative value on error. */
10int AllegroInit(ALLEGRO_DISPLAY*& display, ALLEGRO_FONT*& font, ALLEGRO_TIMER*& timer, ALLEGRO_EVENT_QUEUE*& queue);
11/** Shut down all Allegro 5 stuff. Usually, destroy them in opposite order they were initialized. */
12void AllegroDeinit(ALLEGRO_DISPLAY*& display, ALLEGRO_FONT*& font, ALLEGRO_TIMER*& timer, ALLEGRO_EVENT_QUEUE*& queue);
13
14const double FPS = 60.0;
15const int SCREEN_W = 800;
16const int SCREEN_H = 600;
17
18
19template<typename T>
20class TVector2
21{
22public:
23 TVector2() : x(T()), y(T()) {}
24 TVector2(T InX, T InY) : x(InX), y(InY) {}
25 TVector2(const TVector2<T>& other)
26 {
27 x = other.x;
28 y = other.y;
29 }
30
31 TVector2<T>& operator=(const TVector2<T>& other)
32 {
33 if (this != &other)
34 {
35 x = other.x;
36 y = other.y;
37 }
38 return *this;
39 }
40
41 TVector2<T> operator+=(const TVector2& other)
42 {
43 x += other.x;
44 y += other.y;
45 return *this;
46 }
47
48 TVector2<T> operator*(const float scalar) const
49 {
50 TVector2 VectorScalar(this->x * scalar, this->y * scalar);
51 return VectorScalar;
52 }
53
54 TVector2<T> operator+(const float scalar) const
55 {
56 TVector2<T> VectorScalar(this->x + scalar, this->y + scalar);
57 return VectorScalar;
58 }
59
60 TVector2<T> operator-(const float scalar) const
61 {
62 TVector2<T> VectorScalar(this->x - scalar, this->y - scalar);
63 return VectorScalar;
64 }
65
66 TVector2<T> operator+(const TVector2<T>& other) const
67 {
68 TVector2<T> Vector(this->x + other.x, this->y + other.y);
69 return Vector;
70 }
71
72 TVector2<T> operator-(const TVector2<T>& other) const
73 {
74 TVector2<T> Vector(this->x - other.x, this->y - other.y);
75 return Vector;
76 }
77
78 T x;
79 T y;
80};
81
82
83typedef TVector2<float> FVector2;
84
85
86class FBouncer
87{
88public:
89 FBouncer(const FVector2& Size, const FVector2& StartingPosition)
90 : _size(Size * 0.5f)
91 , _position(StartingPosition)
92 , _bitmap(nullptr)
93 , _bIsControlled(false)
94 { }
95
96 ~FBouncer()
97 {
98 al_destroy_bitmap(_bitmap);
99 _bitmap = nullptr;
100 }
101
102 FVector2 GetSize() const { return _size * 2.0f; }
103 FVector2 GetPosition() const { return _position; }
104 FVector2 GetDirection() const { return _direction; }
105 bool GetControlled() const { return _bIsControlled; }
106 ALLEGRO_BITMAP* GetBitmap() { return _bitmap; }
107
108 void SetPosition(const FVector2& InPosition)
109 {
110 _position = InPosition;
111 }
112
113 void SetDirection(const FVector2& InDirection)
114 {
115 _direction.x = InDirection.x;
116 _direction.y = InDirection.y;
117 }
118
119 void SetControlled(bool bIsControlled)
120 {
121 if (_bIsControlled != bIsControlled)
122 {
123 _bIsControlled = bIsControlled;
124 }
125 }
126
127 void Move()
128 {
129 if (!_bIsControlled)
130 {
131 _position.x += _direction.x;
132 _position.y += _direction.y;
133
134 // Check whether we need to bounce off the walls.
135 if (_position.x < _top_left_bounds.x)
136 {
137 _direction.x = -_direction.x;
138 _position.x += _top_left_bounds.x - _position.x;
139 }
140 else if (_position.x > _bottom_right_bounds.x)
141 {
142 _direction.x = -_direction.x;
143 _position.x += _bottom_right_bounds.x - _position.x;
144 }
145
146 if (_position.y < _top_left_bounds.y)
147 {
148 _direction.y = -_direction.y;
149 _position.y += _top_left_bounds.y - _position.y;
150 }
151 else if (_position.y > _bottom_right_bounds.y)
152 {
153 _direction.y = -_direction.y;
154 _position.y += _bottom_right_bounds.y - _position.y;
155 }
156 }
157 }
158
159 int Init(ALLEGRO_BITMAP* CurrentTargetBitmap, const FVector2& TopLeftBounds, const FVector2& BottomRightBounds)
160 {
161 _bitmap = al_create_bitmap(_size.x * 2.0f, _size.y * 2.0f);
162 if (_bitmap == nullptr)
163 {
164 std::cout << "FBouncer is unable to create ALLEGRO_BITMAP." << std::endl;
165 return 1;
166 }
167
168 al_set_target_bitmap(_bitmap);
169 al_clear_to_color(al_map_rgb(255, 0, 255));
170 al_draw_pixel(3.0f + 0.5f, 3.0f + 0.5f, al_map_rgb(0, 0, 255));
171 al_draw_pixel(3.0f + 0.5f, 4.0f + 0.5f, al_map_rgb(0, 0, 255));
172 al_draw_pixel(28.0f + 0.5f, 3.0f + 0.5f, al_map_rgb(0, 0, 255));
173 al_draw_pixel(28.0f + 0.5f, 4.0f + 0.5f, al_map_rgb(0, 0, 255));
174 al_set_target_bitmap(CurrentTargetBitmap);
175
176 // Adjusting the bounds instead of calculating x/y offsets from the center
177 // simplifies the math.
178 _top_left_bounds = TopLeftBounds + _size;
179 _bottom_right_bounds = BottomRightBounds - _size;
180
181 return 0;
182 }
183
184 void Draw()
185 {
186 al_draw_bitmap(_bitmap, _position.x - _size.x, _position.y - _size.y, 0);
187 }
188
189protected:
190 /* Size is actually 1/2 the size requested, since object origin is the center, not upper-left corner. */
191 FVector2 _size;
192 FVector2 _top_left_bounds;
193 FVector2 _bottom_right_bounds;
194 FVector2 _position;
195 FVector2 _direction;
196 bool _bIsControlled;
197 ALLEGRO_BITMAP* _bitmap;
198};
199
200
201/** Returns < 0 on Allegro init errors, > 0 on gameplay errors, or 0 on success. */
202int main(int argc, char** argv)
203{
204 ALLEGRO_DISPLAY* display = nullptr;
205 ALLEGRO_FONT* font = nullptr;
206 ALLEGRO_TIMER* timer = nullptr;
207 ALLEGRO_EVENT_QUEUE* event_queue = nullptr;
208
209 int init_error = AllegroInit(display, font, timer, event_queue);
210 if (init_error != 0)
211 {
212 AllegroDeinit(display, font, timer, event_queue);
213 return init_error;
214 }
215
216 al_register_event_source(event_queue, al_get_display_event_source(display));
217 al_register_event_source(event_queue, al_get_timer_event_source(timer));
218 al_register_event_source(event_queue, al_get_mouse_event_source());
219
220 al_clear_to_color(al_map_rgb(0, 0, 0));
221 al_flip_display();
222
223 al_start_timer(timer);
224
225 FBouncer* bouncer = new FBouncer(FVector2(32.0f, 32.0f), FVector2(SCREEN_W / 2, SCREEN_H / 2));
226 if (bouncer == nullptr)
227 {
228 AllegroDeinit(display, font, timer, event_queue);
229 std::cout << "Unable to create Bouncer. Shutting down." << std::endl;
230 return 1;
231 }
232 bouncer->SetDirection(FVector2(-4.0, 4.0));
233 bouncer->Init(al_get_backbuffer(display), FVector2(0, 0), FVector2(SCREEN_W, SCREEN_H));
234
235 std::string mouse_pos_msg("");
236
237 // HACK! Eww, eww, eww.
238 bool b_mouse_in_window = true;
239 bool b_needs_redraw = false;
240 while (1)
241 {
242 ALLEGRO_EVENT event;
243 al_wait_for_event(event_queue, &event);
244
245 if (event.type == ALLEGRO_EVENT_TIMER)
246 {
247 b_needs_redraw = true;
248
249 // Game logic goes here...
250 bouncer->Move();
251 }
252 else if (event.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
253 {
254 break;
255 }
256 else if (event.type == ALLEGRO_EVENT_MOUSE_AXES)
257 {
258 if (b_mouse_in_window && !bouncer->GetControlled())
259 {
260 bouncer->SetControlled(true);
261 }
262 if (bouncer->GetControlled())
263 {
264 FVector2 mouse_pos(event.mouse.x, event.mouse.y);
265 bouncer->SetPosition(mouse_pos);
266 std::stringstream ss("Pos: ");
267 ss << event.mouse.x << "," << event.mouse.y;
268 mouse_pos_msg = ss.str();
269 }
270 }
271 else if (event.type == ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY)
272 {
273 b_mouse_in_window = true;
274 bouncer->SetControlled(true);
275 mouse_pos_msg = "";
276 }
277 else if (event.type == ALLEGRO_EVENT_MOUSE_LEAVE_DISPLAY)
278 {
279 b_mouse_in_window = false;
280 bouncer->SetControlled(false);
281 mouse_pos_msg = "";
282 }
283 else if (event.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP)
284 {
285 break;
286 }
287
288 if (b_needs_redraw && al_is_event_queue_empty(event_queue))
289 {
290 // Redraw logic goes in here
291
292 al_clear_to_color(al_map_rgb(0, 0, 0));
293
294 al_draw_text(font, al_map_rgb(255, 255, 255), 400, 300, ALLEGRO_ALIGN_CENTER, "Welcome to Allegro 5!");
295 al_draw_text(font, al_map_rgb(255, 255, 255), 400, 300 + al_get_font_line_height(font), ALLEGRO_ALIGN_CENTER, mouse_pos_msg.c_str());
296 for (int i = 1; i < argc; i++)
297 {
298 std::cout << "argv[" << i << "] = " << argv[i] << std::endl;
299 al_draw_text(font, al_map_rgb(255, 255, 255), 400, 300 + i * al_get_font_line_height(font), ALLEGRO_ALIGN_CENTER, argv[i]);
300 }
301
302 bouncer->Draw();
303
304 al_flip_display();
305
306 b_needs_redraw = false;
307 }
308 }
309
310 delete bouncer;
311 bouncer = nullptr;
312
313 AllegroDeinit(display, font, timer, event_queue);
314
315 return 0;
316}
317
318
319int AllegroInit(ALLEGRO_DISPLAY*& display, ALLEGRO_FONT*& font, ALLEGRO_TIMER*& timer, ALLEGRO_EVENT_QUEUE*& queue)
320{
321 if (!al_init())
322 {
323 std::cout << "Unable to initialize Allegro 5. Shutting down." << std::endl;
324 return -1;
325 }
326
327 // Call all al_init_*_addon() before other functions.
328 al_init_font_addon();
329
330 if (!al_install_mouse())
331 {
332 std::cout << "Unable to install the mouse. Shutting down." << std::endl;
333 return -2;
334 }
335
336 display = al_create_display(SCREEN_W, SCREEN_H);
337 if (display == nullptr)
338 {
339 std::cout << "Unable to create ALLEGRO_DISPLAY. Shutting down." << std::endl;
340 return -3;
341 }
342
343 font = al_create_builtin_font();
344 if (font == nullptr)
345 {
346 std::cout << "Unable to create ALLEGRO_FONT. Shutting down." << std::endl;
347 return -4;
348 }
349
350 timer = al_create_timer(1.0 / FPS);
351 if (timer == nullptr)
352 {
353 std::cout << "Unable to create ALLEGRO_TIMER. Shutting down." << std::endl;
354 return -5;
355 }
356
357 queue = al_create_event_queue();
358 if (queue == nullptr)
359 {
360 std::cout << "Unable to create ALLEGRO_EVENT_QUEUE. Shutting down." << std::endl;
361 return -6;
362 }
363
364 return 0;
365}
366
367void AllegroDeinit(ALLEGRO_DISPLAY*& display, ALLEGRO_FONT*& font, ALLEGRO_TIMER*& timer, ALLEGRO_EVENT_QUEUE*& queue)
368{
369 al_destroy_event_queue(queue);
370 al_destroy_timer(timer);
371 al_destroy_font(font);
372 al_destroy_display(display);
373
374 if (al_is_mouse_installed())
375 {
376 al_uninstall_mouse();
377 }
378}
I just wish that I could get rid of that nasty b_mouse_in_window check within the loop. Like just check the mouse position before I enter `while (1) { ... }` and set the bouncer->SetControlled() value there.
|
|