|
|
@ -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_y = area_to_check.tile_y1; tile_y <= area_to_check.tile_y2; tile_y++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
for(unsigned int tile_x = tile_x1; tile_x <= tile_x2; tile_x++)
|
|
|
|
for(unsigned int tile_x = area_to_check.tile_x1; tile_x <= area_to_check.tile_x2; tile_x++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (grid->tiles[tile_y*grid->width + tile_x].solid) return true;
|
|
|
|
unsigned int tile_idx = tile_y*grid->width + tile_x;
|
|
|
|
|
|
|
|
if (grid->tiles[tile_idx].solid) return true;
|
|
|
|
|
|
|
|
unsigned int ent_idx;
|
|
|
|
|
|
|
|
sc_map_foreach_value(&grid->tiles[tile_idx].entities_set, 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;
|
|
|
|
|
|
|
|
if (p_bbox == NULL || p_ctransform == NULL) continue;
|
|
|
|
|
|
|
|
if (p_bbox->solid && !p_bbox->fragile && find_AABB_overlap(pos, bbox_sz, p_ctransform->position, p_bbox->size, &overlap)) return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static inline bool check_on_ground(unsigned int ent_idx, Vector2 pos, Vector2 bbox_sz, TileGrid_t* grid, Scene_t* scene)
|
|
|
|
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;
|
|
|
|
pos.y += 1;
|
|
|
|
unsigned int tile_x1 = (pos.x) / TILE_SIZE;
|
|
|
|
TileArea_t area = {
|
|
|
|
unsigned int tile_x2 = (pos.x + bbox_sz.x - 1) / TILE_SIZE;
|
|
|
|
.tile_x1 = (pos.x) / TILE_SIZE,
|
|
|
|
unsigned int tile_y = (pos.y + bbox_sz.y - 1) / TILE_SIZE;
|
|
|
|
.tile_y1 = (pos.y + bbox_sz.y - 1) / TILE_SIZE,
|
|
|
|
|
|
|
|
.tile_x2 = (pos.x + bbox_sz.x - 1) / TILE_SIZE,
|
|
|
|
for(unsigned int tile_x = tile_x1; tile_x <= tile_x2; tile_x++)
|
|
|
|
.tile_y2 = (pos.y + bbox_sz.y - 1) / TILE_SIZE,
|
|
|
|
{
|
|
|
|
};
|
|
|
|
unsigned int tile_idx = tile_y*grid->width + tile_x;
|
|
|
|
return check_collision(pos, bbox_sz, area, grid, p_manager);
|
|
|
|
if (grid->tiles[tile_idx].solid) return true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
unsigned int other_ent_idx;
|
|
|
|
|
|
|
|
sc_map_foreach_key(&grid->tiles[tile_idx].entities_set, other_ent_idx)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
Vector2 overlap;
|
|
|
|
|
|
|
|
if (other_ent_idx == ent_idx) continue;
|
|
|
|
|
|
|
|
Entity_t *p_other_ent = get_entity(&scene->ent_manager, other_ent_idx);
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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};
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hit)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|