Compare commits

...

6 Commits

Author SHA1 Message Date
En Yi e465b0c1d4 Zero out accel for contacts in y-direction 2023-02-04 17:37:07 +08:00
En Yi e4018f1ad6 Fix edge case in handling horizontal movement
Changelog:
- Zero out acceleration when colliding with solid tile or strong entities
- This is to prevent continuous overlap after a single collision
  horizontally, similar to the gravity handling
2023-02-04 17:22:01 +08:00
En Yi 0165016a7c Refactor collision event to be LevelSceneData 2023-02-04 16:17:15 +08:00
En Yi c2bf930059 Fix player collision with crates
Changelog:
- Check for collision before moving
- Refactor out collision check and move function
- Remove anchor check when shifting bbox as it is unneccesary
- Collision checking will check for tiles and entities
2023-02-04 16:00:37 +08:00
En Yi c5c9b84154 Fix bbox shifting when resizing
Changelog:
- Check for collision before shifting bbox
- This fix the odd bbox shifting when exiting water
- Hack a way to force crouch when exiting water
2023-02-04 12:24:50 +08:00
En Yi 2e9fadb79f Rework forcing crouch on ground
Changelog:
- Change to check the player 'head' for collision to force crouch
2023-02-02 23:11:19 +08:00
4 changed files with 184 additions and 164 deletions

View File

