From c8d2ee540830dc1bef7d67740b27c23ef2065c37 Mon Sep 17 00:00:00 2001 From: En Yi Date: Wed, 21 Jun 2023 21:27:13 +0800 Subject: [PATCH] Improve crushing using edge testing Changelog: - Add len reduction to edge checking to give leeway in crushing --- scenes/editor_scene.c | 2 +- scenes/game_systems.c | 65 +++++++++++-------------------------------- 2 files changed, 17 insertions(+), 50 deletions(-) diff --git a/scenes/editor_scene.c b/scenes/editor_scene.c index 4b8819d..f107d5f 100644 --- a/scenes/editor_scene.c +++ b/scenes/editor_scene.c @@ -477,7 +477,7 @@ void init_level_scene(LevelScene_t* scene) sc_array_add(&scene->scene.systems, &tile_collision_system); sc_array_add(&scene->scene.systems, &update_tilemap_system); sc_array_add(&scene->scene.systems, &hitbox_update_system); - //sc_array_add(&scene->scene.systems, &player_crushing_system); + sc_array_add(&scene->scene.systems, &player_crushing_system); sc_array_add(&scene->scene.systems, &state_transition_update_system); sc_array_add(&scene->scene.systems, &player_ground_air_transition_system); sc_array_add(&scene->scene.systems, &sprite_animation_system); diff --git a/scenes/game_systems.c b/scenes/game_systems.c index 6ea31d2..6f8670b 100644 --- a/scenes/game_systems.c +++ b/scenes/game_systems.c @@ -298,14 +298,19 @@ collision_end: static uint8_t check_bbox_edges( TileGrid_t* tilemap, - Entity_t* p_ent, Vector2 pos, Vector2 prev_pos, Vector2 bbox + Entity_t* p_ent, Vector2 pos, Vector2 prev_pos, Vector2 bbox, + int8_t len_reduction ) { uint8_t detected = 0; + + bbox.x -= 2 * len_reduction; + bbox.y -= 2 * len_reduction; + CollideEntity_t ent = { .p_ent = p_ent, - .bbox = (Rectangle){pos.x - 1, pos.y, 1, bbox.y}, + .bbox = (Rectangle){pos.x - 1, pos.y + len_reduction, 1, bbox.y}, .prev_bbox = (Rectangle){pos.x, pos.y, bbox.x, bbox.y}, .area = (TileArea_t){ .tile_x1 = (pos.x - 1) / TILE_SIZE, @@ -327,8 +332,8 @@ static uint8_t check_bbox_edges( detected |= (check_collision_line(&ent, tilemap, false) ? 1 : 0) << 2; // Up - ent.bbox.x = pos.x; - ent.bbox.y--; + ent.bbox.x = pos.x + len_reduction; + ent.bbox.y = pos.y - 1; ent.bbox.width = bbox.x; ent.bbox.height = 1; ent.area.tile_x1 = (pos.x) / TILE_SIZE, @@ -672,57 +677,19 @@ void player_bbox_update_system(Scene_t* scene) void player_crushing_system(Scene_t* scene) { LevelSceneData_t* data = &(CONTAINER_OF(scene, LevelScene_t, scene)->data); - TileGrid_t tilemap = data->tilemap; Entity_t* p_player; sc_map_foreach_value(&scene->ent_manager.entities_map[PLAYER_ENT_TAG], p_player) { CTransform_t* p_ctransform = get_component(p_player, CTRANSFORM_COMP_T); CBBox_t* p_bbox = get_component(p_player, CBBOX_COMP_T); - CollideEntity_t ent = - { - .p_ent = p_player, - .bbox = (Rectangle){p_ctransform->position.x, p_ctransform->position.y, p_bbox->size.x, p_bbox->size.y}, - .prev_bbox = (Rectangle){p_ctransform->prev_velocity.x, p_ctransform->prev_position.y, p_bbox->size.x, p_bbox->size.y}, - .area = (TileArea_t){ - .tile_x1 = (p_ctransform->position.x) / TILE_SIZE, - .tile_y1 = (p_ctransform->position.y) / TILE_SIZE, - .tile_x2 = (p_ctransform->position.x) / TILE_SIZE, - .tile_y2 = (p_ctransform->position.y + p_bbox->size.y - 1) / TILE_SIZE, - }, - }; - // Mostly identical to edge check function - // Except we want collision instead of just touching - uint8_t detected = 0; - // Left - detected |= (check_collision(&ent, &tilemap, false) ? 1 : 0); + uint8_t edges = check_bbox_edges( + &data->tilemap, p_player, + p_ctransform->position, p_ctransform->prev_position, p_bbox->size, 2 + ); - //Right - ent.area.tile_x1 = (p_ctransform->position.x + p_bbox->size.x - 1) / TILE_SIZE; - ent.area.tile_x2 = ent.area.tile_x1; - detected |= (check_collision(&ent, &tilemap, false) ? 1 : 0) << 1; - - if (detected == 0b11) - { - p_player->m_alive = false; - return; - } - - detected = 0; - // Up - ent.area.tile_x1 = (p_ctransform->position.x) / TILE_SIZE, - ent.area.tile_y1 = (p_ctransform->position.y - 1) / TILE_SIZE, - ent.area.tile_y2 = ent.area.tile_y1; - detected |= (check_collision(&ent, &tilemap, false) ? 1 : 0) << 1; - - // Down - ent.area.tile_y1 = (p_ctransform->position.y + p_bbox->size.y - 1) / TILE_SIZE, - ent.area.tile_y2 = ent.area.tile_y1; - detected |= (check_collision(&ent, &tilemap, true) ? 1 : 0); - - //if (check_collision(&ent, &tilemap, false) == 1) - if (detected == 0b11) + if ((edges & 0b1100) == 0b1100 || (edges & 0b0011) == 0b0011) { p_player->m_alive = false; return; @@ -801,7 +768,7 @@ void tile_collision_system(Scene_t* scene) // Post movement edge check to zero out velocity uint8_t edges = check_bbox_edges( &data->tilemap, p_ent, - p_ctransform->position, p_ctransform->prev_position, p_bbox->size + p_ctransform->position, p_ctransform->prev_position, p_bbox->size, 0 ); if (edges & (1<<3)) { @@ -927,7 +894,7 @@ void global_external_forces_system(Scene_t* scene) // Zero out acceleration for contacts with sturdy entites and tiles uint8_t edges = check_bbox_edges( &data->tilemap, p_ent, - p_ctransform->position, p_ctransform->prev_position, p_bbox->size + p_ctransform->position, p_ctransform->prev_position, p_bbox->size, 0 ); if (edges & (1<<3)) {