Compare commits

...

3 Commits

Author SHA1 Message Date
En Yi c64ef906e0 Reposition airtimer point check 2023-11-15 21:01:02 +08:00
En Yi 315d9849a7 Use water overlap for friction update
Also relocate the water overlap update
2023-11-15 20:53:41 +08:00
En Yi 0b5f34b9f3 Modify water upthrust behaviour
Changelog:
- Upthrust now depends on water area overlap with entity
- Fix complete overlap checks
2023-11-14 22:31:28 +08:00
3 changed files with 57 additions and 74 deletions

View File

@ -3,13 +3,17 @@
uint8_t find_1D_overlap(Vector2 l1, Vector2 l2, float* overlap) uint8_t find_1D_overlap(Vector2 l1, Vector2 l2, float* overlap)
{ {
// No Overlap // No Overlap
if (l1.y <= l2.x || l2.y <= l1.x) return 0; if (l1.y < l2.x || l2.y < l1.x) return 0;
if (l1.x >= l2.x && l1.y <= l2.y) if (
(l1.x >= l2.x && l1.y <= l2.y)
|| (l2.x >= l1.x && l2.y <= l1.y)
)
{ {
// Complete Overlap, any direction is possible // Complete Overlap, any direction is possible
// Cannot give a singular value, but return something anyways // Cannot give a singular value, but return something anyways
*overlap = l2.y-l2.x + l1.y-l1.x; //*overlap = l2.y-l2.x + l1.y-l1.x;
*overlap = fmin(fabs(l2.y-l2.x), fabs(l1.y-l1.x));
return 2; return 2;
} }
//Partial overlap //Partial overlap

View File

@ -59,6 +59,7 @@ typedef struct _CMovementState_t {
uint8_t ground_state; uint8_t ground_state;
uint8_t water_state; uint8_t water_state;
uint8_t x_dir; uint8_t x_dir;
float water_overlap;
} CMovementState_t; } CMovementState_t;
// This is to store the occupying tiles // This is to store the occupying tiles

View File

@ -875,11 +875,20 @@ void friction_coefficient_update_system(Scene_t* scene)
// Friction // Friction
if (p_mstate != NULL && p_mstate->water_state & 1) if (p_mstate != NULL)
{ {
// Apply water friction // Apply water friction
// Consistent in all direction // Consistent in all direction
p_ct->fric_coeff = (Vector2){-WATER_FRICTION, -WATER_FRICTION}; p_ct->fric_coeff = Vector2Add(
Vector2Scale(
(Vector2){-WATER_FRICTION, -WATER_FRICTION},
p_mstate->water_overlap
),
Vector2Scale(
(Vector2){-GROUND_X_FRICTION, -GROUND_Y_FRICTION},
(1 - p_mstate->water_overlap)
)
);
} }
else else
{ {
@ -918,35 +927,14 @@ void global_external_forces_system(Scene_t* scene)
if (!(p_mstate->ground_state & 1)) if (!(p_mstate->ground_state & 1))
{ {
// Only apply upthrust if center is in water p_ctransform->accel = Vector2Multiply(
// If need more accuracy, need to find area of overlap Vector2Add(
if (p_mstate->water_state & 1) p_ctransform->accel,
{ Vector2Scale(UPTHRUST, p_mstate->water_overlap)
Vector2 player_center = (Vector2){ ),
.x = p_ctransform->position.x + p_bbox->half_size.x, p_ctransform->shape_factor
.y = p_ctransform->position.y + p_bbox->half_size.y,
};
unsigned int tile_idx = get_tile_idx(
player_center.x,
player_center.y,
data->tilemap.width
); );
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 = Vector2Multiply(Vector2Add(p_ctransform->accel, UPTHRUST), p_ctransform->shape_factor);
}
}
}
p_ctransform->accel = Vector2Add(p_ctransform->accel, GRAVITY); p_ctransform->accel = Vector2Add(p_ctransform->accel, GRAVITY);
} }
@ -1407,54 +1395,44 @@ void state_transition_update_system(Scene_t* scene)
p_ctransform->grav_timer = p_ctransform->grav_delay; p_ctransform->grav_timer = p_ctransform->grav_delay;
} }
bool in_water = false; // Upthrust depends on water overlapping
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(
player_center.x,
player_center.y,
data->tilemap.width
);
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
{
unsigned int tile_x1 = (p_ctransform->position.x) / TILE_SIZE; unsigned int tile_x1 = (p_ctransform->position.x) / TILE_SIZE;
unsigned int tile_y1 = (p_ctransform->position.y) / TILE_SIZE; unsigned int tile_y1 = (p_ctransform->position.y) / TILE_SIZE;
unsigned int tile_x2 = (p_ctransform->position.x + p_bbox->size.x) / TILE_SIZE; unsigned int tile_x2 = (p_ctransform->position.x + p_bbox->size.x) / TILE_SIZE;
unsigned int tile_y2 = (p_ctransform->position.y + p_bbox->size.y) / TILE_SIZE; unsigned int tile_y2 = (p_ctransform->position.y + p_bbox->size.y) / TILE_SIZE;
float water_area = 0;
for (unsigned int tile_y = tile_y1; tile_y <= tile_y2; tile_y++) for (unsigned int tile_y = tile_y1; tile_y <= tile_y2; tile_y++)
{ {
for (unsigned int tile_x = tile_x1; tile_x <= tile_x2; tile_x++) for (unsigned int tile_x = tile_x1; tile_x <= tile_x2; tile_x++)
{ {
unsigned int tile_idx = tile_y * data->tilemap.width + tile_x; unsigned int tile_idx = tile_y * data->tilemap.width + tile_x;
if (data->tilemap.tiles[tile_idx].water_level == 0) continue; if (data->tilemap.tiles[tile_idx].water_level > 0)
{
uint32_t water_height = data->tilemap.tiles[tile_idx].water_level * WATER_BBOX_STEP; uint32_t water_height = data->tilemap.tiles[tile_idx].water_level * WATER_BBOX_STEP;
Vector2 tl = {tile_x * data->tilemap.tile_size, (tile_y + 1) * data->tilemap.tile_size - water_height}; Vector2 water_tl = {
in_water |= find_AABB_overlap( .x = (tile_idx % data->tilemap.width) * data->tilemap.tile_size,
.y = (tile_idx / data->tilemap.width + 1) * data->tilemap.tile_size - water_height};
Vector2 water_sz = {
.x = data->tilemap.tile_size,
.y = water_height,
};
Vector2 overlap;
if (find_AABB_overlap(
p_ctransform->position, p_bbox->size, p_ctransform->position, p_bbox->size,
tl, (Vector2){data->tilemap.tile_size, water_height} water_tl, water_sz, &overlap
, NULL ))
) > 0; {
water_area += fabs(overlap.x * overlap.y);
} }
} }
} }
}
p_mstate->water_overlap = water_area/(p_bbox->size.x * p_bbox->size.y);
bool in_water = p_mstate->water_overlap > 0;
p_mstate->ground_state <<= 1; p_mstate->ground_state <<= 1;
p_mstate->ground_state |= on_ground? 1:0; p_mstate->ground_state |= on_ground? 1:0;
p_mstate->ground_state &= 3; p_mstate->ground_state &= 3;
@ -1866,7 +1844,7 @@ void airtimer_update_system(Scene_t* scene)
Vector2 point_to_check = { Vector2 point_to_check = {
(p_movement->x_dir == 0) ? p_ctransform->position.x : p_ctransform->position.x + p_bbox->size.x, (p_movement->x_dir == 0) ? p_ctransform->position.x : p_ctransform->position.x + p_bbox->size.x,
p_ctransform->position.y + p_bbox->half_size.y, p_ctransform->position.y + p_bbox->half_size.y / 2,
}; };
unsigned int tile_idx = get_tile_idx( unsigned int tile_idx = get_tile_idx(