a-game

2D platformer written from scratch.
git clone git://git.amin.space/a-game.git
Log | Files | Refs | README | LICENSE

commit 359cee0b96a22775d22ca9c07c6c2a671c57bc94
parent d7eb12f2301685649964c47cb4a9025c5bc8506a
Author: amin <dev@aminmesbah.com>
Date:   Mon, 10 Jun 2019 05:56:39 +0000

Compress and reduce game update code

FossilOrigin-Name: 5ad0c313ea09ed143d6627734825b1256d23050935c3d2726add39b4b12f31da
Diffstat:
Msrc/am_math.h | 28++++++++++++++++++++++++++++
Msrc/game.c | 228+++++++++++++++++++++++--------------------------------------------------------
2 files changed, 93 insertions(+), 163 deletions(-)

diff --git a/src/am_math.h b/src/am_math.h @@ -528,6 +528,8 @@ enum MathRectEdge RECT_EDGE_TOP, RECT_EDGE_LEFT, RECT_EDGE_RIGHT, + + NUM_RECT_EDGES, }; internal inline segment math_rect_get_edge(rect r, enum MathRectEdge e) @@ -552,6 +554,7 @@ internal inline segment math_rect_get_edge(rect r, enum MathRectEdge e) case RECT_EDGE_RIGHT: edge = (segment) {se, ne}; break; + case NUM_RECT_EDGES: // fallthrough default: assert(false); break; @@ -559,6 +562,31 @@ internal inline segment math_rect_get_edge(rect r, enum MathRectEdge e) return edge; } +internal v2 math_rect_get_normal(enum MathRectEdge e) +{ + v2 normal = {0}; + switch(e) + { + case RECT_EDGE_BOTTOM: + normal = (v2) {0.0f, -1.0f}; + break; + case RECT_EDGE_TOP: + normal = (v2) {0.0f, 1.0f}; + break; + case RECT_EDGE_LEFT: + normal = (v2) {-1.0f, 0.0f}; + break; + case RECT_EDGE_RIGHT: + normal = (v2) {1.0f, 0.0f}; + break; + case NUM_RECT_EDGES: // fallthrough + default: + assert(false); + break; + } + return normal; +} + internal inline bool math_in_interval_open(f32 n, f32 min, f32 max) { assert(min <= max); diff --git a/src/game.c b/src/game.c @@ -149,10 +149,7 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga }; viewport.max = math_v2_a(viewport.min, viewport_size); - } - - { m4 view = math_m4_init_id(); // World origin is in the lower left view = math_translate(view, (v3) {0.0f, framebuffer.height, 0.0f}); @@ -160,102 +157,17 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga view = math_translate(view, (v3) {viewport.min.x, viewport.min.y, 0.0f}); view = math_scale(view, (v3) {ppm, ppm, 1.0f}); game_state->renderer.view = view; - } - // Screen origin is in the upper left - game_state->renderer.projection = math_projection_ortho(0.0f, framebuffer.width, framebuffer.height, 0.0f, -1.0f, 0.0f); + // Screen origin is in the upper left + game_state->renderer.projection = math_projection_ortho(0.0f, framebuffer.width, framebuffer.height, 0.0f, -1.0f, 0.0f); + } v2i current_room_i = game_state->player.pos.room; struct Room *current_room = world_room_get(game_state->world, current_room_i); assert(current_room); - - // game_print_player_chunk - { - v2i c_i = world_room_get_chunk_index(current_room_i); - struct WorldChunk *c = world_chunk_get(game_state->world, c_i); - assert(c); - printf("------------\n"); - printf("Current Player Room: "); - math_print(current_room_i); - printf("Current Actual Room: "); - math_print(current_room->index); - printf("Chunk Index: "); - math_print(c->index); - } - assert(math_v2i_eq(current_room_i, current_room->index)); - u32 *tiles = current_room->tiles; - - // game_render_tiles - { - for (size_t y = 0; y < ROOM_TILE_DIM_Y; y++) - { - for (size_t x = 0; x < ROOM_TILE_DIM_X; x++) - { - v2 tile_pos = { - x, - ROOM_TILE_DIM_Y - 1.0f - y, - }; - - m4 model = math_m4_init_id(); - // our square verts are anchored around the center point of the - // square, so we want to offset by 0.5 to instead have our - // anchor in the min corner - model = math_translate(model, (v3) {TILE_SIZE * 0.5f, TILE_SIZE * 0.5f, 0.0f}); - model = math_translate(model, (v3) {tile_pos.x, tile_pos.y, 0.0f}); - model = math_scale(model, (v3) {TILE_SIZE, TILE_SIZE, 1.0f}); - - v3 color; - - bool solid = tile_is_solid(tiles, tile_pos); - if (solid) - { - color = (v3) {0.4f, 0.4f, 0.4f}; - } - else - { - color = (v3) {0.3f, 0.3f, 0.3f}; - } - - { - struct Entity player = game_state->player; - f32 half_w = 0.5f * player.dimensions.width; - f32 half_h = 0.5f * player.dimensions.height; - rect player_aabb = { - .min = {player.pos.local.x - half_w, player.pos.local.y - half_h}, - .max = {player.pos.local.x + half_w, player.pos.local.y + half_h}, - }; - rect tile_aabb = { - .min = tile_pos, - .max = {tile_pos.x + TILE_SIZE, tile_pos.y + TILE_SIZE}, - }; - - bool player_is_in_tile = math_intersect_aabb_aabb(player_aabb, tile_aabb); - if (player_is_in_tile) - { - color = (v3) {0.4f, 0.8f, 0.4f}; - } - if (player_is_in_tile && solid) - { - color = (v3) {0.8f, 0.4f, 0.4f}; - assert(false); - } - } - - renderer_job_enqueue( - &game_state->renderer, - (struct RenderJob) { - .ebo = game_state->renderer.quad_ebo, - .color = color, - .model = model, - .layer = RENDER_LAYER_TILES, - }); - } - } - } - // game_update_player { struct Entity *player = &game_state->player; @@ -350,7 +262,7 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga }); // NOTE(amin): pointer alias - u32 *tile_set = tiles; + u32 *tile_set = current_room->tiles; bool tile_is_past_world_edge = false; if (!math_v2i_eq(tile_pos.room, current_room_i)) { @@ -374,82 +286,30 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga RENDER_COLLISION_DEBUG_QUAD(tile_aabb, ((v3) {0.8f, 0.4f, 0.4f})); rect tile_player_sum = math_minkowski_sum_rect_rect(tile_aabb, player->dimensions); - segment tile_sum_b = math_rect_get_edge(tile_player_sum, RECT_EDGE_BOTTOM); - segment tile_sum_t = math_rect_get_edge(tile_player_sum, RECT_EDGE_TOP); - segment tile_sum_l = math_rect_get_edge(tile_player_sum, RECT_EDGE_LEFT); - segment tile_sum_r = math_rect_get_edge(tile_player_sum, RECT_EDGE_RIGHT); - - v2 norm_b = {0.0f, -1.0f}; - v2 norm_t = {0.0f, 1.0f}; - v2 norm_l = {-1.0f, 0.0f}; - v2 norm_r = {1.0f, 0.0f}; - if (!wall_is_internal(game_state->world, current_room_i, math_rect_get_edge(tile_aabb, RECT_EDGE_BOTTOM))) + for (enum MathRectEdge edge = 0; edge < NUM_RECT_EDGES; edge++) { - struct WallCollision bottom = get_wall_collision(player->pos.local, new_p, tile_sum_b, norm_b); - if (bottom.collision_occurred) - { - if (smallest_distance_scale_factor > bottom.distance_scale_factor) - { - smallest_distance_scale_factor = bottom.distance_scale_factor; - } - wall_normal = norm_b; - rect collision = { - .min = tile_aabb.min, - .max = {tile_aabb.max.x, tile_aabb.min.y + 0.2f}, - }; - RENDER_COLLISION_DEBUG_QUAD(collision, ((v3) {1.0f, 0.0f, 0.0f})); - } - } - if (!wall_is_internal(game_state->world, current_room_i, math_rect_get_edge(tile_aabb, RECT_EDGE_TOP))) - { - struct WallCollision top = get_wall_collision(player->pos.local, new_p, tile_sum_t, norm_t); - if (top.collision_occurred) - { - if (smallest_distance_scale_factor > top.distance_scale_factor) - { - smallest_distance_scale_factor = top.distance_scale_factor; - } - wall_normal = norm_t; - rect collision = { - .min = {tile_aabb.min.x, tile_aabb.max.y - 0.2f}, - .max = tile_aabb.max, - }; - RENDER_COLLISION_DEBUG_QUAD(collision, ((v3) {0.0f, 1.0f, 0.0f})); - } - } - if (!wall_is_internal(game_state->world, current_room_i, math_rect_get_edge(tile_aabb, RECT_EDGE_LEFT))) - { - struct WallCollision left = get_wall_collision(player->pos.local, new_p, tile_sum_l, norm_l); - if (left.collision_occurred) - { - if (smallest_distance_scale_factor > left.distance_scale_factor) - { - smallest_distance_scale_factor = left.distance_scale_factor; - } - wall_normal = norm_l; - rect collision = { - .min = tile_aabb.min, - .max = {tile_aabb.min.x + 0.2f, tile_aabb.max.y}, - }; - RENDER_COLLISION_DEBUG_QUAD(collision, ((v3) {0.0f, 0.0f, 1.0f})); - } - } - if (!wall_is_internal(game_state->world, current_room_i, math_rect_get_edge(tile_aabb, RECT_EDGE_RIGHT))) - { - struct WallCollision right = get_wall_collision(player->pos.local, new_p, tile_sum_r, norm_r); - if (right.collision_occurred) + segment player_sum_wall = math_rect_get_edge(tile_player_sum, edge); + v2 normal = math_rect_get_normal(edge); + segment tile_wall = math_rect_get_edge(tile_aabb, edge); + + if (!wall_is_internal(game_state->world, current_room_i, tile_wall)) { - if (smallest_distance_scale_factor > right.distance_scale_factor) + struct WallCollision c = get_wall_collision(player->pos.local, new_p, player_sum_wall, normal); + if (c.collision_occurred) { - smallest_distance_scale_factor = right.distance_scale_factor; + if (smallest_distance_scale_factor > c.distance_scale_factor) + { + smallest_distance_scale_factor = c.distance_scale_factor; + } + wall_normal = normal; + RENDER_COLLISION_DEBUG_QUAD( + ((rect) { + .min = tile_wall.min, + .max = math_v2_a(tile_wall.max, math_v2f_m(normal, -0.2f)), + }), + ((v3) {0.0f, 0.8f, 0.0f})); } - wall_normal = norm_r; - rect collision = { - .min = {tile_aabb.max.x - 0.2f, tile_aabb.min.y}, - .max = tile_aabb.max, - }; - RENDER_COLLISION_DEBUG_QUAD(collision, ((v3) {1.0f, 0.0f, 1.0f})); } } } @@ -541,6 +401,48 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga }); } + // game_render_tiles + { + for (size_t y = 0; y < ROOM_TILE_DIM_Y; y++) + { + for (size_t x = 0; x < ROOM_TILE_DIM_X; x++) + { + v2 tile_pos = { + x, + ROOM_TILE_DIM_Y - 1.0f - y, + }; + + m4 model = math_m4_init_id(); + // our square verts are anchored around the center point of the + // square, so we want to offset by 0.5 to instead have our + // anchor in the min corner + model = math_translate(model, (v3) {TILE_SIZE * 0.5f, TILE_SIZE * 0.5f, 0.0f}); + model = math_translate(model, (v3) {tile_pos.x, tile_pos.y, 0.0f}); + model = math_scale(model, (v3) {TILE_SIZE, TILE_SIZE, 1.0f}); + + v3 color; + bool solid = tile_is_solid(current_room->tiles, tile_pos); + if (solid) + { + color = (v3) {0.4f, 0.4f, 0.4f}; + } + else + { + color = (v3) {0.3f, 0.3f, 0.3f}; + } + + renderer_job_enqueue( + &game_state->renderer, + (struct RenderJob) { + .ebo = game_state->renderer.quad_ebo, + .color = color, + .model = model, + .layer = RENDER_LAYER_TILES, + }); + } + } + } + renderer_jobs_sort(&game_state->renderer, &game_state->world_allocator); renderer_jobs_draw(&game_state->renderer); }