ENTRYPOINT void draw_camera (ModeInfo *mi) { camera_configuration *bp = &bps[MI_SCREEN(mi)]; Display *dpy = MI_DISPLAY(mi); Window window = MI_WINDOW(mi); GLfloat camera_size; int i; if (!bp->glx_context) return; glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context)); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix (); # ifdef HAVE_MOBILE glRotatef (current_device_rotation(), 0, 0, 1); /* right side up */ # endif gltrackball_rotate (bp->user_trackball); # ifdef HAVE_MOBILE { GLfloat s = 0.6; glScalef (s, s, s); } # endif # ifdef DEBUG if (debug_p) { GLfloat s = 0.2; glScalef (s, s, s); glRotatef (30, 0, 1, 0); glRotatef (15, 1, 0, 0); glTranslatef (0, 0, -80); } # endif mi->polygon_count = 0; camera_size = 5; if (MI_COUNT(mi) <= 2) /* re-frame the scene a little bit */ glTranslatef (0, -1, 7); if (MI_COUNT(mi) >= 20) glTranslatef (0, -1.5, -5); if (MI_COUNT(mi) >= 40) glTranslatef (0, 2, -15); glScalef (camera_size, camera_size, camera_size); /* +Z is toward sky; +X is toward the right along the back wall; +Y is toward the viewer. */ glRotatef (-90, 1, 0, 0); glScalef (1, -1, 1); glPushMatrix(); glScalef (1/camera_size, 1/camera_size, 1/camera_size); glTranslatef (0, -2.38, -8); /* Move the ground down and back */ glCallList (bp->dlists[GROUND]); mi->polygon_count += ground->points; glPopMatrix(); { pedestrian *p, *p2; for (p = bp->pedestrians, p2 = p ? p->next : 0; p; p = p2, p2 = p2 ? p2->next : 0) { mi->polygon_count += draw_pedestrian (mi, p); tick_pedestrian (mi, p); /* might free p */ } if (!bp->pedestrians || !(random() % MAX (1, (int) (200 / speed_arg)))) add_pedestrian (mi); } for (i = 0; i < bp->ncameras; i++) { camera *c = &bp->cameras[i]; mi->polygon_count += draw_camera_1 (mi, c); tick_camera (mi, c); } for (i = 0; i < bp->ncameras; i++) { camera *c = &bp->cameras[i]; if (c->state == ZOT) /* Do this last, for alpha blending */ mi->polygon_count += draw_ray (mi, c); } glPopMatrix (); if (mi->fps_p) do_fps (mi); glFinish(); glXSwapBuffers(dpy, window); }
void tick_game(struct GameMemory *memory, struct Input *input, uint32 screen_width, uint32 screen_height, float dt) { struct GameState *game_state = (struct GameState *)memory->game_memory; struct RenderBuffer *render_buffer = (struct RenderBuffer *)memory->render_memory; clear_render_buffer(render_buffer); for (uint32 i = 0; i < game_state->visibility_graph.vertex_count; ++i) { vec2 vertex = game_state->visibility_graph.vertices[i]; draw_world_quad_buffered(render_buffer, vertex, vec2_scalar(0.1f), vec4_zero(), vec3_new(0, 1, 1)); } for (uint32 i = 0; i < game_state->visibility_graph.edge_count; ++i) { uint32 *edge = &game_state->visibility_graph.edges[i][0]; vec2 p0 = game_state->visibility_graph.vertices[edge[0]]; vec2 p1 = game_state->visibility_graph.vertices[edge[1]]; draw_world_line_buffered(render_buffer, p0, p1, vec3_new(1, 1, 0)); } if (mouse_down(MOUSE_LEFT, input)) { struct AABB box = calc_mouse_selection_box(input, MOUSE_LEFT); vec2 size = vec2_sub(box.max, box.min); vec2 bottom_left = vec2_new(box.min.x, box.max.y); vec2 bottom_right = vec2_new(box.max.x, box.max.y); vec2 top_left = vec2_new(box.min.x, box.min.y); vec2 top_right = vec2_new(box.max.x, box.min.y); const uint32 outline_thickness = 1; draw_screen_quad_buffered(render_buffer, top_left, vec2_new(size.x, outline_thickness), vec4_zero(), vec3_new(1, 1, 0)); draw_screen_quad_buffered(render_buffer, bottom_left, vec2_new(size.x, outline_thickness), vec4_zero(), vec3_new(1, 1, 0)); draw_screen_quad_buffered(render_buffer, top_left, vec2_new(outline_thickness, size.y), vec4_zero(), vec3_new(1, 1, 0)); draw_screen_quad_buffered(render_buffer, top_right, vec2_new(outline_thickness, size.y), vec4_zero(), vec3_new(1, 1, 0)); } if (mouse_released(MOUSE_LEFT, input)) { // Clear previous selection. game_state->selected_ship_count = 0; struct AABB screen_selection_box = calc_mouse_selection_box(input, MOUSE_LEFT); // Because screen space y-values are inverted, these two results have conflicting // y-values, i.e. screen_to_world_min.y is actually the maximum y. These values // are then properly min/maxed and stored correctly in world_selection_box. vec2 screen_to_world_min = screen_to_world_coords(screen_selection_box.min, &game_state->camera, screen_width, screen_height); vec2 screen_to_world_max = screen_to_world_coords(screen_selection_box.max, &game_state->camera, screen_width, screen_height); struct AABB world_selection_box; world_selection_box.min = min_vec2(screen_to_world_min, screen_to_world_max); world_selection_box.max = max_vec2(screen_to_world_min, screen_to_world_max); // Add colliding ships to the selection list. // TODO: optimize, spatial grid hash? for (uint32 i = 0; i < game_state->ship_count; ++i) { struct Ship *ship = &game_state->ships[i]; struct AABB ship_aabb = aabb_from_transform(ship->position, ship->size); vec2 center = vec2_div(vec2_add(ship_aabb.min, ship_aabb.max), 2.0f); if (aabb_aabb_intersection(world_selection_box, ship_aabb)) game_state->selected_ships[game_state->selected_ship_count++] = ship->id; } if (game_state->selected_ship_count > 0) fprintf(stderr, "selected %u ships\n", game_state->selected_ship_count); } if (mouse_down(MOUSE_RIGHT, input)) { vec2 target_position = screen_to_world_coords(input->mouse_position, &game_state->camera, screen_width, screen_height); for (uint32 i = 0; i < game_state->selected_ship_count; ++i) { uint32 id = game_state->selected_ships[i]; struct Ship *ship = get_ship_by_id(game_state, id); ship->target_position = target_position; ship->move_order = true; } } // Outline selected ships. for (uint32 i = 0; i < game_state->selected_ship_count; ++i) { uint32 id = game_state->selected_ships[i]; struct Ship *ship = get_ship_by_id(game_state, id); draw_world_quad_buffered(render_buffer, ship->position, vec2_mul(ship->size, 1.1f), vec4_zero(), vec3_new(0, 1, 0)); if (ship->move_order) draw_world_quad_buffered(render_buffer, ship->target_position, vec2_new(0.5f, 0.5f), vec4_zero(), vec3_new(0, 1, 0)); } // Handle move orders. for (uint32 i = 0; i < game_state->ship_count; ++i) { struct Ship *ship = &game_state->ships[i]; if (ship->move_order) { vec2 direction = vec2_zero(); /* if (vec2_length2(direction) < FLOAT_EPSILON) direction = vec2_normalize(vec2_sub(ship->target_position, ship->position)); */ ship->move_velocity = vec2_mul(direction, 2.0f); /* vec2 direction = vec2_normalize(vec2_sub(ship->target_position, ship->position)); ship->move_velocity = vec2_mul(direction, 2.0f); */ if (vec2_distance2(ship->position, ship->target_position) < 0.1f) { ship->move_velocity = vec2_zero(); ship->move_order = false; } } } tick_camera(input, &game_state->camera, dt); tick_combat(game_state, dt); tick_physics(game_state, dt); }