commit c7a57149e4dd3faee96fa81f92e7d23a9a181630
parent c9251221fc319bf126f25bf9b706b943a76ad6a2
Author: amin <dev@aminmesbah.com>
Date: Tue, 30 Apr 2019 04:01:58 +0000
Split some code out into new files
FossilOrigin-Name: afc6d004125b330cca89179671fd1990838767e358bff799b88783b57438d209
Diffstat:
A | src/collision.c | | | 61 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | src/game.c | | | 219 | ++++--------------------------------------------------------------------------- |
M | src/game.h | | | 20 | +------------------- |
A | src/world.c | | | 138 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | src/world.h | | | 18 | ++++++++++++++++++ |
5 files changed, 227 insertions(+), 229 deletions(-)
diff --git a/src/collision.c b/src/collision.c
@@ -0,0 +1,61 @@
+struct WallCollision
+{
+ bool collision_occurred;
+ f32 distance_scale_factor;
+};
+
+internal struct WallCollision get_wall_collision(v2 entity_p_initial, v2 entity_p_final, segment wall, v2 wall_normal)
+
+{
+ struct WallCollision result = {0};
+ result.collision_occurred = false;
+
+ assert(math_v2_le(wall.min, wall.max));
+
+ bool wall_is_horizontal = wall.min.y == wall.max.y;
+ bool wall_is_vertical = wall.min.x == wall.max.x;
+ assert(wall_is_horizontal || wall_is_vertical);
+
+ enum VectorAxis wall_axis = AXIS_X;
+ enum VectorAxis wall_normal_axis = AXIS_Y;
+ if (wall_is_vertical)
+ {
+ wall_axis = AXIS_Y;
+ wall_normal_axis = AXIS_X;
+ }
+
+ v2 player_delta = math_v2_s(entity_p_final, entity_p_initial);
+
+ // NOTE(amin): We needn't normalize player_delta here because its magnitude
+ // becomes irrelevant as the value of cos(theta) nears zero, and we are
+ // concerned only about the behavior near pi/2 and 3pi/2, where cos(theta)
+ // is zero. Therefore we simply treat player_delta as if it _were_
+ // normalized.
+ f32 cos_theta = math_v2_dot(player_delta, wall_normal);
+
+ bool theta_is_obtuse = cos_theta < 0.0f;
+ 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];
+ v2 collision_point = math_v2_a(entity_p_initial, math_v2f_m(player_delta, segment_scale_factor));
+
+ if (math_in_interval_open(segment_scale_factor, 0.0f, 1.0f))
+ {
+ if (math_in_interval_open(
+ collision_point.E[wall_axis],
+ wall.min.E[wall_axis],
+ wall.max.E[wall_axis]))
+ {
+ result.collision_occurred = true;
+ result.distance_scale_factor = math_max(0.0f, segment_scale_factor);
+ }
+ }
+ }
+
+ return result;
+}
diff --git a/src/game.c b/src/game.c
@@ -2,13 +2,8 @@
#include "glad.c"
#include "shader.c"
#include "memory.c"
-
-#ifdef PLATFORM_HOTLOAD_GAME_CODE
-void game_load_opengl_symbols(void)
-{
- gladLoadGL();
-}
-#endif
+#include "collision.c"
+#include "world.c"
internal void game_init(struct GameMemory *game_memory, v2u framebuffer)
{
@@ -30,10 +25,8 @@ internal void game_init(struct GameMemory *game_memory, v2u framebuffer)
game_memory->buffer + sizeof(struct GameState),
game_memory->buffer_size - sizeof(struct GameState));
-
game_state->world = mem_st_alloc_struct(&game_state->world_allocator, struct World);
-
struct Room knytt_hanging_fly_village = {
.index = {0, 0},
.tiles = {
@@ -134,207 +127,6 @@ internal void game_init(struct GameMemory *game_memory, v2u framebuffer)
}
}
-internal struct AbsolutePos pos_recanonicalize(struct AbsolutePos p)
-{
- struct AbsolutePos p_final = p;
- v2i room_index_delta = {0};
-
- if (p.local.x < 0.0f)
- {
- room_index_delta.x -= 1;
- p_final.local.x = math_wrap(p.local.x, 0.0f, ROOM_TILE_DIM_X);
- }
- else if (p.local.x > ROOM_TILE_DIM_X)
- {
- room_index_delta.x += 1;
- p_final.local.x = math_wrap(p.local.x, 0.0f, ROOM_TILE_DIM_X);
- }
-
- if (p.local.y < 0.0f)
- {
- room_index_delta.y -= 1;
- p_final.local.y = math_wrap(p.local.y, 0.0f, ROOM_TILE_DIM_Y);
- }
- else if (p.local.y > ROOM_TILE_DIM_Y)
- {
- room_index_delta.y += 1;
- p_final.local.y = math_wrap(p.local.y, 0.0f, ROOM_TILE_DIM_Y);
- }
-
- p_final.room = math_v2i_a(p.room, room_index_delta);
- return p_final;
-}
-
-struct RoomSearchResult
-{
- bool room_found;
- size_t room_array_index;
-};
-
-internal struct RoomSearchResult get_room_at_index(struct Room *rooms, u32 num_rooms, v2i room_i)
-{
- struct RoomSearchResult result = {0};
- for (size_t i = 0; i < num_rooms; i++)
- {
- struct Room *r = &rooms[i];
- if (r->index.x == room_i.x && r->index.y == room_i.y)
- {
- result.room_found = true;
- result.room_array_index = i;
- }
- }
- return result;
-}
-
-struct WallCollision
-{
- bool collision_occurred;
- f32 distance_scale_factor;
-};
-
-internal struct WallCollision get_wall_collision(v2 entity_p_initial, v2 entity_p_final, segment wall, v2 wall_normal)
-
-{
- struct WallCollision result = {0};
- result.collision_occurred = false;
-
- assert(math_v2_le(wall.min, wall.max));
-
- bool wall_is_horizontal = wall.min.y == wall.max.y;
- bool wall_is_vertical = wall.min.x == wall.max.x;
- assert(wall_is_horizontal || wall_is_vertical);
-
- enum VectorAxis wall_axis = AXIS_X;
- enum VectorAxis wall_normal_axis = AXIS_Y;
- if (wall_is_vertical)
- {
- wall_axis = AXIS_Y;
- wall_normal_axis = AXIS_X;
- }
-
- v2 player_delta = math_v2_s(entity_p_final, entity_p_initial);
-
- // NOTE(amin): We needn't normalize player_delta here because its magnitude
- // becomes irrelevant as the value of cos(theta) nears zero, and we are
- // concerned only about the behavior near pi/2 and 3pi/2, where cos(theta)
- // is zero. Therefore we simply treat player_delta as if it _were_
- // normalized.
- f32 cos_theta = math_v2_dot(player_delta, wall_normal);
-
- bool theta_is_obtuse = cos_theta < 0.0f;
- 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];
- v2 collision_point = math_v2_a(entity_p_initial, math_v2f_m(player_delta, segment_scale_factor));
-
- if (math_in_interval_open(segment_scale_factor, 0.0f, 1.0f))
- {
- if (math_in_interval_open(
- collision_point.E[wall_axis],
- wall.min.E[wall_axis],
- wall.max.E[wall_axis]))
- {
- result.collision_occurred = true;
- result.distance_scale_factor = math_max(0.0f, segment_scale_factor);
- }
- }
- }
-
- return result;
-}
-
-internal u32 get_tile_value(u32 *tiles, v2 tile_pos)
-{
- assert(tiles);
-
- v2u tile_i_2d = {
- tile_pos.x,
- ROOM_TILE_DIM_Y - 1.0f - tile_pos.y,
- };
-
- assert(math_v2_lt(
- (v2) {tile_i_2d.x, tile_i_2d.y},
- (v2) {ROOM_TILE_DIM_X, ROOM_TILE_DIM_Y}));
-
- assert(math_v2_ge(
- (v2) {tile_i_2d.x, tile_i_2d.y},
- (v2) {0}));
-
- u32 tile_i_linearized = (ROOM_TILE_DIM_X * tile_i_2d.y) + tile_i_2d.x;
- assert(tile_i_linearized < ROOM_TILE_COUNT);
-
- u32 tile_value = tiles[tile_i_linearized];
- return tile_value;
-}
-
-internal bool tile_is_solid(u32 *tiles, v2 tile_pos)
-{
- assert(tiles);
-
- bool is_solid = false;
- u32 tile_value = get_tile_value(tiles, tile_pos);
- is_solid = tile_value > 0;
- return is_solid;
-}
-
-internal bool wall_is_screen_edge(u32 *tiles, segment wall)
-{
- assert(tiles);
-
- bool is_screen_edge = false;
- bool wall_is_horizontal = wall.min.y == wall.max.y;
- bool wall_is_vertical = wall.min.x == wall.max.x;
-
- assert(wall_is_vertical || wall_is_horizontal);
- assert(math_v2_ge(wall.min, (v2) {0}));
- assert(math_v2_le(wall.max, (v2) {ROOM_TILE_DIM_X, ROOM_TILE_DIM_Y}));
-
- if (wall_is_vertical)
- {
- is_screen_edge = wall.min.x == 0.0f || wall.min.x == ROOM_TILE_DIM_X;
- }
- else
- {
- is_screen_edge = wall.min.y == 0.0f || wall.min.y == ROOM_TILE_DIM_Y;
- }
-
- return is_screen_edge;
-}
-
-internal bool wall_is_internal(u32 *tiles, segment wall)
-{
- assert(tiles);
-
- bool is_internal = false;
- bool wall_is_horizontal = wall.min.y == wall.max.y;
- bool wall_is_vertical = wall.min.x == wall.max.x;
-
- assert(wall_is_vertical || wall_is_horizontal);
-
- v2 lesser_neighbor = {0};
- v2 greater_neighbor = {0};
-
- if (wall_is_vertical)
- {
- lesser_neighbor = (v2) {wall.min.x - TILE_SIZE, wall.min.y};
- greater_neighbor = wall.min;
- is_internal = tile_is_solid(tiles, lesser_neighbor) && tile_is_solid(tiles, greater_neighbor);
- }
- else
- {
- lesser_neighbor = (v2) {wall.min.x, wall.min.y - TILE_SIZE};
- greater_neighbor = wall.min;
- is_internal = tile_is_solid(tiles, lesser_neighbor) && tile_is_solid(tiles, greater_neighbor);
- }
-
- return is_internal;
-}
-
// NOTE(amin): For now updating and rendering are interleaved. We simulate the
// world at the same rate we render it. Our timestep is not fixed. We may want
// to change this in the future.
@@ -750,3 +542,10 @@ internal void render_debug_quad(struct GameState *game_state, rect r, v3 color,
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, initial_ebo);
}
+
+#ifdef PLATFORM_HOTLOAD_GAME_CODE
+void game_load_opengl_symbols(void)
+{
+ gladLoadGL();
+}
+#endif
diff --git a/src/game.h b/src/game.h
@@ -12,14 +12,11 @@
#include "am_math.h"
#include "shader.h"
#include "memory.h"
+#include "world.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
{
@@ -44,21 +41,6 @@ struct Entity
v2 dimensions;
};
-struct Room
-{
- v2i index;
- u32 tiles[ROOM_TILE_COUNT];
-};
-
-// TODO: delete
-#define MAX_ROOMS 120
-
-struct World
-{
- struct Room rooms[MAX_ROOMS];
- u32 num_rooms;
-};
-
struct GameState
{
struct RendererState renderer;
diff --git a/src/world.c b/src/world.c
@@ -0,0 +1,138 @@
+internal struct AbsolutePos pos_recanonicalize(struct AbsolutePos p)
+{
+ struct AbsolutePos p_final = p;
+ v2i room_index_delta = {0};
+
+ if (p.local.x < 0.0f)
+ {
+ room_index_delta.x -= 1;
+ p_final.local.x = math_wrap(p.local.x, 0.0f, ROOM_TILE_DIM_X);
+ }
+ else if (p.local.x > ROOM_TILE_DIM_X)
+ {
+ room_index_delta.x += 1;
+ p_final.local.x = math_wrap(p.local.x, 0.0f, ROOM_TILE_DIM_X);
+ }
+
+ if (p.local.y < 0.0f)
+ {
+ room_index_delta.y -= 1;
+ p_final.local.y = math_wrap(p.local.y, 0.0f, ROOM_TILE_DIM_Y);
+ }
+ else if (p.local.y > ROOM_TILE_DIM_Y)
+ {
+ room_index_delta.y += 1;
+ p_final.local.y = math_wrap(p.local.y, 0.0f, ROOM_TILE_DIM_Y);
+ }
+
+ p_final.room = math_v2i_a(p.room, room_index_delta);
+ return p_final;
+}
+
+struct RoomSearchResult
+{
+ bool room_found;
+ size_t room_array_index;
+};
+
+internal struct RoomSearchResult get_room_at_index(struct Room *rooms, u32 num_rooms, v2i room_i)
+{
+ struct RoomSearchResult result = {0};
+ for (size_t i = 0; i < num_rooms; i++)
+ {
+ struct Room *r = &rooms[i];
+ if (r->index.x == room_i.x && r->index.y == room_i.y)
+ {
+ result.room_found = true;
+ result.room_array_index = i;
+ }
+ }
+ return result;
+}
+
+internal u32 get_tile_value(u32 *tiles, v2 tile_pos)
+{
+ assert(tiles);
+
+ v2u tile_i_2d = {
+ tile_pos.x,
+ ROOM_TILE_DIM_Y - 1.0f - tile_pos.y,
+ };
+
+ assert(math_v2_lt(
+ (v2) {tile_i_2d.x, tile_i_2d.y},
+ (v2) {ROOM_TILE_DIM_X, ROOM_TILE_DIM_Y}));
+
+ assert(math_v2_ge(
+ (v2) {tile_i_2d.x, tile_i_2d.y},
+ (v2) {0}));
+
+ u32 tile_i_linearized = (ROOM_TILE_DIM_X * tile_i_2d.y) + tile_i_2d.x;
+ assert(tile_i_linearized < ROOM_TILE_COUNT);
+
+ u32 tile_value = tiles[tile_i_linearized];
+ return tile_value;
+}
+
+internal bool tile_is_solid(u32 *tiles, v2 tile_pos)
+{
+ assert(tiles);
+
+ bool is_solid = false;
+ u32 tile_value = get_tile_value(tiles, tile_pos);
+ is_solid = tile_value > 0;
+ return is_solid;
+}
+
+internal bool wall_is_screen_edge(u32 *tiles, segment wall)
+{
+ assert(tiles);
+
+ bool is_screen_edge = false;
+ bool wall_is_horizontal = wall.min.y == wall.max.y;
+ bool wall_is_vertical = wall.min.x == wall.max.x;
+
+ assert(wall_is_vertical || wall_is_horizontal);
+ assert(math_v2_ge(wall.min, (v2) {0}));
+ assert(math_v2_le(wall.max, (v2) {ROOM_TILE_DIM_X, ROOM_TILE_DIM_Y}));
+
+ if (wall_is_vertical)
+ {
+ is_screen_edge = wall.min.x == 0.0f || wall.min.x == ROOM_TILE_DIM_X;
+ }
+ else
+ {
+ is_screen_edge = wall.min.y == 0.0f || wall.min.y == ROOM_TILE_DIM_Y;
+ }
+
+ return is_screen_edge;
+}
+
+internal bool wall_is_internal(u32 *tiles, segment wall)
+{
+ assert(tiles);
+
+ bool is_internal = false;
+ bool wall_is_horizontal = wall.min.y == wall.max.y;
+ bool wall_is_vertical = wall.min.x == wall.max.x;
+
+ assert(wall_is_vertical || wall_is_horizontal);
+
+ v2 lesser_neighbor = {0};
+ v2 greater_neighbor = {0};
+
+ if (wall_is_vertical)
+ {
+ lesser_neighbor = (v2) {wall.min.x - TILE_SIZE, wall.min.y};
+ greater_neighbor = wall.min;
+ is_internal = tile_is_solid(tiles, lesser_neighbor) && tile_is_solid(tiles, greater_neighbor);
+ }
+ else
+ {
+ lesser_neighbor = (v2) {wall.min.x, wall.min.y - TILE_SIZE};
+ greater_neighbor = wall.min;
+ is_internal = tile_is_solid(tiles, lesser_neighbor) && tile_is_solid(tiles, greater_neighbor);
+ }
+
+ return is_internal;
+}
diff --git a/src/world.h b/src/world.h
@@ -0,0 +1,18 @@
+// TODO: delete
+#define MAX_ROOMS 120
+#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 Room
+{
+ v2i index;
+ u32 tiles[ROOM_TILE_COUNT];
+};
+
+struct World
+{
+ struct Room rooms[MAX_ROOMS];
+ u32 num_rooms;
+};