@ -25,50 +25,61 @@ static inline unsigned int get_tile_idx(int x, int y, unsigned int tilemap_width
return tile_y * tilemap_width + tile_x; return tile_y * tilemap_width + tile_x;
} }
static bool check_collision_at(Vector2 pos, Vector2 bbox_sz, TileGrid_t* grid, Vector2 point) typedef struct TileArea
{ {
Vector2 new_pos = Vector2Add(pos, point); unsigned int tile_x1;
unsigned int tile_x1 = (new_pos.x) / TILE_SIZE; unsigned int tile_y1;
unsigned int tile_x2 = (new_pos.x + bbox_sz.x - 1) / TILE_SIZE; unsigned int tile_x2;
unsigned int tile_y1 = (new_pos.y) / TILE_SIZE; unsigned int tile_y2;
unsigned int tile_y2 = (new_pos.y + bbox_sz.y - 1) / TILE_SIZE; }TileArea_t;
for(unsigned int tile_y = tile_y1; tile_y <= tile_y2; tile_y++) static bool check_collision(Vector2 pos, Vector2 bbox_sz, TileArea_t area_to_check, TileGrid_t* grid, EntityManager_t* p_manager)
{ {
for(unsigned int tile_x = tile_x1; tile_x <= tile_x2; tile_x++) for(unsigned int tile_y = area_to_check.tile_y1; tile_y <= area_to_check.tile_y2; tile_y++)
{ {
if (grid->tiles[tile_y*grid->width + tile_x].solid) return true; for(unsigned int tile_x = area_to_check.tile_x1; tile_x <= area_to_check.tile_x2; tile_x++)
}
}
return false;
}
static inline bool check_on_ground(unsigned int ent_idx, Vector2 pos, Vector2 bbox_sz, TileGrid_t* grid, Scene_t* scene)
{
pos.y += 1;
unsigned int tile_x1 = (pos.x) / TILE_SIZE;
unsigned int tile_x2 = (pos.x + bbox_sz.x - 1) / TILE_SIZE;
unsigned int tile_y = (pos.y + bbox_sz.y - 1) / TILE_SIZE;
for(unsigned int tile_x = tile_x1; tile_x <= tile_x2; tile_x++)
{ {
unsigned int tile_idx = tile_y*grid->width + tile_x; unsigned int tile_idx = tile_y*grid->width + tile_x;
if (grid->tiles[tile_idx].solid) return true; if (grid->tiles[tile_idx].solid) return true;
unsigned int ent_idx;
unsigned int other_ent_idx; sc_map_foreach_value(&grid->tiles[tile_idx].entities_set, ent_idx)
sc_map_foreach_key(&grid->tiles[tile_idx].entities_set, other_ent_idx)
{ {
Entity_t * p_ent = get_entity(p_manager, ent_idx);
CTransform_t *p_ctransform = get_component(p_manager, p_ent, CTRANSFORM_COMP_T);
CBBox_t *p_bbox = get_component(p_manager, p_ent, CBBOX_COMP_T);
Vector2 overlap; Vector2 overlap;
if (other_ent_idx == ent_idx) continue; if (p_bbox == NULL || p_ctransform == NULL) continue;
Entity_t *p_other_ent = get_entity(&scene->ent_manager, other_ent_idx); if (p_bbox->solid && !p_bbox->fragile && find_AABB_overlap(pos, bbox_sz, p_ctransform->position, p_bbox->size, &overlap)) return true;
CBBox_t *p_other_bbox = get_component(&scene->ent_manager, p_other_ent, CBBOX_COMP_T); }
if (p_other_bbox == NULL || !p_other_bbox->solid || p_other_bbox->fragile) continue;
CTransform_t *p_other_ct = get_component(&scene->ent_manager, p_other_ent, CTRANSFORM_COMP_T);
if (find_AABB_overlap(pos, bbox_sz, p_other_ct->position, p_other_bbox->size, &overlap)) return true;
} }
} }
return false; return false;
}
static bool check_collision_at(Vector2 pos, Vector2 bbox_sz, TileGrid_t* grid, Vector2 point, EntityManager_t* p_manager)
{
Vector2 new_pos = Vector2Add(pos, point);
TileArea_t area = {
.tile_x1 = (new_pos.x) / TILE_SIZE,
.tile_y1 = (new_pos.y) / TILE_SIZE,
.tile_x2 = (new_pos.x + bbox_sz.x - 1) / TILE_SIZE,
.tile_y2 = (new_pos.y + bbox_sz.y - 1) / TILE_SIZE
};
return check_collision(new_pos, bbox_sz, area, grid, p_manager);
}
static inline bool check_on_ground(unsigned int ent_idx, Vector2 pos, Vector2 bbox_sz, TileGrid_t* grid, EntityManager_t* p_manager)
{
pos.y += 1;
TileArea_t area = {
.tile_x1 = (pos.x) / TILE_SIZE,
.tile_y1 = (pos.y + bbox_sz.y - 1) / TILE_SIZE,
.tile_x2 = (pos.x + bbox_sz.x - 1) / TILE_SIZE,
.tile_y2 = (pos.y + bbox_sz.y - 1) / TILE_SIZE,
};
return check_collision(pos, bbox_sz, area, grid, p_manager);
} }
static Vector2 shift_bbox(Vector2 bbox, Vector2 new_bbox, AnchorPoint_t anchor) static Vector2 shift_bbox(Vector2 bbox, Vector2 new_bbox, AnchorPoint_t anchor)
{ {
@ -151,6 +162,7 @@ void player_movement_input_system(Scene_t* scene)
mag = (mag == 0)? 1 : mag; mag = (mag == 0)? 1 : mag;
Entity_t * p_player = get_entity(&scene->ent_manager, ent_idx); Entity_t * p_player = get_entity(&scene->ent_manager, ent_idx);
CTransform_t* p_ctransform = get_component(&scene->ent_manager, p_player, CTRANSFORM_COMP_T); CTransform_t* p_ctransform = get_component(&scene->ent_manager, p_player, CTRANSFORM_COMP_T);
CBBox_t* p_bbox = get_component(&scene->ent_manager, p_player, CBBOX_COMP_T);
CJump_t* p_cjump = get_component(&scene->ent_manager, p_player, CJUMP_COMP_T); CJump_t* p_cjump = get_component(&scene->ent_manager, p_player, CJUMP_COMP_T);
CMovementState_t* p_mstate = get_component(&scene->ent_manager, p_player, CMOVEMENTSTATE_T); CMovementState_t* p_mstate = get_component(&scene->ent_manager, p_player, CMOVEMENTSTATE_T);
@ -175,22 +187,23 @@ void player_movement_input_system(Scene_t* scene)
} }
} }
//else //else
{ {
if (!(p_mstate->ground_state & 1)) p_pstate->is_crouch &= 0b01; bool hit = false;
if (p_pstate->is_crouch == 0b01) unsigned int tile_x1 = (p_ctransform->position.x) / TILE_SIZE;
unsigned int tile_x2 = (p_ctransform->position.x + p_bbox->size.x - 1) / TILE_SIZE;
unsigned int tile_y = (p_ctransform->position.y) / TILE_SIZE;
if (p_bbox->size.y < TILE_SIZE && tile_y > 0) tile_y--; // hack to detect small bbox state
for(unsigned int tile_x = tile_x1; tile_x <= tile_x2; tile_x++)
{ {
Vector2 test_pos = p_ctransform->position; hit |= tilemap.tiles[tile_y * tilemap.width + tile_x].solid;
Vector2 test_bbox = {PLAYER_WIDTH, PLAYER_HEIGHT}; }
Vector2 top = {0, 0}; if (hit)
test_pos.x += PLAYER_C_XOFFSET;
test_pos.y -= PLAYER_C_YOFFSET;
if (check_collision_at(test_pos, test_bbox, &tilemap, top))
{ {
p_pstate->is_crouch |= 0b10; p_pstate->is_crouch |= 0b10;
} }
} if (!(p_mstate->ground_state & 1)) p_pstate->is_crouch &= 0b01;
p_pstate->is_crouch >>= 1; p_pstate->is_crouch >>= 1;
if (p_cjump->cooldown_timer > 0) p_cjump->cooldown_timer--; if (p_cjump->cooldown_timer > 0) p_cjump->cooldown_timer--;
@ -209,7 +222,7 @@ void player_movement_input_system(Scene_t* scene)
Vector2 top = {0, -1}; Vector2 top = {0, -1};
test_pos.x += PLAYER_C_XOFFSET; test_pos.x += PLAYER_C_XOFFSET;
test_pos.y -= PLAYER_C_YOFFSET; test_pos.y -= PLAYER_C_YOFFSET;
jump_valid = !check_collision_at(test_pos, test_bbox, &tilemap, top); jump_valid = !check_collision_at(test_pos, test_bbox, &tilemap, top, &scene->ent_manager);
} }
// Jump okay // Jump okay
@ -248,29 +261,12 @@ void player_bbox_update_system(Scene_t *scene)
CBBox_t* p_bbox = get_component(&scene->ent_manager, p_player, CBBOX_COMP_T); CBBox_t* p_bbox = get_component(&scene->ent_manager, p_player, CBBOX_COMP_T);
CPlayerState_t* p_pstate = get_component(&scene->ent_manager, p_player, CPLAYERSTATE_T); CPlayerState_t* p_pstate = get_component(&scene->ent_manager, p_player, CPLAYERSTATE_T);
CMovementState_t* p_mstate = get_component(&scene->ent_manager, p_player, CMOVEMENTSTATE_T); CMovementState_t* p_mstate = get_component(&scene->ent_manager, p_player, CMOVEMENTSTATE_T);
Vector2 new_bbox;
Vector2 offset;
if (p_mstate->ground_state & 1) if (p_mstate->ground_state & 1)
{ {
AnchorPoint_t anchor = AP_BOT_CENTER; AnchorPoint_t anchor = AP_BOT_CENTER;
int dx[3] = {1, 0, 2};
for (size_t i=0; i<3; i++)
{
unsigned int tile_idx = get_tile_idx
(
p_ctransform->position.x + p_bbox->half_size.x * dx[i],
p_ctransform->position.y + p_bbox->size.y,
tilemap.width
);
if (tilemap.tiles[tile_idx].solid)
{
switch(i)
{
case 1: anchor = AP_BOT_LEFT;break;
case 2: anchor = AP_BOT_RIGHT;break;
}
break;
}
}
Vector2 new_bbox;
if(p_pstate->is_crouch & 1) if(p_pstate->is_crouch & 1)
{ {
new_bbox.x = PLAYER_C_WIDTH; new_bbox.x = PLAYER_C_WIDTH;
@ -281,31 +277,89 @@ void player_bbox_update_system(Scene_t *scene)
new_bbox.x = PLAYER_WIDTH; new_bbox.x = PLAYER_WIDTH;
new_bbox.y = PLAYER_HEIGHT; new_bbox.y = PLAYER_HEIGHT;
} }
Vector2 offset = shift_bbox(p_bbox->size, new_bbox, anchor); offset = shift_bbox(p_bbox->size, new_bbox, anchor);
set_bbox(p_bbox, new_bbox.x, new_bbox.y);
p_ctransform->position = Vector2Add(p_ctransform->position, offset);
} }
else else
{ {
if (p_mstate->water_state & 1) if (p_mstate->water_state & 1)
{ {
Vector2 new_bbox = {PLAYER_C_WIDTH, PLAYER_C_HEIGHT}; new_bbox.x = PLAYER_C_WIDTH;
Vector2 offset = shift_bbox(p_bbox->size, new_bbox, AP_MID_CENTER); new_bbox.y = PLAYER_C_HEIGHT;
set_bbox(p_bbox, PLAYER_C_WIDTH, PLAYER_C_HEIGHT); offset = shift_bbox(p_bbox->size, new_bbox, AP_MID_CENTER);
p_ctransform->position = Vector2Add(p_ctransform->position, offset);
} }
else else
{ {
Vector2 new_bbox = {PLAYER_WIDTH, PLAYER_HEIGHT}; new_bbox.x = PLAYER_WIDTH;
Vector2 offset = shift_bbox(p_bbox->size, new_bbox, AP_MID_CENTER); new_bbox.y = PLAYER_HEIGHT;
set_bbox(p_bbox, PLAYER_WIDTH, PLAYER_HEIGHT); offset = shift_bbox(p_bbox->size, new_bbox, AP_MID_CENTER);
p_ctransform->position = Vector2Add(p_ctransform->position, offset);
} }
} }
if (!check_collision_at(p_ctransform->position, new_bbox, &tilemap, offset, &scene->ent_manager))
{
set_bbox(p_bbox, new_bbox.x, new_bbox.y);
p_ctransform->position = Vector2Add(p_ctransform->position, offset);
}
} }
} }
static struct sc_map_32 collision_events; static bool check_collision_and_move(EntityManager_t* p_manager, TileGrid_t* tilemap, CTransform_t *const p_ct, Vector2 sz, Vector2 other_pos, Vector2 other_sz, bool other_solid, uint32_t* collision_value)
{
Vector2 overlap = {0,0};
Vector2 prev_overlap = {0,0};
if (find_AABB_overlap(p_ct->position, sz, other_pos, other_sz, &overlap))
{
// If there is collision, use previous overlap to determine direction
find_AABB_overlap(p_ct->prev_position, sz, other_pos, other_sz, &prev_overlap);
// Store collision event here
// Check collision on x or y axis
// Encode key and value, -ve is left and up, +ve is right and down
uint8_t dir_to_move = 0;
Vector2 offset = {0, 0};
if (fabs(prev_overlap.y) > fabs(prev_overlap.x))
{
offset.x = overlap.x;
*collision_value = (((overlap.x > 0?1:0)<< 14) | ( (uint16_t)(fabs(overlap.x)) ));
}
else if (fabs(prev_overlap.x) > fabs(prev_overlap.y))
{
dir_to_move = 1;
offset.y = overlap.y;
*collision_value = (((overlap.y > 0?3:2)<< 14) | ( (uint16_t)(fabs(overlap.y)) ));
}
else if (fabs(overlap.x) < fabs(overlap.y))
{
offset.x = overlap.x;
*collision_value = (((overlap.x > 0?1:0)<< 14) | ( (uint16_t)(fabs(overlap.x)) ));
}
else
{
dir_to_move = 1;
offset.y = overlap.y;
*collision_value = (((overlap.y > 0?3:2)<< 14) | ( (uint16_t)(fabs(overlap.y)) ));
}
// Resolve collision via moving player by the overlap amount only if other is solid
// also check for empty to prevent creating new collision. Not fool-proof, but good enough
if (other_solid && !check_collision_at(p_ct->position, sz, tilemap, offset, p_manager))
{
p_ct->position = Vector2Add(p_ct->position, offset);
if (dir_to_move == 0)
//if (offset.x != 0)
{
p_ct->velocity.x = 0;
}
else
{
p_ct->velocity.y = 0;
}
}
return true;
}
return false;
}
void tile_collision_system(Scene_t *scene) void tile_collision_system(Scene_t *scene)
{ {
static bool checked_entities[MAX_COMP_POOL_SIZE] = {0}; static bool checked_entities[MAX_COMP_POOL_SIZE] = {0};
@ -322,54 +376,27 @@ void tile_collision_system(Scene_t *scene)
Entity_t *p_ent = get_entity(&scene->ent_manager, ent_idx); Entity_t *p_ent = get_entity(&scene->ent_manager, ent_idx);
CTransform_t* p_ctransform = get_component(&scene->ent_manager, p_ent, CTRANSFORM_COMP_T); CTransform_t* p_ctransform = get_component(&scene->ent_manager, p_ent, CTRANSFORM_COMP_T);
// Get the occupied tiles // Get the occupied tiles
// For each tile, loop through the entities and find overlaps // For each tile, loop through the entities, check collision and move
// exclude self // exclude self
// find also previous overlap
// If there is collision, use previous overlap to determine direction
// Resolve collision via moving player by the overlap amount
Vector2 overlap = {0};
Vector2 prev_overlap = {0};
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;
uint32_t collision_value;
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 * tilemap.width + tile_x; unsigned int tile_idx = tile_y * tilemap.width + tile_x;
//for (size_t i=0;i<p_tilecoord->n_tiles;++i)
//{
//unsigned int tile_idx = p_tilecoord->tiles[i];
Vector2 other; Vector2 other;
if(tilemap.tiles[tile_idx].solid) if(tilemap.tiles[tile_idx].solid)
{ {
other.x = (tile_idx % tilemap.width) * TILE_SIZE; other.x = (tile_idx % tilemap.width) * TILE_SIZE;
other.y = (tile_idx / tilemap.width) * TILE_SIZE; // Precision loss is intentional other.y = (tile_idx / tilemap.width) * TILE_SIZE; // Precision loss is intentional
if (find_AABB_overlap(p_ctransform->position, p_bbox->size, other, TILE_SZ, &overlap))
{ check_collision_and_move(&scene->ent_manager, &tilemap, p_ctransform, p_bbox->size, other, TILE_SZ, true, &collision_value);
find_AABB_overlap(p_ctransform->prev_position, p_bbox->size, other, TILE_SZ, &prev_overlap);
if (fabs(prev_overlap.y) > fabs(prev_overlap.x))
{
p_ctransform->position.x += overlap.x;
p_ctransform->velocity.x = 0;
}
else if (fabs(prev_overlap.x) > fabs(prev_overlap.y))
{
p_ctransform->position.y += overlap.y;
p_ctransform->velocity.y = 0;
}
else if (fabs(overlap.x) < fabs(overlap.y))
{
p_ctransform->position.x += overlap.x;
p_ctransform->velocity.x = 0;
}
else
{
p_ctransform->position.y += overlap.y;
p_ctransform->velocity.y = 0;
}
}
} }
else else
{ {
@ -387,49 +414,10 @@ void tile_collision_system(Scene_t *scene)
if (p_other_bbox == NULL) continue; if (p_other_bbox == NULL) continue;
CTransform_t *p_other_ct = get_component(&scene->ent_manager, p_other_ent, CTRANSFORM_COMP_T); CTransform_t *p_other_ct = get_component(&scene->ent_manager, p_other_ent, CTRANSFORM_COMP_T);
if (find_AABB_overlap(p_ctransform->position, p_bbox->size, p_other_ct->position, p_other_bbox->size, &overlap)) if (check_collision_and_move(&scene->ent_manager, &tilemap, p_ctransform, p_bbox->size, p_other_ct->position, p_other_bbox->size, p_other_bbox->solid, &collision_value))
{ {
find_AABB_overlap(p_ctransform->prev_position, p_bbox->size, p_other_ct->prev_position, p_other_bbox->size, &prev_overlap);
// TODO: Store collision event here
// Check collision on x or y axis
// Encode key and value, -ve is left and up, +ve is right and down
// Move only if solid
uint8_t dir_to_move = 0; // x-axis, y-axis
uint32_t collision_key = ((ent_idx << 16) | other_ent_idx); uint32_t collision_key = ((ent_idx << 16) | other_ent_idx);
uint32_t collision_value = 0; sc_map_put_32(&data->collision_events, collision_key, collision_value);
if (fabs(prev_overlap.y) > fabs(prev_overlap.x))
{
collision_value = (((overlap.x > 0?1:0)<< 14) | ( (uint16_t)(fabs(overlap.x)) ));
dir_to_move = 0;
}
else if (fabs(prev_overlap.x) > fabs(prev_overlap.y))
{
collision_value = (((overlap.y > 0?3:2)<< 14) | ( (uint16_t)(fabs(overlap.x)) ));
dir_to_move = 1;
}
else if (fabs(overlap.x) < fabs(overlap.y))
{
collision_value = (((overlap.x > 0?1:0)<< 14) | ( (uint16_t)(fabs(overlap.x)) ));
dir_to_move = 0;
}
else
{
collision_value = (((overlap.y > 0?3:2)<< 14) | ( (uint16_t)(fabs(overlap.x)) ));
dir_to_move = 1;
}
sc_map_put_32(&collision_events, collision_key, collision_value);
if (!p_other_bbox->solid) continue;
if (dir_to_move == 1)
{
p_ctransform->position.y += overlap.y;
p_ctransform->velocity.y = 0;
}
else
{
p_ctransform->position.x += overlap.x;
p_ctransform->velocity.x = 0;
}
} }
} }
} }
@ -437,8 +425,8 @@ void tile_collision_system(Scene_t *scene)
} }
// TODO: Resolve all collision events // TODO: Resolve all collision events
uint32_t collision_key, collision_value; uint32_t collision_key;
sc_map_foreach(&collision_events, collision_key, collision_value) sc_map_foreach(&data->collision_events, collision_key, collision_value)
{ {
ent_idx = (collision_key >> 16); ent_idx = (collision_key >> 16);
uint other_ent_idx = (collision_key & 0xFFFF); uint other_ent_idx = (collision_key & 0xFFFF);
@ -480,7 +468,7 @@ void tile_collision_system(Scene_t *scene)
} }
} }
} }
sc_map_clear_32(&collision_events); sc_map_clear_32(&data->collision_events);
// Level boundary collision // Level boundary collision
unsigned int level_width = tilemap.width * TILE_SIZE; unsigned int level_width = tilemap.width * TILE_SIZE;
@ -572,6 +560,37 @@ void global_external_forces_system(Scene_t *scene)
p_ctransform->accel.x += p_ctransform->velocity.x * -3.3; p_ctransform->accel.x += p_ctransform->velocity.x * -3.3;
p_ctransform->accel.y += p_ctransform->velocity.y * -1; p_ctransform->accel.y += p_ctransform->velocity.y * -1;
} }
// Zero out acceleration for contacts with sturdy entites and tiles
Vector2 new_pos = p_ctransform->position;
new_pos.x--;
TileArea_t area = {
.tile_x1 = (p_ctransform->position.x - 1) / TILE_SIZE,
.tile_y1 = (p_ctransform->position.y) / TILE_SIZE,
.tile_x2 = (p_ctransform->position.x - 1) / TILE_SIZE,
.tile_y2 = (p_ctransform->position.y + p_bbox->size.y - 1) / TILE_SIZE,
};
if (check_collision(new_pos, p_bbox->size, area, &data->tilemap, &scene->ent_manager) && p_ctransform->accel.x < 0) p_ctransform->accel.x = 0;
new_pos.x += 2; // 2 to account for the previous subtraction
area.tile_x1 = (p_ctransform->position.x + p_bbox->size.x + 1) / TILE_SIZE;
area.tile_x2 = area.tile_x1;
if (check_collision(new_pos, p_bbox->size, area, &data->tilemap, &scene->ent_manager) && p_ctransform->accel.x > 0) p_ctransform->accel.x = 0;
new_pos.x -= 2;
new_pos.y--;
area.tile_x1 = (p_ctransform->position.x) / TILE_SIZE,
area.tile_x2 = (p_ctransform->position.x - 1) / TILE_SIZE,
area.tile_y1 = (p_ctransform->position.y - 1) / TILE_SIZE,
area.tile_y1 = area.tile_y2;
if (check_collision(new_pos, p_bbox->size, area, &data->tilemap, &scene->ent_manager) && p_ctransform->accel.y < 0) p_ctransform->accel.y = 0;
new_pos.y += 2;
area.tile_y1 = (p_ctransform->position.y + p_bbox->size.y + 1) / TILE_SIZE,
area.tile_y1 = area.tile_y2;
if (check_collision(new_pos, p_bbox->size, area, &data->tilemap, &scene->ent_manager) && p_ctransform->accel.y > 0) p_ctransform->accel.y = 0;
} }
} }
@ -652,7 +671,7 @@ void state_transition_update_system(Scene_t *scene)
CBBox_t *p_bbox = get_component(&scene->ent_manager, p_ent, CBBOX_COMP_T); CBBox_t *p_bbox = get_component(&scene->ent_manager, p_ent, CBBOX_COMP_T);
if (p_ctransform == NULL || p_bbox == NULL) continue; if (p_ctransform == NULL || p_bbox == NULL) continue;
bool on_ground = check_on_ground(ent_idx, p_ctransform->position, p_bbox->size, &data->tilemap, scene); bool on_ground = check_on_ground(ent_idx, p_ctransform->position, p_bbox->size, &data->tilemap, &scene->ent_manager);
bool in_water = false; bool in_water = false;
if (!(p_mstate->water_state & 1)) if (!(p_mstate->water_state & 1))
{ {
@ -732,12 +751,12 @@ void update_tilemap_system(Scene_t *scene)
} }
} }
void init_collision_system(void) void init_level_scene_data(LevelSceneData_t *data)
{ {
sc_map_init_32(&collision_events, 128, 0); sc_map_init_32(&data->collision_events, 128, 0);
} }
void term_collision_system(void) void term_level_scene_data(LevelSceneData_t *data)
{ {
sc_map_term_32(&collision_events); sc_map_term_32(&data->collision_events);
} }

