a-game

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

commit 487823facfe3c4477fc01b3951e369b3da1e6f12
parent e42269fa3745f6c6610263ee5bd8d58fcefd3ff0
Author: amin <dev@aminmesbah.com>
Date:   Sat, 27 Apr 2019 02:21:04 +0000

Use AbsolutePos as player position

FossilOrigin-Name: 37236722038689f009aa238e57c579c9ced9398f701d1795bc53ecd6a7e8be0b
Diffstat:
Msrc/game.c | 78+++++++++++++++++++++++++++++++++++++-----------------------------------------
Msrc/game.h | 20+++++++++++---------
2 files changed, 48 insertions(+), 50 deletions(-)

diff --git a/src/game.c b/src/game.c @@ -2,8 +2,6 @@ #include "glad.c" #include "shader.c" -// One tile is one square meter -#define TILE_SIZE 1.0f // TODO: delete #define NUM_ROOMS 2 @@ -18,13 +16,12 @@ internal void game_init(struct GameMemory *game_memory, v2u framebuffer) { struct GameState *game_state = game_memory->game_state; - game_state->player_pos_absolute = (struct AbsolutePos) { - .room_index = {0, 0}, - .room_offset = {12.5f, 5.0f}, - }; // init player - game_state->player.pos = game_state->player_pos_absolute.room_offset; + game_state->player.pos = (struct AbsolutePos) { + .room = {0, 0}, + .local = {12.5f, 5.0f}, + }; // In Knytt, the player is 9 by 14 texels and a tile is 24 by 24 texels. // These dimensions are relative to a square 'meter', one tile @@ -97,29 +94,29 @@ internal struct AbsolutePos pos_recanonicalize(struct AbsolutePos p) struct AbsolutePos p_final = p; v2i room_index_delta = {0}; - if (p.room_offset.x < 0.0f) + if (p.local.x < 0.0f) { room_index_delta.x -= 1; - p_final.room_offset.x = glmth_wrap(p.room_offset.x, 0.0f, ROOM_TILE_DIM_X); + p_final.local.x = glmth_wrap(p.local.x, 0.0f, ROOM_TILE_DIM_X); } - else if (p.room_offset.x > ROOM_TILE_DIM_X) + else if (p.local.x > ROOM_TILE_DIM_X) { room_index_delta.x += 1; - p_final.room_offset.x = glmth_wrap(p.room_offset.x, 0.0f, ROOM_TILE_DIM_X); + p_final.local.x = glmth_wrap(p.local.x, 0.0f, ROOM_TILE_DIM_X); } - if (p.room_offset.y < 0.0f) + if (p.local.y < 0.0f) { room_index_delta.y -= 1; - p_final.room_offset.y = glmth_wrap(p.room_offset.y, 0.0f, ROOM_TILE_DIM_Y); + p_final.local.y = glmth_wrap(p.local.y, 0.0f, ROOM_TILE_DIM_Y); } - else if (p.room_offset.y > ROOM_TILE_DIM_Y) + else if (p.local.y > ROOM_TILE_DIM_Y) { room_index_delta.y += 1; - p_final.room_offset.y = glmth_wrap(p.room_offset.y, 0.0f, ROOM_TILE_DIM_Y); + p_final.local.y = glmth_wrap(p.local.y, 0.0f, ROOM_TILE_DIM_Y); } - p_final.room_index = glmth_v2i_a(p.room_index, room_index_delta); + p_final.room = glmth_v2i_a(p.room, room_index_delta); return p_final; } @@ -183,6 +180,8 @@ internal struct WallCollision get_wall_collision(v2 entity_p_initial, v2 entity_ if (theta_is_obtuse) { f32 wall_position = wall.min.E[wall_normal_axis]; + + // Not to be confused with the anime about street racing f32 initial_d = wall_position - entity_p_initial.E[wall_normal_axis]; f32 segment_scale_factor = initial_d / player_delta.E[wall_normal_axis]; @@ -222,7 +221,7 @@ internal u32 get_tile_value(u32 *tiles, v2 tile_pos) (v2) {0})); u32 tile_i_linearized = (ROOM_TILE_DIM_X * tile_i_2d.y) + tile_i_2d.x; - assert(tile_i_linearized < ROOM_TILE_DIM_X * ROOM_TILE_DIM_Y); + assert(tile_i_linearized < ROOM_TILE_COUNT); u32 tile_value = tiles[tile_i_linearized]; return tile_value; @@ -382,7 +381,7 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga // TODO: This is, of course, just temporary. Delete it. struct Room *rooms[NUM_ROOMS] = {&collision_test_zone, &knytt_hanging_fly_village}; - v2i current_room_i = game_state->player_pos_absolute.room_index; + v2i current_room_i = game_state->player.pos.room; struct RoomSearchResult r = get_room_at_index(rooms, NUM_ROOMS, current_room_i); assert(r.room_found); struct Room *current_room = rooms[r.room_array_index]; @@ -427,8 +426,8 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga f32 half_w = 0.5f * player.dimensions.width; f32 half_h = 0.5f * player.dimensions.height; rect player_aabb = { - .min = {player.pos.x - half_w, player.pos.y - half_h}, - .max = {player.pos.x + half_w, player.pos.y + half_h}, + .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, @@ -511,11 +510,11 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga { #define RENDER_COLLISION_DEBUG_QUAD(r, c) render_debug_quad(game_state, (r), (c), &view, &projection); v2 player_delta = glmth_v2f_m(player->velocity, dt); - v2 new_p = glmth_v2_a(player->pos, player_delta); + v2 new_p = glmth_v2_a(player->pos.local, player_delta); rect player_traversal_bb = { - .min = {glmth_min(player->pos.x, new_p.x), glmth_min(player->pos.y, new_p.y)}, - .max = {glmth_max(player->pos.x, new_p.x), glmth_max(player->pos.y, new_p.y)}, + .min = {glmth_min(player->pos.local.x, new_p.x), glmth_min(player->pos.local.y, new_p.y)}, + .max = {glmth_max(player->pos.local.x, new_p.x), glmth_max(player->pos.local.y, new_p.y)}, }; rect player_traversal_occupancy_bb = glmth_minkowski_sum_rect_rect(player_traversal_bb, player->dimensions); @@ -571,7 +570,7 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga if (!wall_is_screen_edge(tiles, glmth_rect_get_edge(tile_aabb, RECT_EDGE_BOTTOM)) && !wall_is_internal(tiles, glmth_rect_get_edge(tile_aabb, RECT_EDGE_BOTTOM))) { - struct WallCollision bottom = get_wall_collision(player->pos, new_p, tile_sum_b, norm_b); + 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) @@ -588,7 +587,7 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga } if (!wall_is_screen_edge(tiles, glmth_rect_get_edge(tile_aabb, RECT_EDGE_TOP)) && !wall_is_internal(tiles, glmth_rect_get_edge(tile_aabb, RECT_EDGE_TOP))) { - struct WallCollision top = get_wall_collision(player->pos, new_p, tile_sum_t, norm_t); + 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) @@ -605,7 +604,7 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga } if (!wall_is_screen_edge(tiles, glmth_rect_get_edge(tile_aabb, RECT_EDGE_LEFT)) && !wall_is_internal(tiles, glmth_rect_get_edge(tile_aabb, RECT_EDGE_LEFT))) { - struct WallCollision left = get_wall_collision(player->pos, new_p, tile_sum_l, norm_l); + 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) @@ -622,7 +621,7 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga } if (!wall_is_screen_edge(tiles, glmth_rect_get_edge(tile_aabb, RECT_EDGE_RIGHT)) && !wall_is_internal(tiles, glmth_rect_get_edge(tile_aabb, RECT_EDGE_RIGHT))) { - struct WallCollision right = get_wall_collision(player->pos, new_p, tile_sum_r, norm_r); + struct WallCollision right = get_wall_collision(player->pos.local, new_p, tile_sum_r, norm_r); if (right.collision_occurred) { if (smallest_distance_scale_factor > right.distance_scale_factor) @@ -642,23 +641,23 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga } v2 delta_to_nearest_collision = glmth_v2f_m(player_delta, smallest_distance_scale_factor); - v2 nearest_collision_p = glmth_v2_a(player->pos, delta_to_nearest_collision); + v2 nearest_collision_p = glmth_v2_a(player->pos.local, delta_to_nearest_collision); f32 epsilon = 0.0001f; rect local_inhabitable_region = { .min = { - glmth_min(player->pos.x, nearest_collision_p.x + epsilon), - glmth_min(player->pos.y, nearest_collision_p.y + epsilon), + glmth_min(player->pos.local.x, nearest_collision_p.x + epsilon), + glmth_min(player->pos.local.y, nearest_collision_p.y + epsilon), }, .max = { - glmth_max(player->pos.x, nearest_collision_p.x - epsilon), - glmth_max(player->pos.y, nearest_collision_p.y - epsilon), + glmth_max(player->pos.local.x, nearest_collision_p.x - epsilon), + glmth_max(player->pos.local.y, nearest_collision_p.y - epsilon), }, }; - player->pos = nearest_collision_p; - glmth_clamp(&player->pos.x, local_inhabitable_region.min.x, local_inhabitable_region.max.x); - glmth_clamp(&player->pos.y, local_inhabitable_region.min.y, local_inhabitable_region.max.y); + player->pos.local = nearest_collision_p; + glmth_clamp(&player->pos.local.x, local_inhabitable_region.min.x, local_inhabitable_region.max.x); + glmth_clamp(&player->pos.local.y, local_inhabitable_region.min.y, local_inhabitable_region.max.y); // NOTE(amin): // n * dot(v, n) @@ -672,16 +671,13 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga player->velocity = glmth_v2_s(player->velocity, colliding_velocity_component); player_delta = glmth_v2f_m(player->velocity, dt); - new_p = glmth_v2_a(player->pos, player_delta); + new_p = glmth_v2_a(player->pos.local, player_delta); remaining_time_factor -= smallest_distance_scale_factor; } } #undef RENDER_COLLISION_DEBUG_QUAD - game_state->player_pos_absolute.room_offset = player->pos; - struct AbsolutePos new_canonical_p = pos_recanonicalize(game_state->player_pos_absolute); - game_state->player_pos_absolute = new_canonical_p; - player->pos = game_state->player_pos_absolute.room_offset; + player->pos = pos_recanonicalize(player->pos); } // render player @@ -690,7 +686,7 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga struct Entity player = game_state->player; m4 model = glmth_m4_init_id(); - model = glmth_translate(model, (v3) {player.pos.x, player.pos.y, 0.0f}); + model = glmth_translate(model, (v3) {player.pos.local.x, player.pos.local.y, 0.0f}); model = glmth_scale(model, (v3) {player.dimensions.x, player.dimensions.y, 1.0f}); v3 color = (v3) { 1.0f, 0.0f, 1.0f }; diff --git a/src/game.h b/src/game.h @@ -12,8 +12,11 @@ #include "shader.h" #include "platform.h" +// One tile is one square meter +#define TILE_SIZE 1.0f #define ROOM_TILE_DIM_X 25 #define ROOM_TILE_DIM_Y 10 +#define ROOM_TILE_COUNT ROOM_TILE_DIM_X * ROOM_TILE_DIM_Y #define ROOM_ASPECT_RATIO (f32)ROOM_TILE_DIM_X / (f32)ROOM_TILE_DIM_Y struct RendererState @@ -25,31 +28,30 @@ struct RendererState struct Shader shader; }; +struct AbsolutePos +{ + v2i room; + v2 local; +}; + struct Entity { + struct AbsolutePos pos; v2 acceleration; v2 velocity; - v2 pos; v2 dimensions; }; struct Room { v2i index; - u32 tiles[ROOM_TILE_DIM_Y * ROOM_TILE_DIM_X]; -}; - -struct AbsolutePos -{ - v2i room_index; - v2 room_offset; + u32 tiles[ROOM_TILE_COUNT]; }; struct GameState { struct RendererState renderer; struct Entity player; - struct AbsolutePos player_pos_absolute; }; internal void game_init(struct GameMemory *game_memory, v2u framebuffer);