Modify player collision with water blocks

Collision now handles different water level
scene_man
En Yi 2023-07-24 21:19:16 +08:00
parent 4a09550c0b
commit 0a76826c27
4 changed files with 44 additions and 19 deletions

View File

@ -39,4 +39,5 @@
#define GROUND_Y_FRICTION 1.0 #define GROUND_Y_FRICTION 1.0
#define MAX_WATER_LEVEL 4 #define MAX_WATER_LEVEL 4
#define WATER_BBOX_STEP (TILE_SIZE / MAX_WATER_LEVEL)
#endif // __CONSTANTS_H #endif // __CONSTANTS_H

View File

@ -113,14 +113,14 @@ static void level_scene_render_func(Scene_t* scene)
} }
// Draw water tile // 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 // Draw water tile
Color water_colour = ColorAlpha(BLUE, 0.5); Color water_colour = ColorAlpha(BLUE, 0.5);
DrawRectangle( DrawRectangle(
x, x,
y + (1.0f - water_height) * TILE_SIZE, y + (TILE_SIZE - water_height),
TILE_SIZE, TILE_SIZE,
water_height * TILE_SIZE, water_height,
water_colour water_colour
); );
} }

View File

@ -869,29 +869,37 @@ void global_external_forces_system(Scene_t* scene)
continue; continue;
} }
Vector2 half_size = {0, 0};
if (p_bbox != NULL)
{
half_size = p_bbox->half_size;
}
if (!(p_mstate->ground_state & 1)) if (!(p_mstate->ground_state & 1))
{ {
// Only apply upthrust if center is in water // Only apply upthrust if center is in water
// If need more accuracy, need to find area of overlap // If need more accuracy, need to find area of overlap
if (p_mstate->water_state & 1) 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( unsigned int tile_idx = get_tile_idx(
p_ctransform->position.x + half_size.x, player_center.x,
p_ctransform->position.y + half_size.y, player_center.y,
data->tilemap.width data->tilemap.width
); );
if (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,
};
if (point_in_AABB(player_center, box))
{ {
p_ctransform->accel = Vector2Add(p_ctransform->accel, UPTHRUST); p_ctransform->accel = Vector2Add(p_ctransform->accel, UPTHRUST);
} }
} }
}
p_ctransform->accel = Vector2Add(p_ctransform->accel, GRAVITY); p_ctransform->accel = Vector2Add(p_ctransform->accel, GRAVITY);
} }
@ -1318,12 +1326,27 @@ void state_transition_update_system(Scene_t* scene)
bool in_water = false; bool in_water = false;
if (!(p_mstate->water_state & 1)) 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( unsigned int tile_idx = get_tile_idx(
p_ctransform->position.x + p_bbox->half_size.x, player_center.x,
p_ctransform->position.y + p_bbox->half_size.y, player_center.y,
data->tilemap.width 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 else
{ {

View File

@ -166,7 +166,7 @@ void update_water_runner_system(Scene_t* scene)
{ {
// Use previously store tile position // Use previously store tile position
// Clear from those positions // 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); sc_map_del_64v(&(tilemap.tiles[tile_idx].entities_set), ent_idx);
} }
free_water_runner(ent, &scene->ent_manager); 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); runner_BFS(&tilemap, p_crunner, &lowest_tile, p_crunner->current_tile);
p_crunner->target_tile = lowest_tile; p_crunner->target_tile = lowest_tile;
// Trace path from lowest_tile // Trace path from lowest_tile
unsigned int prev_idx = lowest_tile; int prev_idx = lowest_tile;
unsigned int curr_idx = p_crunner->bfs_tilemap.tilemap[prev_idx].from; int curr_idx = p_crunner->bfs_tilemap.tilemap[prev_idx].from;
while (p_crunner->bfs_tilemap.tilemap[prev_idx].from >= 0) while (p_crunner->bfs_tilemap.tilemap[prev_idx].from >= 0)
{ {
p_crunner->bfs_tilemap.tilemap[curr_idx].to = prev_idx; p_crunner->bfs_tilemap.tilemap[curr_idx].to = prev_idx;
@ -271,6 +271,7 @@ void update_water_runner_system(Scene_t* scene)
break; break;
case SCANLINE_FILL: case SCANLINE_FILL:
{ {
// Unsigned usage here is okay
unsigned int start_tile = unsigned int start_tile =
(p_crunner->current_tile / p_crunner->bfs_tilemap.width) * p_crunner->bfs_tilemap.width; (p_crunner->current_tile / p_crunner->bfs_tilemap.width) * p_crunner->bfs_tilemap.width;
//for (size_t i = 0; i < 10; ++i) //for (size_t i = 0; i < 10; ++i)