#include #include #include #include #include #include #include long frames; long score; ALLEGRO_DISPLAY * init_allegro_display(struct rb *rb) { if (!rb) return NULL; al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS, 1, ALLEGRO_SUGGEST); al_set_new_display_option(ALLEGRO_SAMPLES, 8, ALLEGRO_SUGGEST); al_set_new_bitmap_flags(ALLEGRO_MIN_LINEAR | ALLEGRO_MAG_LINEAR); return al_create_display(rb->width, rb->height); } /* * Allegro lib functions return 0 in case of error (or NULL), to make * it compliant to Unix, return 0 if we succeed, non-zero otherwise */ int initialize_allegro(struct rb **p) { struct rb *rb; if (*p != NULL) { printf("Allegro already initialized\n"); return 1; } rb = malloc(sizeof(struct rb)); if (!rb) return 1; rb->width = RB_WIDTH; rb->height = RB_HEIGHT; rb->fps = RB_FPS; if (!al_init()) goto err_alloc; if (!al_install_keyboard()) goto err_alloc; if (!al_install_mouse()) goto err_alloc; rb->timer = al_create_timer(rb->fps); if (!rb->timer) goto err_alloc; rb->event_queue = al_create_event_queue(); if (!rb->event_queue) goto err_timer; rb->font = al_create_builtin_font(); if (!rb->font) goto err_event_queue; rb->display = init_allegro_display(rb); if (!rb->display) goto err_font; if (!al_init_primitives_addon()) goto err_display; *p = rb; return 0; err_display: al_destroy_display(rb->display); err_font: al_destroy_font(rb->font); err_event_queue: al_destroy_event_queue(rb->event_queue); err_timer: al_destroy_timer(rb->timer); err_alloc: printf("Couldn't initialize Allegro\n"); free(rb); return 1; } void shutdown_allegro(struct rb *rb) { al_destroy_display(rb->display); al_destroy_font(rb->font); al_destroy_event_queue(rb->event_queue); al_destroy_timer(rb->timer); free(rb); } void register_events(struct rb *rb) { al_register_event_source(rb->event_queue, al_get_keyboard_event_source()); al_register_event_source(rb->event_queue, al_get_display_event_source(rb->display)); al_register_event_source(rb->event_queue, al_get_timer_event_source(rb->timer)); al_register_event_source(rb->event_queue, al_get_mouse_event_source()); al_hide_mouse_cursor(rb->display); al_grab_mouse(rb->display); } void rb_draw_status(struct rb *rb, struct spaceship *sp, float x, float y, float dx, float dy) { ALLEGRO_TRANSFORM transform; al_identity_transform(&transform); al_rotate_transform(&transform, 0); al_translate_transform(&transform, 0, 0); al_use_transform(&transform); al_draw_textf(rb->font, al_map_rgb(255, 255, 255), 0, 0, 0, "X: %.1f Y: %.1f DX: %f DY: %f HDG: %f", sp->x, sp->y, dx, dy, sp->heading); } void start_game(struct rb *rb) { #define KEY_SEEN 1 #define KEY_DOWN 2 bool done = false; bool redraw = true; float x, y; float dx, dy; /* mouse velocity - change in coordinate since prev event*/ ALLEGRO_EVENT event; unsigned char key[ALLEGRO_KEY_MAX]; struct spaceship sp = {0}; rb_ship_init(&sp); memset(key, 0, sizeof(key)); dx = 0; dy = 0; x = 100; y = 100; al_start_timer(rb->timer); while (1) { al_wait_for_event(rb->event_queue, &event); switch(event.type) { case ALLEGRO_EVENT_TIMER: x += dx; y += dy; if(key[ALLEGRO_KEY_UP]) rb_ship_accelerate(&sp); if(key[ALLEGRO_KEY_LEFT]) rb_ship_rotate_left(&sp); if(key[ALLEGRO_KEY_RIGHT]) rb_ship_rotate_right(&sp); if (key[ALLEGRO_KEY_ESCAPE]) done = true; dx *= 0.9; dy *= 0.9; for (int i = 0; i < ALLEGRO_KEY_MAX; i++) key[i] &= ~KEY_SEEN; redraw = true; break; case ALLEGRO_EVENT_MOUSE_AXES: dx += event.mouse.dx * 0.1; dy += event.mouse.dy * 0.1; case ALLEGRO_EVENT_KEY_DOWN: key[event.keyboard.keycode] = KEY_SEEN | KEY_DOWN; break; case ALLEGRO_EVENT_KEY_UP: key[event.keyboard.keycode] &= ~KEY_DOWN; break; case ALLEGRO_EVENT_KEY_CHAR: if (event.keyboard.keycode == ALLEGRO_KEY_UP) rb_ship_accelerate(&sp); if (event.keyboard.keycode == ALLEGRO_KEY_DOWN) y++; if (event.keyboard.keycode == ALLEGRO_KEY_LEFT) rb_ship_rotate_left(&sp); if (event.keyboard.keycode == ALLEGRO_KEY_RIGHT) rb_ship_rotate_right(&sp); if (event.keyboard.keycode != ALLEGRO_KEY_ESCAPE) break; case ALLEGRO_EVENT_DISPLAY_CLOSE: done = true; break; } if (done) break; if (redraw && al_is_event_queue_empty(rb->event_queue)) { al_clear_to_color(al_map_rgb(0, 0, 0)); rb_draw_status(rb, &sp, x, y, dx, dy); rb_draw_ship(&sp); al_flip_display(); redraw = false; } } } int main(void) { int error; struct rb *rb = NULL; error = initialize_allegro(&rb); if (error) exit(EXIT_FAILURE); register_events(rb); start_game(rb); shutdown_allegro(rb); return 0; }