void draw_scene() { // setup the render settings al_set_render_state(ALLEGRO_DEPTH_TEST, 1); al_set_render_state(ALLEGRO_WRITE_MASK, ALLEGRO_MASK_DEPTH | ALLEGRO_MASK_RGBA); al_clear_depth_buffer(1); ALLEGRO_TRANSFORM t; Entity3D *camera = static_cast<Entity3D *>(scene_root.find_first("name", "camera")); if (camera) camera->place.build_reverse_transform(&t); else al_identity_transform(&t); set_projection(backbuffer_sub_bitmap, &t); // draw our scene scene_root._draw(); }
void primary_timer_func() override { // // UPDATE // for (unsigned i=0; i<entities.size(); i++) { entities[i]->place.position += entities[i]->velocity.position; entities[i]->place.rotation += entities[i]->velocity.rotation; } // // DRAW // // the functionality of this line might eventually be embedded in the framework setup_projection(); // draw the entities in our scene vec3d camera_position = camera.get_real_position(); vec3d light_position = light.position; // draw the skybox (and clear the depth buffer) skybox->place.position = camera_position; skybox->draw(0, 0); al_clear_depth_buffer(1); for (unsigned i=0; i<entities.size(); i++) { entities[i]->draw(camera_position, light_position); } // draw the Construct (the environment box) /* glEnable(GL_CULL_FACE); // requiring opengl should eventually be fazed out construct.draw(); glDisable(GL_CULL_FACE); */ }
void setup_projection() { // setup the render settings al_set_render_state(ALLEGRO_DEPTH_TEST, 1); al_set_render_state(ALLEGRO_WRITE_MASK, ALLEGRO_MASK_DEPTH | ALLEGRO_MASK_RGBA); al_clear_depth_buffer(1); ALLEGRO_TRANSFORM t; camera.reverse_position_transform(&t); float aspect_ratio = (float)al_get_bitmap_height(backbuffer_sub_bitmap) / al_get_bitmap_width(backbuffer_sub_bitmap); al_perspective_transform(&t, -1, aspect_ratio, 1, 1, -aspect_ratio, 1000); //al_set_target_bitmap(backbuffer_sub_bitmap); << I don't think this is necessairy, it also occours just prior to this function al_use_projection_transform(&t); }
static void redraw(void) { ALLEGRO_TRANSFORM t; int i; /* We first draw the Obp background and clear the depth buffer to 1. */ al_set_render_state(ALLEGRO_ALPHA_TEST, true); al_set_render_state(ALLEGRO_ALPHA_FUNCTION, ALLEGRO_RENDER_GREATER); al_set_render_state(ALLEGRO_ALPHA_TEST_VALUE, 0); al_set_render_state(ALLEGRO_DEPTH_TEST, false); al_set_render_state(ALLEGRO_WRITE_MASK, ALLEGRO_MASK_DEPTH | ALLEGRO_MASK_RGBA); al_clear_depth_buffer(1); al_clear_to_color(al_map_rgb_f(0, 0, 0)); al_draw_scaled_bitmap(example.obp, 0, 0, 532, 416, 0, 0, 640, 416 * 640 / 532, 0); /* Next we draw all sprites but only to the depth buffer (with a depth value * of 0). */ al_set_render_state(ALLEGRO_DEPTH_TEST, true); al_set_render_state(ALLEGRO_DEPTH_FUNCTION, ALLEGRO_RENDER_ALWAYS); al_set_render_state(ALLEGRO_WRITE_MASK, ALLEGRO_MASK_DEPTH); for (i = 0; i < COUNT; i++) { struct Sprite *s = example.sprites + i; int x, y; al_hold_bitmap_drawing(true); for (y = -480; y <= 0; y += 480) { for (x = -640; x <= 0; x += 640) { al_identity_transform(&t); al_rotate_transform(&t, s->angle); al_translate_transform(&t, s->x + x, s->y + y); al_use_transform(&t); al_draw_text(example.font, al_map_rgb(0, 0, 0), 0, 0, ALLEGRO_ALIGN_CENTER, "Allegro 5"); } } al_hold_bitmap_drawing(false); } al_identity_transform(&t); al_use_transform(&t); /* Finally we draw Mysha, with depth testing so she only appears where * sprites have been drawn before. */ al_set_render_state(ALLEGRO_DEPTH_FUNCTION, ALLEGRO_RENDER_EQUAL); al_set_render_state(ALLEGRO_WRITE_MASK, ALLEGRO_MASK_RGBA); al_draw_scaled_bitmap(example.mysha, 0, 0, 320, 200, 0, 0, 320 * 480 / 200, 480, 0); /* Finally we draw an FPS counter. */ al_set_render_state(ALLEGRO_DEPTH_TEST, false); al_draw_textf(example.font2, al_map_rgb_f(1, 1, 1), 640, 0, ALLEGRO_ALIGN_RIGHT, "%.1f FPS", 1.0 / example.direct_speed_measure); }
void game_loop (GAME *game) { if (!game) return; ALLEGRO_KEYBOARD_STATE keyboard_state; ALLEGRO_EVENT event; ALLEGRO_FONT *font = al_load_font ("data/fixed_font.tga", 0, 0); SCENE *scene; SPRITE_ACTOR *actor; LIST_ITEM *item; AABB_COLLISIONS collisions; aabb_init_collisions (&collisions); AABB_COLLISIONS portal_collisions; aabb_init_collisions (&portal_collisions); AABB_COLLISIONS npc_collisions; aabb_init_collisions (&npc_collisions); int i = 0; bool redraw = true; float times[NTIMES] = {0}; double frame_time, current_time, new_time, mean_frame_time; double fixed_dt = 1.0 / FPS, dt; double curfps = 0.0; current_time = al_get_time (); al_start_timer (game->timer); float fadeout_duration = 0; float fadein_duration = 0; SCENE_PORTAL *dest_portal = NULL; char *arrow_path = get_resource_path_str ("data/ui/smallarrow_down.png"); ALLEGRO_BITMAP *sel_arrow = al_load_bitmap (arrow_path); while (game->running) { scene = game->current_scene; actor = game->current_actor; if (redraw) { al_clear_depth_buffer (0); tiled_draw_map_back (scene->map, game->screen.tint, game->screen.position.x, game->screen.position.y, game->screen.width, game->screen.height, 0, 0, 0); al_draw_textf (font, al_map_rgba_f (0.9, 0, 0, 1), 5, 5, 0, "FPS: %.2f", curfps); al_set_render_state (ALLEGRO_ALPHA_TEST, true); al_set_render_state (ALLEGRO_DEPTH_TEST, true); al_set_render_state (ALLEGRO_DEPTH_FUNCTION, ALLEGRO_RENDER_GREATER); al_hold_bitmap_drawing (true); sprite_draw (actor, &game->screen); item = _al_list_front (scene->npcs); while (item) { SPRITE_ACTOR *npc_actor = (SPRITE_ACTOR *)_al_list_item_data (item); sprite_draw (npc_actor, &game->screen); item = _al_list_next (scene->npcs, item); } al_hold_bitmap_drawing (false); al_set_render_state (ALLEGRO_DEPTH_TEST, false); al_set_render_state (ALLEGRO_ALPHA_TEST, false); if (false) { item = _al_list_front (portal_collisions.boxes); while (item) { BOX *box = _al_list_item_data (item); box_draw (*box, game->screen.position, al_map_rgb_f (1, 0, 0)); item = _al_list_next (portal_collisions.boxes, item); } aabb_draw (scene->portal_tree, &game->screen, al_map_rgb_f (0, 0, 1)); } tiled_draw_map_fore (scene->map, game->screen.tint, game->screen.position.x, game->screen.position.y, game->screen.width, game->screen.height, 0, 0, 0); if (game->current_npc) { float dx = game->current_npc->actor.box.center.x - game->screen.position.x; float dy = game->current_npc->actor.box.center.y - game->screen.position.y; dx -= al_get_bitmap_width (sel_arrow) * 0.5f; dy -= game->current_npc->actor.box.extent.y * 3.0f; al_draw_bitmap (sel_arrow, dx, dy, 0); } ui_draw (game->ui, &game->screen); if (game->force_vsync) al_wait_for_vsync (); al_flip_display (); redraw = false; } al_wait_for_event (game->event_queue, &event); switch (event.type) { case ALLEGRO_EVENT_TIMER: new_time = al_get_time (); frame_time = new_time - current_time; current_time = new_time; times[i] = frame_time; i = (i + 1) % NTIMES; mean_frame_time = 0.0; for (int j = 0; j < NTIMES; j++) mean_frame_time += times[j]; mean_frame_time /= NTIMES; curfps = 1.0 / mean_frame_time; dt = mean_frame_time / fixed_dt; if (fadeout_duration > 0.0f) { float fadef = fadeout_duration / TRANS_TIME; game->screen.tint = al_map_rgba_f (fadef, fadef, fadef, 1.0); fadeout_duration -= mean_frame_time; if (fadeout_duration <= 0.0f) { fadein_duration = TRANS_TIME; fadeout_duration = 0.0f; game_enter_portal (game, dest_portal); } } if (fadein_duration > 0.0f) { float fadef = 1.0 - fadein_duration / TRANS_TIME; game->screen.tint = al_map_rgba_f (fadef, fadef, fadef, 1.0); fadein_duration -= mean_frame_time; if (fadein_duration <= 0.0f) { game->paused = false; fadein_duration = 0.0f; } } if (game->paused) { redraw = true; break; } al_get_keyboard_state (&keyboard_state); if (al_key_down (&keyboard_state, ALLEGRO_KEY_ESCAPE)) { game->running = false; continue; } if (al_key_down (&keyboard_state, ALLEGRO_KEY_ENTER)) { ui_show_dialog (game->ui, NULL, NULL); } if (al_key_down (&keyboard_state, ALLEGRO_KEY_RIGHT)) { actor->event->move_right (actor, dt); } if (al_key_down (&keyboard_state, ALLEGRO_KEY_LEFT)) { actor->event->move_left (actor, dt); } if (al_key_down (&keyboard_state, ALLEGRO_KEY_UP)) { actor->event->move_up (actor, dt); } if (al_key_down (&keyboard_state, ALLEGRO_KEY_DOWN)) { actor->event->move_down (actor, dt); } BOX box = actor->box; box.center.x += actor->movement.x * dt; box.center.y += actor->movement.y * dt; aabb_collide_fill_cache (scene->collision_tree, &box, &collisions); if (scene->collision_tree->num_collisions > 0) { item = _al_list_front (collisions.boxes); while (item) { if (box_lateral (*(BOX *)_al_list_item_data (item), actor->box)) actor->movement.x = 0; else actor->movement.y = 0; item = _al_list_next (collisions.boxes, item); } } aabb_collide_fill_cache (scene->portal_tree, &box, &portal_collisions); if (scene->portal_tree->num_collisions > 0) { item = _al_list_front (portal_collisions.boxes); while (item) { BOX *colbox = _al_list_item_data (item); TILED_OBJECT *obj = colbox->data; SCENE_PORTAL *portal = scene_get_portal (game->scenes, obj->name); if (portal && portal->destiny_portal) { dest_portal = scene_get_portal (game->scenes, portal->destiny_portal); if (dest_portal) { fadeout_duration = TRANS_TIME; game->paused = true; actor->movement = (VECTOR2D){0, 0}; ui_show_dialog_cstr (game->ui, "Speaker:", "Entering portal."); break; } } item = _al_list_next (portal_collisions.boxes, item); } } box = screen_box (&game->screen); game->current_npc = NULL; item = _al_list_front (scene->npcs); float max_dist = 0; while (item) { SPRITE_NPC *npc = _al_list_item_data (item); float dist = vsqdistance (npc->actor.box.center, game->current_actor->box.center); if (dist < 128.0f * 128.0f && dist > max_dist) { game->current_npc = npc; max_dist = dist; } item = _al_list_next (scene->npcs, item); } //aabb_collide_fill_cache (scene->npc_tree, &box, &npc_collisions); //if (scene->npc_tree->num_collisions > 0) { // item = _al_list_front (npc_collisions.boxes); // float max_dist = 0; // while (item) { // BOX *colbox = _al_list_item_data (item); // SPRITE_NPC *npc = colbox->data; // float dist = vsqdistance (npc->actor.box.center, game->current_actor->box.center); // if (dist < 128.0f * 128.0f && dist > max_dist) { // game->current_npc = npc; // max_dist = dist; // } // item = _al_list_next (npc_collisions.boxes, item); // } //} screen_update (&game->screen, actor->position, scene->map, dt); sprite_update (actor, dt, mean_frame_time); item = _al_list_front (scene->npcs); while (item) { SPRITE_ACTOR *npc_actor = (SPRITE_ACTOR *)_al_list_item_data (item); sprite_update (npc_actor, dt, mean_frame_time); item = _al_list_next (scene->npcs, item); } redraw = true; break; case ALLEGRO_EVENT_DISPLAY_CLOSE: game->running = false; break; default: fprintf (stderr, "Unsupported event received: %d\n", event.type); break; } } aabb_free_collisions (&collisions); aabb_free_collisions (&portal_collisions); aabb_free_collisions (&npc_collisions); }
int main(void) { ALLEGRO_VERTEX v[8]; ALLEGRO_DISPLAY * display; ALLEGRO_TRANSFORM perst; ALLEGRO_TRANSFORM camt; ALLEGRO_BITMAP * texture, * texture2; ALLEGRO_EVENT_QUEUE * queue; ALLEGRO_EVENT event; ALLEGRO_FONT * font; int busy = 1; float cx = 0; float cy = -2; // 128; float cz = 0; int face = 0; int hori = 0; float angle = 0; float theta = 0; float near = 2; float far = 8192; float zoom = 1; float scale = 1.0; float us = 20; float ratio = 480.0 / 640.0; al_init(); al_init_image_addon(); al_init_font_addon(); al_install_keyboard(); font = al_create_builtin_font(); queue = al_create_event_queue(); al_set_new_display_option(ALLEGRO_DEPTH_SIZE, 16, ALLEGRO_SUGGEST); display = al_create_display(640, 480); al_register_event_source(queue, al_get_keyboard_event_source()); texture = al_load_bitmap("tile_1.png"); texture2 = al_load_bitmap("tile_2.png"); /* Allegro coordinates: +Y is down, +X is to the right, * and +Z comes "out of" the screen. * */ while (busy) { init_vertex(v+0, 0, 0, 0, 0, 0, 1, 0, 0, 1); init_vertex(v+1, 0, 0, us, 0, 256, 0, 1, 0, 1); init_vertex(v+2, us, 0, us, 256, 256, 0, 0, 1, 1); init_vertex(v+3, us, 0, 0, 256, 0, 1, 1, 0, 1); init_vertex(v+4, us, -us, 0, 256, 256, 1, 0, 1, 1); init_vertex(v+5, 0, -us, 0, 256, 0, 0, 1, 1, 1); init_vertex(v+6, 0, -us, us, 256, 256, 0, 0, 0, 1); init_vertex(v+7, 0, 0, us, 0, 256, 1, 1, 1, 1); al_identity_transform(&camt); al_scale_transform_3d(&camt, scale, scale, scale); al_translate_transform_3d(&camt, cx, cy, cz); angle = face * 0.125 * ALLEGRO_PI; al_rotate_transform_3d(&camt, 0, -1, 0, angle); theta = hori * 0.125 * ALLEGRO_PI; al_rotate_transform_3d(&camt, -1, 0, 0, theta); al_use_transform(&camt); // al_set_projection_transform(display, &perst); al_clear_to_color(al_map_rgb_f(0.75, 0.75, 0.95)); al_set_render_state(ALLEGRO_DEPTH_TEST, 1); al_clear_depth_buffer(far); al_identity_transform(&perst); al_perspective_transform(&perst, -1, ratio, near, 1, -ratio, far); al_use_projection_transform(&perst); al_draw_filled_rectangle(0, 0, 4, 5, al_map_rgb_f(0, 0.25, 0.25)); al_draw_prim(v, NULL, texture, 0, 8, ALLEGRO_PRIM_TRIANGLE_FAN); draw_textured_colored_rectangle_3d(0 , -us, 0, us, us, 0, 1.0, 1.0, texture2, al_map_rgb_f(1,1,1)); draw_textured_colored_rectangle_3d(0 , -us, 0, 0, us, us, 1.0, 1.0, texture2, al_map_rgb_f(1,1,1)); draw_textured_colored_rectangle_3d(0 , 0, 0, us, 0, us, 1.0, 1.0, texture2, al_map_rgb_f(1,1,1)); al_identity_transform(&perst); al_orthographic_transform(&perst, 0, 0, -1.0, 640, 480, 1.0); al_identity_transform(&camt); al_use_projection_transform(&perst); al_use_transform(&camt); al_draw_filled_rectangle(111, 22, 133, 44, al_map_rgb_f(0.25, 0.25, 0)); al_draw_multiline_textf(font, al_map_rgb_f(1,1,1), 10, 10, 620, 0, 0, "Coords: (%f %f %f)\nAngle: (%f %f)\nView: [%f %f %f %f]\nScale: %f", cx, cy, cz, angle, theta, near, far, zoom, scale); al_flip_display(); al_wait_for_event(queue, &event); if (event.type == ALLEGRO_EVENT_KEY_DOWN) { switch (event.keyboard.keycode) { case ALLEGRO_KEY_RIGHT: cx += 8; break; case ALLEGRO_KEY_LEFT: cx -= 8; break; case ALLEGRO_KEY_UP: cy += 8; break; case ALLEGRO_KEY_DOWN: cy -= 8; break; case ALLEGRO_KEY_HOME: cz += 8; break; case ALLEGRO_KEY_END: cz -= 8; break; case ALLEGRO_KEY_R: face++; break; case ALLEGRO_KEY_L: face--; break; case ALLEGRO_KEY_H: hori++; break; case ALLEGRO_KEY_G: hori--; break; case ALLEGRO_KEY_N: near *= 2.0; break; case ALLEGRO_KEY_M: near /= 2.0; break; case ALLEGRO_KEY_F: far += 64; break; case ALLEGRO_KEY_V: far -= 64; break; case ALLEGRO_KEY_Z: zoom *= 2.0f; break; case ALLEGRO_KEY_S: zoom /= 2.0f; break; case ALLEGRO_KEY_A: scale *= 2.0f; break; case ALLEGRO_KEY_Q: scale /= 2.0f; break; case ALLEGRO_KEY_ESCAPE: busy = 0 ; break; default: break; } } } al_destroy_bitmap(texture); al_destroy_bitmap(texture2); return 0; }