Improve on the boulder pushing mechan

Changelog:
- Implement point to AABB check function
- Change moveable check to use point-AABB check
- Allow boulder pushing from standing still
scene_man
En Yi 2023-06-03 14:01:10 +08:00
parent 62dc51d45e
commit 20ec3f6395
5 changed files with 67 additions and 41 deletions

View File

@ -432,6 +432,7 @@ void init_level_scene(LevelScene_t* scene)
sc_array_add(&scene->scene.systems, &player_ground_air_transition_system);
sc_array_add(&scene->scene.systems, &sprite_animation_system);
sc_array_add(&scene->scene.systems, &camera_update_system);
sc_array_add(&scene->scene.systems, &player_dir_reset_system);
sc_array_add(&scene->scene.systems, &toggle_block_system);
// This avoid graphical glitch, not essential

View File

@ -44,3 +44,13 @@ bool find_AABB_overlap(const Vector2 tl1, const Vector2 sz1, const Vector2 tl2,
return overlap_x && overlap_y;
}
bool point_in_AABB(Vector2 point, Rectangle box)
{
return (
point.x > box.x
&& point.y > box.y
&& point.x < box.x + box.width
&& point.y < box.y + box.height
);
}

View File

@ -4,4 +4,5 @@
#include "raymath.h"
bool find_1D_overlap(Vector2 l1, Vector2 l2, float* overlap);
bool find_AABB_overlap(const Vector2 tl1, const Vector2 sz1, const Vector2 tl2, const Vector2 sz2, Vector2* overlap);
bool point_in_AABB(Vector2 point, Rectangle box);
#endif // __AABB_H

View File

@ -298,6 +298,17 @@ static Vector2 shift_bbox(Vector2 bbox, Vector2 new_bbox, AnchorPoint_t anchor)
return offset;
}
void player_dir_reset_system(Scene_t* scene)
{
CPlayerState_t* p_pstate;
unsigned int ent_idx;
sc_map_foreach(&scene->ent_manager.component_map[CPLAYERSTATE_T], ent_idx, p_pstate)
{
p_pstate->player_dir.x = 0;
p_pstate->player_dir.y = 0;
}
}
void player_movement_input_system(Scene_t* scene)
{
LevelSceneData_t* data = &(CONTAINER_OF(scene, LevelScene_t, scene)->data);
@ -466,8 +477,6 @@ void player_movement_input_system(Scene_t* scene)
p_cjump->jump_ready = false;
}
p_pstate->player_dir.x = 0;
p_pstate->player_dir.y = 0;
}
}
@ -830,56 +839,60 @@ void player_pushing_system(Scene_t* scene)
sc_map_foreach_value(&scene->ent_manager.entities_map[PLAYER_ENT_TAG], p_player)
{
CMovementState_t* p_movement = get_component(p_player, CMOVEMENTSTATE_T);
CPlayerState_t* p_pstate = get_component(p_player, CPLAYERSTATE_T);
if (!(p_movement->ground_state & 1)) continue;
CTransform_t* p_ctransform = get_component(p_player, CTRANSFORM_COMP_T);
CBBox_t* p_bbox = get_component(p_player, CBBOX_COMP_T);
Vector2 point_to_check = p_ctransform->position;
point_to_check.y += p_bbox->half_size.y;
if (p_pstate->player_dir.x > 0)
{
point_to_check.x += p_bbox->size.x + 1;
}
else
{
point_to_check.x -= 1;
}
//CHitBoxes_t* p_hitbox = get_component(p_player, CHITBOXES_T);
// Get the occupied tiles
// For each tile, loop through the entities, check collision and move
// exclude self
unsigned int tile_x1 = (p_ctransform->position.x) / TILE_SIZE;
unsigned int tile_y1 = (p_ctransform->position.y + 1) / 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 - 1) / TILE_SIZE;
unsigned int tile_x = (point_to_check.x) / TILE_SIZE;
unsigned int tile_y = (point_to_check.y) / TILE_SIZE;
unsigned int tile_idx = tile_y * tilemap.width + tile_x;
if(tilemap.tiles[tile_idx].tile_type != EMPTY_TILE) continue;
for (unsigned int tile_y = tile_y1; tile_y <= tile_y2; tile_y++)
unsigned int other_ent_idx;
sc_map_foreach_key(&tilemap.tiles[tile_idx].entities_set, other_ent_idx)
{
for (unsigned int tile_x = tile_x1; tile_x <= tile_x2; tile_x++)
if (other_ent_idx == p_player->m_id) continue;
Entity_t *p_other_ent = get_entity(&scene->ent_manager, other_ent_idx);
if (!p_other_ent->m_alive) continue; // To only allow one way collision check
CMoveable_t *p_other_moveable = get_component(p_other_ent, CMOVEABLE_T);
if (p_other_moveable == NULL) continue;
CTransform_t *p_other_ct = get_component(p_other_ent, CTRANSFORM_COMP_T);
CBBox_t *p_other_bbox = get_component(p_other_ent, CBBOX_COMP_T);
Rectangle box = {
.x = p_other_ct->position.x,
.y = p_other_ct->position.y,
.width = p_other_bbox->size.x,
.height = p_other_bbox->size.y
};
if (point_in_AABB(point_to_check, box))
{
unsigned int tile_idx = tile_y * tilemap.width + tile_x;
if(tilemap.tiles[tile_idx].tile_type != EMPTY_TILE) continue;
unsigned int other_ent_idx;
sc_map_foreach_key(&tilemap.tiles[tile_idx].entities_set, other_ent_idx)
p_other_moveable->gridmove = true;
p_other_moveable->target_pos = p_other_ct->position;
if (p_ctransform->position.x < p_other_ct->position.x)
{
if (other_ent_idx == p_player->m_id) continue;
Entity_t *p_other_ent = get_entity(&scene->ent_manager, other_ent_idx);
if (!p_other_ent->m_alive) continue; // To only allow one way collision check
CMoveable_t *p_other_moveable = get_component(p_other_ent, CMOVEABLE_T);
if (p_other_moveable == NULL) continue;
CTransform_t *p_other_ct = get_component(p_other_ent, CTRANSFORM_COMP_T);
CBBox_t *p_other_bbox = get_component(p_other_ent, CBBOX_COMP_T);
if (check_collision_and_move(
&scene->ent_manager, &tilemap, p_player->m_id,
p_ctransform, p_bbox->size, p_other_ct->position,
p_other_bbox->size, false
)
)
{
p_other_moveable->gridmove = true;
p_other_moveable->target_pos = p_other_ct->position;
if (p_ctransform->position.x < p_other_ct->position.x)
{
p_other_moveable->target_pos.x = p_other_ct->position.x + TILE_SIZE;
}
else
{
p_other_moveable->target_pos.x = p_other_ct->position.x - TILE_SIZE;
}
}
p_other_moveable->target_pos.x = p_other_ct->position.x + TILE_SIZE;
}
else
{
p_other_moveable->target_pos.x = p_other_ct->position.x - TILE_SIZE;
}
}
}

View File

@ -18,4 +18,5 @@ void update_tilemap_system(Scene_t* scene);
void hitbox_update_system(Scene_t* scene);
void sprite_animation_system(Scene_t* scene);
void camera_update_system(Scene_t* scene);
void player_dir_reset_system(Scene_t* scene);
#endif // __GAME_SYSTEMS_H