#include #include #include #include #include #include #define DISP_WIDTH 960 #define DISP_HEIGHT 480 #define FPS 60.0 #define DO_INIT(check, desc) \ if (!(check)) { \ fprintf(stderr, "err: can't initialise %s\n", desc); \ rval = 1; \ goto done; \ } static bool bit_get(uint8_t *bline, unsigned off) { return (bline[off / 8] >> (off % 8)) & 0x01; } static void bit_set(uint8_t *bline, unsigned off) { bline[off / 8] = (bline[off / 8] | (0x01 << (off % 8)) ); } int main(int argc, char **argv) { int rval = 0; unsigned goframes; uint8_t bits[DISP_HEIGHT][DISP_WIDTH / 8]; uint8_t automaton = 0; unsigned x, y; ALLEGRO_DISPLAY* d = NULL; ALLEGRO_TIMER* t = NULL; ALLEGRO_EVENT_QUEUE* eq = NULL; ALLEGRO_EVENT e; DO_INIT(al_init(), "allegro"); DO_INIT(al_init_primitives_addon(), "primitives"); DO_INIT(al_install_keyboard(), "keyboard"); DO_INIT(t = al_create_timer(1.0 / FPS), "timer"); DO_INIT(eq = al_create_event_queue(), "event queue"); al_set_new_display_option(ALLEGRO_SINGLE_BUFFER, 1, ALLEGRO_REQUIRE); DO_INIT(d = al_create_display(DISP_WIDTH, DISP_HEIGHT), "display"); al_register_event_source(eq, al_get_keyboard_event_source()); al_register_event_source(eq, al_get_display_event_source(d)); al_register_event_source(eq, al_get_timer_event_source(t)); al_start_timer(t); goframes = 0; reset: al_clear_to_color(al_map_rgb(0, 0, 0)); memset(bits, 0, DISP_HEIGHT * DISP_WIDTH / 8); /* seed bit */ bit_set(bits[0], DISP_WIDTH / 2); for (y = 0; y < DISP_HEIGHT - 1; y++) { for (x = 1; x < DISP_WIDTH - 2; x++) { if ( bit_get(&automaton, bit_get(bits[y], x + 2) + bit_get(bits[y], x + 1) * 2 + bit_get(bits[y], x) * 4 ) ) { bit_set(bits[y + 1], x + 1); } } } while(true) { al_wait_for_event(eq, &e); switch (e.type) { case ALLEGRO_EVENT_DISPLAY_CLOSE: goto done; case ALLEGRO_EVENT_KEY_DOWN: switch(e.keyboard.keycode) { case ALLEGRO_KEY_UP: automaton += 10; printf("%d\n", automaton); break; case ALLEGRO_KEY_DOWN: automaton -= 10; printf("%d\n", automaton); break; case ALLEGRO_KEY_LEFT: automaton -= 1; printf("%d\n", automaton); break; case ALLEGRO_KEY_RIGHT: automaton += 1; printf("%d\n", automaton); break; case ALLEGRO_KEY_ENTER: goframes = DISP_HEIGHT; goto reset; default: continue; } case ALLEGRO_EVENT_TIMER: if (goframes == 0) { al_flip_display(); break; } /* draw line */ for (x = 0; x < DISP_WIDTH; x++) { if (bit_get(bits[DISP_HEIGHT - goframes], x)) { al_draw_filled_rectangle( (float)x, (float)(DISP_HEIGHT - goframes), (float)(x + 1), (float)(DISP_HEIGHT - goframes + 1), al_map_rgb(255, 255, 255) ); } } al_flip_display(); goframes--; if (goframes == 0) puts("next"); } } done: if (d) al_destroy_display(d); if (t) al_destroy_timer(t); if (eq) al_destroy_event_queue(eq); return rval; }