/* * Example program for the Allegro library, by Peter Wang. * * In this example, each thread handles its own window and event queue. */ #include #include #include #include "common.c" #define MAX_THREADS 100 #define MAX_BACKGROUNDS 10 #define MAX_SQUARES 25 typedef struct Background { double rmax; double gmax; double bmax; } Background; typedef struct Square { float cx, cy; float dx, dy; float size, dsize; float rot, drot; float life, dlife; } Square; static float rand01(void) { return (rand() % 10000) / 10000.0; } static float rand11(void) { return (-10000 + (rand() % 20000)) / 20000.0; } static void gen_square(Square *sq, int w, int h) { sq->cx = rand() % w; sq->cy = rand() % h; sq->dx = 3.0 * rand11(); sq->dy = 3.0 * rand11(); sq->size = 10 + (rand() % 10); sq->dsize = rand11(); sq->rot = ALLEGRO_PI * rand01(); sq->drot = rand11() / 3.0; sq->life = 0.0; sq->dlife = (ALLEGRO_PI / 100.0) + (ALLEGRO_PI / 30.0) * rand01(); } static void animate_square(Square *sq) { sq->cx += sq->dx; sq->cy += sq->dy; sq->size += sq->dsize; sq->rot += sq->drot; sq->life += sq->dlife; if (sq->size < 1.0 || sq->life > ALLEGRO_PI) { ALLEGRO_BITMAP *bmp = al_get_target_bitmap(); gen_square(sq, al_get_bitmap_width(bmp), al_get_bitmap_height(bmp)); } } static void draw_square(Square *sq) { ALLEGRO_TRANSFORM trans; float alpha; float size; ALLEGRO_COLOR tint; al_build_transform(&trans, sq->cx, sq->cy, 1.0, 1.0, sq->rot); al_use_transform(&trans); alpha = sin(sq->life); al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_ONE); tint = al_map_rgba_f(0.5, 0.3, 0, alpha); size = sq->size; al_draw_filled_rounded_rectangle(-size, -size, size, size, 3, 3, tint); size *= 1.1; al_draw_rounded_rectangle(-size, -size, size, size, 3, 3, tint, 2); } static void *thread_func(ALLEGRO_THREAD *thr, void *arg) { const int INITIAL_WIDTH = 300; const int INITIAL_HEIGHT = 300; const Background *background = (Background *) arg; ALLEGRO_DISPLAY *display; ALLEGRO_EVENT_QUEUE *queue = NULL; ALLEGRO_TIMER *timer = NULL; ALLEGRO_EVENT event; ALLEGRO_STATE state; Square squares[MAX_SQUARES]; double theta = 0.0; bool redraw = true; int i; (void)thr; al_set_new_display_flags(ALLEGRO_RESIZABLE); display = al_create_display(INITIAL_WIDTH, INITIAL_HEIGHT); if (!display) { goto Quit; } queue = al_create_event_queue(); if (!queue) { goto Quit; } timer = al_create_timer(0.1); if (!timer) { goto Quit; } al_register_event_source(queue, al_get_display_event_source(display)); al_register_event_source(queue, al_get_keyboard_event_source()); al_register_event_source(queue, al_get_timer_event_source(timer)); for (i = 0; i < MAX_SQUARES; i++) { gen_square(&squares[i], INITIAL_WIDTH, INITIAL_HEIGHT); } al_start_timer(timer); while (true) { if (al_is_event_queue_empty(queue) && redraw) { double r = 0.7 + 0.3 * (sin(theta) + 1.0) / 2.0; ALLEGRO_COLOR c = al_map_rgb_f( background->rmax * r, background->gmax * r, background->bmax * r ); al_clear_to_color(c); al_store_state(&state, ALLEGRO_STATE_BLENDER | ALLEGRO_STATE_TRANSFORM); for (i = 0; i < MAX_SQUARES; i++) { draw_square(&squares[i]); } al_restore_state(&state); al_flip_display(); redraw = false; } al_wait_for_event(queue, &event); if (event.type == ALLEGRO_EVENT_TIMER) { for (i = 0; i < MAX_SQUARES; i++) { animate_square(&squares[i]); } theta += 0.1; redraw = true; } else if (event.type == ALLEGRO_EVENT_DISPLAY_CLOSE) { break; } else if (event.type == ALLEGRO_EVENT_KEY_DOWN && event.keyboard.keycode == ALLEGRO_KEY_ESCAPE) { break; } else if (event.type == ALLEGRO_EVENT_DISPLAY_RESIZE) { al_acknowledge_resize(event.display.source); } } Quit: if (timer) { al_destroy_timer(timer); } if (queue) { al_destroy_event_queue(queue); } if (display) { al_destroy_display(display); } return NULL; } int main(int argc, char **argv) { ALLEGRO_THREAD *thread[MAX_THREADS]; Background background[MAX_BACKGROUNDS] = { { 1.0, 0.5, 0.5 }, { 0.5, 1.0, 0.5 }, { 0.5, 0.5, 1.0 }, { 1.0, 1.0, 0.5 }, { 0.5, 1.0, 1.0 }, { 1.0, 0.7, 0.5 }, { 0.5, 1.0, 0.7 }, { 0.7, 0.5, 1.0 }, { 1.0, 0.7, 0.5 }, { 0.5, 0.7, 1.0 } }; int num_threads; int i; if (argc > 1) { num_threads = strtol(argv[1], NULL, 10); if (num_threads > MAX_THREADS) num_threads = MAX_THREADS; else if (num_threads < 1) num_threads = 1; } else { num_threads = 3; } if (!al_init()) { abort_example("Could not init Allegro.\n"); } al_init_primitives_addon(); al_install_keyboard(); al_install_mouse(); for (i = 0; i < num_threads; i++) { thread[i] = al_create_thread(thread_func, &background[i % MAX_BACKGROUNDS]); } for (i = 0; i < num_threads; i++) { al_start_thread(thread[i]); } for (i = 0; i < num_threads; i++) { al_join_thread(thread[i], NULL); al_destroy_thread(thread[i]); } return 0; } /* vim: set sts=3 sw=3 et: */