1 #include <allegro5/allegro.h>
2 #include <allegro5/allegro_image.h>
3 #include <allegro5/allegro_font.h>
4 #include <stdlib.h>
5 #include <math.h>
6
7 #include "common.c"
8
9 ALLEGRO_DEBUG_CHANNEL("main")
10
11 #define FPS 60
12 #define MAX_SPRITES 1024
13
14 typedef struct Sprite {
15 float x, y, dx, dy;
16 } Sprite;
17
18 char const *text[] = {
19 "H - toggle held drawing",
20 "Space - toggle use of textures",
21 "B - toggle alpha blending",
22 "Left/Right - change bitmap size",
23 "Up/Down - change bitmap count",
24 "F1 - toggle help text"
25 };
26
27 struct Example {
28 Sprite sprites[MAX_SPRITES];
29 bool use_memory_bitmaps;
30 int blending;
31 ALLEGRO_DISPLAY *display;
32 ALLEGRO_BITMAP *mysha, *bitmap;
33 bool hold_bitmap_drawing;
34 int bitmap_size;
35 int sprite_count;
36 bool show_help;
37 ALLEGRO_FONT *font;
38
39 int t;
40
41 ALLEGRO_COLOR white;
42 ALLEGRO_COLOR half_white;
43 ALLEGRO_COLOR dark;
44 ALLEGRO_COLOR red;
45
46 double direct_speed_measure;
47
48 int ftpos;
49 double frame_times[FPS];
50 } example;
51
add_time(void)52 static void add_time(void)
53 {
54 example.frame_times[example.ftpos++] = al_get_time();
55 if (example.ftpos >= FPS)
56 example.ftpos = 0;
57 }
58
get_fps(int * average,int * minmax)59 static void get_fps(int *average, int *minmax)
60 {
61 int i;
62 int prev = FPS - 1;
63 double min_dt = 1;
64 double max_dt = 1 / 1000000.0;
65 double av = 0;
66 double d;
67 for (i = 0; i < FPS; i++) {
68 if (i != example.ftpos) {
69 double dt = example.frame_times[i] - example.frame_times[prev];
70 if (dt < min_dt)
71 min_dt = dt;
72 if (dt > max_dt)
73 max_dt = dt;
74 av += dt;
75 }
76 prev = i;
77 }
78 av /= (FPS - 1);
79 *average = ceil(1 / av);
80 d = 1 / min_dt - 1 / max_dt;
81 *minmax = floor(d / 2);
82 }
83
add_sprite(void)84 static void add_sprite(void)
85 {
86 if (example.sprite_count < MAX_SPRITES) {
87 int w = al_get_display_width(example.display);
88 int h = al_get_display_height(example.display);
89 int i = example.sprite_count++;
90 Sprite *s = example.sprites + i;
91 float a = rand() % 360;
92 s->x = rand() % (w - example.bitmap_size);
93 s->y = rand() % (h - example.bitmap_size);
94 s->dx = cos(a) * FPS * 2;
95 s->dy = sin(a) * FPS * 2;
96 }
97 }
98
add_sprites(int n)99 static void add_sprites(int n)
100 {
101 int i;
102 for (i = 0; i < n; i++)
103 add_sprite();
104 }
105
remove_sprites(int n)106 static void remove_sprites(int n)
107 {
108 example.sprite_count -= n;
109 if (example.sprite_count < 0)
110 example.sprite_count = 0;
111 }
112
change_size(int size)113 static void change_size(int size)
114 {
115 int bw, bh;
116 if (size < 1)
117 size = 1;
118 if (size > 1024)
119 size = 1024;
120
121 if (example.bitmap)
122 al_destroy_bitmap(example.bitmap);
123 al_set_new_bitmap_flags(
124 example.use_memory_bitmaps ? ALLEGRO_MEMORY_BITMAP : ALLEGRO_VIDEO_BITMAP);
125 example.bitmap = al_create_bitmap(size, size);
126 example.bitmap_size = size;
127 al_set_target_bitmap(example.bitmap);
128 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
129 al_clear_to_color(al_map_rgba_f(0, 0, 0, 0));
130 bw = al_get_bitmap_width(example.mysha);
131 bh = al_get_bitmap_height(example.mysha);
132 al_draw_scaled_bitmap(example.mysha, 0, 0, bw, bh, 0, 0,
133 size, size * bh / bw, 0);
134 al_set_target_backbuffer(example.display);
135 }
136
sprite_update(Sprite * s)137 static void sprite_update(Sprite *s)
138 {
139 int w = al_get_display_width(example.display);
140 int h = al_get_display_height(example.display);
141
142 s->x += s->dx / FPS;
143 s->y += s->dy / FPS;
144
145 if (s->x < 0) {
146 s->x = -s->x;
147 s->dx = -s->dx;
148 }
149 if (s->x + example.bitmap_size > w) {
150 s->x = -s->x + 2 * (w - example.bitmap_size);
151 s->dx = -s->dx;
152 }
153 if (s->y < 0) {
154 s->y = -s->y;
155 s->dy = -s->dy;
156 }
157 if (s->y + example.bitmap_size > h) {
158 s->y = -s->y + 2 * (h - example.bitmap_size);
159 s->dy = -s->dy;
160 }
161
162 if (example.bitmap_size > w) s->x = w / 2 - example.bitmap_size / 2;
163 if (example.bitmap_size > h) s->y = h / 2 - example.bitmap_size / 2;
164 }
165
update(void)166 static void update(void)
167 {
168 int i;
169 for (i = 0; i < example.sprite_count; i++)
170 sprite_update(example.sprites + i);
171
172 example.t++;
173 if (example.t == 60) {
174 ALLEGRO_DEBUG("tick");
175 example.t = 0;
176 }
177 }
178
redraw(void)179 static void redraw(void)
180 {
181 int w = al_get_display_width(example.display);
182 int h = al_get_display_height(example.display);
183 int i;
184 int f1, f2;
185 int fh = al_get_font_line_height(example.font);
186 char const *info[] = {"textures", "memory buffers"};
187 char const *binfo[] = {"alpha", "additive", "tinted", "solid", "alpha test"};
188 ALLEGRO_COLOR tint = example.white;
189
190 if (example.blending == 0) {
191 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
192 tint = example.half_white;
193 }
194 else if (example.blending == 1) {
195 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ONE);
196 tint = example.dark;
197 }
198 else if (example.blending == 2) {
199 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
200 tint = example.red;
201 }
202 else if (example.blending == 3) {
203 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
204 }
205
206 if (example.blending == 4) {
207 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
208 al_set_render_state(ALLEGRO_ALPHA_TEST, true);
209 al_set_render_state(ALLEGRO_ALPHA_FUNCTION, ALLEGRO_RENDER_GREATER);
210 al_set_render_state(ALLEGRO_ALPHA_TEST_VALUE, 128);
211 }
212 else {
213 al_set_render_state(ALLEGRO_ALPHA_TEST, false);
214 }
215
216 if (example.hold_bitmap_drawing) {
217 al_hold_bitmap_drawing(true);
218 }
219 for (i = 0; i < example.sprite_count; i++) {
220 Sprite *s = example.sprites + i;
221 al_draw_tinted_bitmap(example.bitmap, tint, s->x, s->y, 0);
222 }
223 if (example.hold_bitmap_drawing) {
224 al_hold_bitmap_drawing(false);
225 }
226
227 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
228 if (example.show_help) {
229 int dh = fh * 3.5;
230 for (i = 5; i >= 0; i--) {
231 al_draw_text(example.font, example.white, 0, h - dh, 0, text[i]);
232 dh += fh * 6;
233 }
234 }
235
236 al_draw_textf(example.font, example.white, 0, 0, 0, "count: %d",
237 example.sprite_count);
238 al_draw_textf(example.font, example.white, 0, fh, 0, "size: %d",
239 example.bitmap_size);
240 al_draw_textf(example.font, example.white, 0, fh * 2, 0, "%s",
241 info[example.use_memory_bitmaps]);
242 al_draw_textf(example.font, example.white, 0, fh * 3, 0, "%s",
243 binfo[example.blending]);
244
245 get_fps(&f1, &f2);
246 al_draw_textf(example.font, example.white, w, 0, ALLEGRO_ALIGN_RIGHT, "FPS: %4d +- %-4d",
247 f1, f2);
248 al_draw_textf(example.font, example.white, w, fh, ALLEGRO_ALIGN_RIGHT, "%4d / sec",
249 (int)(1.0 / example.direct_speed_measure));
250
251 }
252
main(int argc,char ** argv)253 int main(int argc, char **argv)
254 {
255 ALLEGRO_TIMER *timer;
256 ALLEGRO_EVENT_QUEUE *queue;
257 ALLEGRO_MONITOR_INFO info;
258 const char* bitmap_filename;
259 int w = 640, h = 480;
260 bool done = false;
261 bool need_redraw = true;
262 bool background = false;
263 example.show_help = true;
264 example.hold_bitmap_drawing = false;
265
266 if (argc > 1) {
267 bitmap_filename = argv[1];
268 }
269 else {
270 bitmap_filename = "data/mysha256x256.png";
271 }
272
273 if (!al_init()) {
274 abort_example("Failed to init Allegro.\n");
275 }
276
277 if (!al_init_image_addon()) {
278 abort_example("Failed to init IIO addon.\n");
279 }
280
281 al_init_font_addon();
282 init_platform_specific();
283
284 al_get_num_video_adapters();
285
286 al_get_monitor_info(0, &info);
287
288 al_set_new_display_option(ALLEGRO_SUPPORTED_ORIENTATIONS,
289 ALLEGRO_DISPLAY_ORIENTATION_ALL, ALLEGRO_SUGGEST);
290 example.display = al_create_display(w, h);
291 if (!example.display) {
292 abort_example("Error creating display.\n");
293 }
294
295 w = al_get_display_width(example.display);
296 h = al_get_display_height(example.display);
297
298 if (!al_install_keyboard()) {
299 abort_example("Error installing keyboard.\n");
300 }
301
302 if (!al_install_mouse()) {
303 abort_example("Error installing mouse.\n");
304 }
305
306 al_install_touch_input();
307
308 example.font = al_create_builtin_font();
309 if (!example.font) {
310 abort_example("Error creating builtin font\n");
311 }
312
313 example.mysha = al_load_bitmap(bitmap_filename);
314 if (!example.mysha) {
315 abort_example("Error loading %s\n", bitmap_filename);
316 }
317
318 example.white = al_map_rgb_f(1, 1, 1);
319 example.half_white = al_map_rgba_f(1, 1, 1, 0.5);
320 example.dark = al_map_rgb(15, 15, 15);
321 example.red = al_map_rgb_f(1, 0.2, 0.1);
322 change_size(256);
323 add_sprite();
324 add_sprite();
325
326 timer = al_create_timer(1.0 / FPS);
327
328 queue = al_create_event_queue();
329 al_register_event_source(queue, al_get_keyboard_event_source());
330 al_register_event_source(queue, al_get_mouse_event_source());
331 al_register_event_source(queue, al_get_timer_event_source(timer));
332
333 if (al_install_touch_input())
334 al_register_event_source(queue, al_get_touch_input_event_source());
335 al_register_event_source(queue, al_get_display_event_source(example.display));
336
337 al_start_timer(timer);
338
339 while (!done) {
340 float x, y;
341 ALLEGRO_EVENT event;
342 w = al_get_display_width(example.display);
343 h = al_get_display_height(example.display);
344
345 if (!background && need_redraw && al_is_event_queue_empty(queue)) {
346 double t = -al_get_time();
347 add_time();
348 al_clear_to_color(al_map_rgb_f(0, 0, 0));
349 redraw();
350 t += al_get_time();
351 example.direct_speed_measure = t;
352 al_flip_display();
353 need_redraw = false;
354 }
355
356 al_wait_for_event(queue, &event);
357 switch (event.type) {
358 case ALLEGRO_EVENT_KEY_CHAR: /* includes repeats */
359 if (event.keyboard.keycode == ALLEGRO_KEY_ESCAPE)
360 done = true;
361 else if (event.keyboard.keycode == ALLEGRO_KEY_UP) {
362 add_sprites(1);
363 }
364 else if (event.keyboard.keycode == ALLEGRO_KEY_DOWN) {
365 remove_sprites(1);
366 }
367 else if (event.keyboard.keycode == ALLEGRO_KEY_LEFT) {
368 change_size(example.bitmap_size - 1);
369 }
370 else if (event.keyboard.keycode == ALLEGRO_KEY_RIGHT) {
371 change_size(example.bitmap_size + 1);
372 }
373 else if (event.keyboard.keycode == ALLEGRO_KEY_F1) {
374 example.show_help ^= 1;
375 }
376 else if (event.keyboard.keycode == ALLEGRO_KEY_SPACE) {
377 example.use_memory_bitmaps ^= 1;
378 change_size(example.bitmap_size);
379 }
380 else if (event.keyboard.keycode == ALLEGRO_KEY_B) {
381 example.blending++;
382 if (example.blending == 5)
383 example.blending = 0;
384 }
385 else if (event.keyboard.keycode == ALLEGRO_KEY_H) {
386 example.hold_bitmap_drawing ^= 1;
387 }
388 break;
389
390 case ALLEGRO_EVENT_DISPLAY_CLOSE:
391 done = true;
392 break;
393
394 case ALLEGRO_EVENT_DISPLAY_HALT_DRAWING:
395
396 background = true;
397 al_acknowledge_drawing_halt(event.display.source);
398
399 break;
400
401 case ALLEGRO_EVENT_DISPLAY_RESUME_DRAWING:
402 background = false;
403 al_acknowledge_drawing_resume(event.display.source);
404 break;
405
406 case ALLEGRO_EVENT_DISPLAY_RESIZE:
407 al_acknowledge_resize(event.display.source);
408 break;
409
410 case ALLEGRO_EVENT_TIMER:
411 update();
412 need_redraw = true;
413 break;
414
415 case ALLEGRO_EVENT_TOUCH_BEGIN:
416 x = event.touch.x;
417 y = event.touch.y;
418 goto click;
419
420 case ALLEGRO_EVENT_MOUSE_BUTTON_UP:
421 x = event.mouse.x;
422 y = event.mouse.y;
423 goto click;
424
425 click:
426 {
427 int fh = al_get_font_line_height(example.font);
428
429 if (x < fh * 12 && y >= h - fh * 30) {
430 int button = (y - (h - fh * 30)) / (fh * 6);
431 if (button == 0) {
432 example.use_memory_bitmaps ^= 1;
433 change_size(example.bitmap_size);
434 }
435 if (button == 1) {
436 example.blending++;
437 if (example.blending == 5)
438 example.blending = 0;
439 }
440 if (button == 3) {
441 if (x < fh * 6)
442 remove_sprites(example.sprite_count / 2);
443 else
444 add_sprites(example.sprite_count);
445 }
446 if (button == 2) {
447 int s = example.bitmap_size * 2;
448 if (x < fh * 6)
449 s = example.bitmap_size / 2;
450 change_size(s);
451 }
452 if (button == 4) {
453 example.show_help ^= 1;
454 }
455
456 }
457 break;
458 }
459 }
460 }
461
462 al_destroy_bitmap(example.bitmap);
463
464 return 0;
465 }
466
467 /* vim: set sts=3 sw=3 et: */
468