From 0a76826c270c9d87cb98b36c55235ef9ec3e4922 Mon Sep 17 00:00:00 2001 From: En Yi Date: Mon, 24 Jul 2023 21:19:16 +0800 Subject: [PATCH] Modify player collision with water blocks Collision now handles different water level --- scenes/constants.h | 1 + scenes/editor_scene.c | 6 +++--- scenes/game_systems.c | 49 +++++++++++++++++++++++++++++++------------ scenes/water_flow.c | 7 ++++--- 4 files changed, 44 insertions(+), 19 deletions(-) diff --git a/scenes/constants.h b/scenes/constants.h index 305ae62..ef2604d 100644 --- a/scenes/constants.h +++ b/scenes/constants.h @@ -39,4 +39,5 @@ #define GROUND_Y_FRICTION 1.0 #define MAX_WATER_LEVEL 4 +#define WATER_BBOX_STEP (TILE_SIZE / MAX_WATER_LEVEL) #endif // __CONSTANTS_H diff --git a/scenes/editor_scene.c b/scenes/editor_scene.c index 996ccaf..de2520f 100644 --- a/scenes/editor_scene.c +++ b/scenes/editor_scene.c @@ -113,14 +113,14 @@ static void level_scene_render_func(Scene_t* scene) } // Draw water tile - float water_height = tilemap.tiles[i].water_level * 1.0f / tilemap.max_water_level; + uint32_t water_height = tilemap.tiles[i].water_level * WATER_BBOX_STEP; // Draw water tile Color water_colour = ColorAlpha(BLUE, 0.5); DrawRectangle( x, - y + (1.0f - water_height) * TILE_SIZE, + y + (TILE_SIZE - water_height), TILE_SIZE, - water_height * TILE_SIZE, + water_height, water_colour ); } diff --git a/scenes/game_systems.c b/scenes/game_systems.c index 84f5a5f..cdf7f93 100644 --- a/scenes/game_systems.c +++ b/scenes/game_systems.c @@ -869,27 +869,35 @@ void global_external_forces_system(Scene_t* scene) continue; } - Vector2 half_size = {0, 0}; - if (p_bbox != NULL) - { - half_size = p_bbox->half_size; - } - if (!(p_mstate->ground_state & 1)) { // Only apply upthrust if center is in water // If need more accuracy, need to find area of overlap if (p_mstate->water_state & 1) { + Vector2 player_center = (Vector2){ + .x = p_ctransform->position.x + p_bbox->half_size.x, + .y = p_ctransform->position.y + p_bbox->half_size.y, + }; unsigned int tile_idx = get_tile_idx( - p_ctransform->position.x + half_size.x, - p_ctransform->position.y + half_size.y, + player_center.x, + player_center.y, data->tilemap.width ); - if (data->tilemap.tiles[tile_idx].water_level > 0) { - p_ctransform->accel = Vector2Add(p_ctransform->accel, UPTHRUST); + uint32_t water_height = data->tilemap.tiles[tile_idx].water_level * WATER_BBOX_STEP; + Rectangle box = { + .x = (tile_idx % data->tilemap.width) * data->tilemap.tile_size, + .y = (tile_idx / data->tilemap.width + 1) * data->tilemap.tile_size - water_height, + .width = data->tilemap.tile_size, + .height = water_height, + }; + + if (point_in_AABB(player_center, box)) + { + p_ctransform->accel = Vector2Add(p_ctransform->accel, UPTHRUST); + } } } p_ctransform->accel = Vector2Add(p_ctransform->accel, GRAVITY); @@ -1318,12 +1326,27 @@ void state_transition_update_system(Scene_t* scene) bool in_water = false; if (!(p_mstate->water_state & 1)) { + Vector2 player_center = (Vector2){ + .x = p_ctransform->position.x + p_bbox->half_size.x, + .y = p_ctransform->position.y + p_bbox->half_size.y, + }; unsigned int tile_idx = get_tile_idx( - p_ctransform->position.x + p_bbox->half_size.x, - p_ctransform->position.y + p_bbox->half_size.y, + player_center.x, + player_center.y, data->tilemap.width ); - in_water = (data->tilemap.tiles[tile_idx].water_level > 0); + if (data->tilemap.tiles[tile_idx].water_level > 0) + { + uint32_t water_height = data->tilemap.tiles[tile_idx].water_level * WATER_BBOX_STEP; + Rectangle box = { + .x = (tile_idx % data->tilemap.width) * data->tilemap.tile_size, + .y = (tile_idx / data->tilemap.width + 1) * data->tilemap.tile_size - water_height, + .width = data->tilemap.tile_size, + .height = water_height, + }; + + in_water = point_in_AABB(player_center, box); + } } else { diff --git a/scenes/water_flow.c b/scenes/water_flow.c index de92aa0..fcf9ef3 100644 --- a/scenes/water_flow.c +++ b/scenes/water_flow.c @@ -166,7 +166,7 @@ void update_water_runner_system(Scene_t* scene) { // Use previously store tile position // Clear from those positions - unsigned int tile_idx = p_tilecoord->tiles[i]; + int tile_idx = p_tilecoord->tiles[i]; sc_map_del_64v(&(tilemap.tiles[tile_idx].entities_set), ent_idx); } free_water_runner(ent, &scene->ent_manager); @@ -192,8 +192,8 @@ void update_water_runner_system(Scene_t* scene) runner_BFS(&tilemap, p_crunner, &lowest_tile, p_crunner->current_tile); p_crunner->target_tile = lowest_tile; // Trace path from lowest_tile - unsigned int prev_idx = lowest_tile; - unsigned int curr_idx = p_crunner->bfs_tilemap.tilemap[prev_idx].from; + int prev_idx = lowest_tile; + int curr_idx = p_crunner->bfs_tilemap.tilemap[prev_idx].from; while (p_crunner->bfs_tilemap.tilemap[prev_idx].from >= 0) { p_crunner->bfs_tilemap.tilemap[curr_idx].to = prev_idx; @@ -271,6 +271,7 @@ void update_water_runner_system(Scene_t* scene) break; case SCANLINE_FILL: { + // Unsigned usage here is okay unsigned int start_tile = (p_crunner->current_tile / p_crunner->bfs_tilemap.width) * p_crunner->bfs_tilemap.width; //for (size_t i = 0; i < 10; ++i)