View File

@ -1,8 +1,8 @@
#ifndef __GAME_SYSTEMS_H #ifndef __GAME_SYSTEMS_H
#define __GAME_SYSTEMS_H #define __GAME_SYSTEMS_H
#include "scene_impl.h" #include "scene_impl.h"
void init_collision_system(void); void init_level_scene_data(LevelSceneData_t *data);
void term_collision_system(void); void term_level_scene_data(LevelSceneData_t *data);
void player_movement_input_system(Scene_t* scene); void player_movement_input_system(Scene_t* scene);
void player_bbox_update_system(Scene_t *scene); void player_bbox_update_system(Scene_t *scene);

View File

@ -250,7 +250,7 @@ void init_level_scene(LevelScene_t *scene)
init_scene(&scene->scene, LEVEL_SCENE, &level_scene_render_func, &level_do_action); init_scene(&scene->scene, LEVEL_SCENE, &level_scene_render_func, &level_do_action);
scene->scene.scene_data = &scene->data; scene->scene.scene_data = &scene->data;
init_collision_system(); init_level_scene_data(&scene->data);
// insert level scene systems // insert level scene systems
sc_array_add(&scene->scene.systems, &player_movement_input_system); sc_array_add(&scene->scene.systems, &player_movement_input_system);
sc_array_add(&scene->scene.systems, &player_bbox_update_system); sc_array_add(&scene->scene.systems, &player_bbox_update_system);
@ -300,7 +300,7 @@ void free_level_scene(LevelScene_t *scene)
all_tiles[i].solid = 0; all_tiles[i].solid = 0;
sc_map_term_64(&all_tiles[i].entities_set); sc_map_term_64(&all_tiles[i].entities_set);
} }
term_collision_system(); term_level_scene_data(&scene->data);
} }
void reload_level_scene(LevelScene_t *scene) void reload_level_scene(LevelScene_t *scene)

View File

@ -23,6 +23,7 @@ typedef struct TileGrid
typedef struct LevelSceneData typedef struct LevelSceneData
{ {
TileGrid_t tilemap; TileGrid_t tilemap;
struct sc_map_32 collision_events;
}LevelSceneData_t; }LevelSceneData_t;
typedef struct LevelScene typedef struct LevelScene