commit d4a3bfc002951be50bd276299c12f673e6c4137f
parent 80f148c28218a6a83aafe37fbb2e717eb1645b05
Author: amin <dev@aminmesbah.com>
Date: Wed, 12 Jun 2019 06:50:40 +0000
Clean up state transitions a bit
FossilOrigin-Name: 501f59f8de68993a25d36b5cd2ad7d970422a9b3c5decfdfb8142db0b2248d5b
Diffstat:
M | src/game.c | | | 182 | ++++++++++++++++++++++++++++++++++++++++++++----------------------------------- |
M | src/game.h | | | 3 | +++ |
2 files changed, 105 insertions(+), 80 deletions(-)
diff --git a/src/game.c b/src/game.c
@@ -28,6 +28,42 @@ internal void move_state_print(enum MoveState s)
}
}
+internal bool entity_is_adjacent_to_solid_tiles(rect entity_rect, u32 *tiles, enum Direction dir)
+{
+ v2 tile_p_to_search_from_min = {0};
+ v2 tile_p_to_search_from_max = {0};
+ switch(dir)
+ {
+ case DIR_RIGHT:
+ tile_p_to_search_from_min = (v2) {math_ceil(entity_rect.max.x), math_floor(entity_rect.min.y)};
+ tile_p_to_search_from_max = (v2) {math_ceil(entity_rect.max.x), math_floor(entity_rect.max.y)};
+ break;
+ case DIR_LEFT:
+ tile_p_to_search_from_min = (v2) {math_floor(entity_rect.min.x - 1.0f), math_floor(entity_rect.min.y)};
+ tile_p_to_search_from_max = (v2) {math_floor(entity_rect.min.x - 1.0f), math_floor(entity_rect.max.y)};
+ break;
+ case DIR_UP:
+ tile_p_to_search_from_min = (v2) {math_floor(entity_rect.min.x), math_ceil(entity_rect.max.y)};
+ tile_p_to_search_from_max = (v2) {math_floor(entity_rect.max.x), math_ceil(entity_rect.max.y)};
+ break;
+ case DIR_DOWN:
+ tile_p_to_search_from_min = (v2) {math_floor(entity_rect.min.x), math_floor(entity_rect.max.y - 1.0f)};
+ tile_p_to_search_from_max = (v2) {math_floor(entity_rect.max.x), math_floor(entity_rect.min.y - 1.0f)};
+ break;
+ default:
+ assert(false);
+ break;
+ }
+
+ bool result = false;
+ if (tile_is_solid(tiles, tile_p_to_search_from_min)
+ || tile_is_solid(tiles, tile_p_to_search_from_max))
+ {
+ result = true;
+ }
+ return result;
+}
+
internal void game_init(struct GameMemory *game_memory, v2u framebuffer)
{
assert(sizeof(struct GameState) <= game_memory->buffer_size);
@@ -227,104 +263,90 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga
player->velocity.x = player->velocity.x * friction;
}
- // TODO: tune these
- if (player->move_state == MOVE_STATE_FALLING)
+ bool player_is_strictly_within_room = true;
{
- player->acceleration.y = -acceleration_rate;
- }
- else if (player->move_state == MOVE_STATE_CLIMBING)
- {
- bool player_is_still_next_to_wall = true;
- rect player_rect = math_rect_from_center_dim(player->pos.local, player->dimensions);
- v2 next_tile_top = {0};
- v2 next_tile_bottom = {0};
- if (player->facing == DIR_LEFT)
- {
- next_tile_top = (v2) {math_floor(player_rect.min.x - 1.0f), math_floor(player_rect.max.y)};
- next_tile_bottom = (v2) {math_floor(player_rect.min.x - 1.0f), math_floor(player_rect.min.y)};
- }
- else if (player->facing == DIR_RIGHT)
- {
- next_tile_top = (v2) {math_ceil(player_rect.max.x), math_floor(player_rect.max.y)};
- next_tile_bottom = (v2) {math_ceil(player_rect.max.x), math_floor(player_rect.min.y)};
- }
- else
- {
- assert(false);
- }
- renderer_debug_quad_draw(
- &game_state->renderer,
- (rect) {
- .min = next_tile_top,
- .max = {next_tile_top.x + TILE_SIZE, next_tile_top.y + TILE_SIZE},
- },
- (v3) {1.0f, 0.0f, 1.0f});
- renderer_debug_quad_draw(
- &game_state->renderer,
- (rect) {
- .min = next_tile_bottom,
- .max = {next_tile_bottom.x + TILE_SIZE, next_tile_bottom.y + TILE_SIZE},
- },
- (v3) {1.0f, 0.0f, 1.0f});
-
rect player_room_bounds = math_minkowski_diff_rect(
(rect) {.min = {0.0f, 0.0f}, .max = {ROOM_TILE_DIM_X, ROOM_TILE_DIM_Y}},
player->dimensions);
+ player_is_strictly_within_room = math_in_interval_open(player->pos.local.x, player_room_bounds.min.x, player_room_bounds.max.x)
+ && math_in_interval_open(player->pos.local.y, player_room_bounds.min.y, player_room_bounds.max.y);
+ }
+ rect player_rect = math_rect_from_center_dim(player->pos.local, player->dimensions);
- if (math_in_interval_open(player->pos.local.x, player_room_bounds.min.x, player_room_bounds.max.x)
- && math_in_interval_open(player->pos.local.y, player_room_bounds.min.y, player_room_bounds.max.y))
- {
- if (!tile_is_solid(current_room->tiles, next_tile_top) && !tile_is_solid(current_room->tiles, next_tile_bottom))
+ // TODO: tune these
+ switch(player->move_state)
+ {
+ case MOVE_STATE_FALLING:
+ player->acceleration.y = -acceleration_rate;
+ break;
+ case MOVE_STATE_GROUNDED:
+#if 1
+ if (game_input->key_jump)
{
- player_is_still_next_to_wall = false;
+ player->acceleration.y = acceleration_rate;
+ player->move_state = MOVE_STATE_JUMPING;
}
- }
-
- if (player_is_still_next_to_wall && player->facing == previous_facing_dir)
- {
- if (game_input->key_up)
+#else
+ // TODO: do a tile check
+ if (player_is_strictly_within_room
+ && entity_is_adjacent_to_solid_tiles(player_rect, current_room->tiles, DIR_DOWN))
{
- player->acceleration.y = acceleration_rate;
+ if (game_input->key_jump)
+ {
+ player->acceleration.y = acceleration_rate;
+ player->move_state = MOVE_STATE_JUMPING;
+ }
+ }
+ else
+ {
+ player->move_state = MOVE_STATE_FALLING;
}
- else if (game_input->key_down)
+#endif
+ break;
+ case MOVE_STATE_CLIMBING:
+ if (player_is_strictly_within_room
+ && player->facing == previous_facing_dir
+ && entity_is_adjacent_to_solid_tiles(player_rect, current_room->tiles, player->facing))
{
- player->acceleration.y = -acceleration_rate;
+ if (game_input->key_up)
+ {
+ player->acceleration.y = acceleration_rate;
+ }
+ else if (game_input->key_down)
+ {
+ player->acceleration.y = -acceleration_rate;
+ }
+ else
+ {
+ player->acceleration.y = -acceleration_rate;
+ }
}
else
{
- player->acceleration.y = -acceleration_rate;
- player->velocity.y = player->velocity.y * friction;
+ player->move_state = MOVE_STATE_FALLING;
}
- }
- else
+ break;
+ case MOVE_STATE_JUMPING:
{
- player->move_state = MOVE_STATE_FALLING;
- }
- }
- else if (player->move_state == MOVE_STATE_GROUNDED
- || player->move_state == MOVE_STATE_CLIMBING)
- {
- if (game_input->key_jump)
- {
- player->acceleration.y = acceleration_rate;
- player->move_state = MOVE_STATE_JUMPING;
- }
- }
- else if (player->move_state == MOVE_STATE_JUMPING)
- {
- if (game_input->key_jump)
- {
- player->acceleration.y = acceleration_rate;
- player->move_state = MOVE_STATE_JUMPING;
- }
- else
- {
- player->acceleration.y = -acceleration_rate;
- player->move_state = MOVE_STATE_FALLING;
+ // TODO: give this a real timer
+ bool jump_timed_out = false;
+ if (!jump_timed_out && game_input->key_jump)
+ {
+ player->acceleration.y = acceleration_rate;
+ player->move_state = MOVE_STATE_JUMPING;
+ }
+ else
+ {
+ player->acceleration.y = -acceleration_rate;
+ player->move_state = MOVE_STATE_FALLING;
+ }
+ break;
}
+ default:
+ assert(false);
+ break;
}
-
// Semi implicit Euler integration: https://gafferongames.com/post/integration_basics/
player->velocity = math_v2_a(player->velocity, math_v2f_m(player->acceleration, dt));
// TODO: clamp the length of the velocity vector, not each of its components
diff --git a/src/game.h b/src/game.h
@@ -49,6 +49,8 @@ enum Direction
{
DIR_RIGHT,
DIR_LEFT,
+ DIR_UP,
+ DIR_DOWN,
};
struct Entity
@@ -59,6 +61,7 @@ struct Entity
v2 dimensions;
enum Direction facing;
enum MoveState move_state;
+ f32 jump_timeout;
};
struct GameState