Adjust ladder player interaction

Changelog:
- Use box check to allow player to climb ladder
    - This make it more lenient
- Use interp to smoothly 'snap' the player to ladder's center
    - only when climbing straight up/down
- Increase speed when climbing horizontally
- Decrease jump penalty when jumping off ladder
main
En Yi 2025-08-27 22:43:09 +08:00
parent dacb235fad
commit b8b475bfc4
1 changed files with 41 additions and 53 deletions

View File

@ -326,77 +326,65 @@ void player_movement_input_system(Scene_t* scene)
CMovementState_t* p_mstate = get_component(p_player, CMOVEMENTSTATE_T); CMovementState_t* p_mstate = get_component(p_player, CMOVEMENTSTATE_T);
// Ladder handling // Ladder handling
// Entering ladder bbox check is a quarter smaller, while exitting the ladder is a full bbox check
if (!p_pstate->ladder_state) if (!p_pstate->ladder_state)
{ {
// Transit into ladder state if possible // Transit into ladder state if possible
if (!p_pstate->locked) if (!p_pstate->locked)
{ {
if (p_pstate->player_dir.y < 0) if (p_pstate->player_dir.y < 0 && p_ctransform->velocity.y >= 0)
{ {
unsigned int tile_idx = get_tile_idx( unsigned int tile_x1 = (p_player->position.x + p_bbox->half_size.x/2) / TILE_SIZE;
p_player->position.x + p_bbox->half_size.x, unsigned int tile_x2 = (p_player->position.x + p_bbox->half_size.x *3/2) / TILE_SIZE;
p_player->position.y + p_bbox->half_size.y, unsigned int tile_y1 = (p_player->position.y + p_bbox->half_size.y/2) / TILE_SIZE;
data->tilemap unsigned int tile_y2 = (p_player->position.y + p_bbox->half_size.y*3/2) / TILE_SIZE;
);
if (tilemap.tiles[tile_idx].tile_type == LADDER && p_ctransform->velocity.y >= 0) for(unsigned int tile_x = tile_x1; tile_x <= tile_x2; tile_x++)
{ {
p_pstate->ladder_state = true; for(unsigned int tile_y = tile_y1; tile_y <= tile_y2; tile_y++)
p_player->position.y--; {
unsigned int tile_idx = tile_y * tilemap.width + tile_x;
if (tilemap.tiles[tile_idx].tile_type == LADDER)
{
p_pstate->ladder_state = true;
p_player->position.y--;
break;
}
}
} }
} }
//else if (p_pstate->player_dir.y > 0)
//{
// unsigned int tile_idx;
// if (p_mstate->ground_state & 1)
// {
// tile_idx = get_tile_idx(
// p_player->position.x + p_bbox->half_size.x,
// p_player->position.y + p_bbox->size.y,
// data->tilemap
// );
// }
// else
// {
// tile_idx = get_tile_idx(
// p_player->position.x + p_bbox->half_size.x,
// p_player->position.y + p_bbox->half_size.y,
// data->tilemap
// );
// }
// if (tile_idx < tilemap.n_tiles && tilemap.tiles[tile_idx].tile_type == LADDER)
// {
// p_pstate->ladder_state = true;
// p_player->position.y++;
// }
//}
} }
} }
else else
{ {
unsigned int tile_x = (p_player->position.x + p_bbox->half_size.x) / TILE_SIZE; unsigned int tile_x1 = (p_player->position.x) / TILE_SIZE;
unsigned int tile_y1 = (p_player->position.y + p_bbox->half_size.y) / TILE_SIZE; unsigned int tile_x2 = (p_player->position.x + p_bbox->size.x) / TILE_SIZE;
unsigned int tile_y1 = (p_player->position.y) / TILE_SIZE;
unsigned int tile_y2 = (p_player->position.y + p_bbox->size.y) / TILE_SIZE; unsigned int tile_y2 = (p_player->position.y + p_bbox->size.y) / TILE_SIZE;
p_pstate->ladder_state = false; p_pstate->ladder_state = false;
unsigned int tile_x = tile_x1;
if (!(p_mstate->ground_state & 1)) if (!(p_mstate->ground_state & 1))
{ {
for(unsigned int tile_y = tile_y1; tile_y <= tile_y2; tile_y++) for(tile_x = tile_x1; tile_x <= tile_x2; tile_x++)
{ {
unsigned int tile_idx = tile_y * tilemap.width + tile_x; for(unsigned int tile_y = tile_y1; tile_y <= tile_y2; tile_y++)
p_pstate->ladder_state |= tilemap.tiles[tile_idx].tile_type == LADDER; {
} unsigned int tile_idx = tile_y * tilemap.width + tile_x;
}
if (tilemap.tiles[tile_idx].tile_type == LADDER)
if (p_pstate->ladder_state) {
{ p_pstate->ladder_state = true;
p_ctransform->velocity.y = p_pstate->player_dir.y * 150 * (p_pstate->locked ? 0 : 1); p_ctransform->velocity.y = p_pstate->player_dir.y * 150 * (p_pstate->locked ? 0 : 1);
p_ctransform->velocity.x = p_pstate->player_dir.x * 40 * (p_pstate->locked ? 0 : 1); p_ctransform->velocity.x = p_pstate->player_dir.x * 60 * (p_pstate->locked ? 0 : 1);
if (p_pstate->player_dir.y != 0) if (p_pstate->player_dir.y != 0 && p_pstate->player_dir.x == 0)
{ {
p_player->position.x = tile_x * tilemap.tile_size; float x_target = tile_x * tilemap.tile_size + (tilemap.tile_size >> 1) - p_bbox->half_size.x;
p_player->position.x += (tilemap.tile_size >> 1); p_player->position.x += (x_target - p_player->position.x) * 0.25;
p_player->position.x -= p_bbox->half_size.x; }
break;
}
}
} }
} }
} }
@ -475,7 +463,7 @@ void player_movement_input_system(Scene_t* scene)
else if (p_pstate->ladder_state) else if (p_pstate->ladder_state)
{ {
play_sfx(scene->engine, PLAYER_JMP_SFX); play_sfx(scene->engine, PLAYER_JMP_SFX);
p_ctransform->velocity.y = -p_cjump->jump_speed / 1.4; p_ctransform->velocity.y = -p_cjump->jump_speed / 1.2;
} }
} }
else else