Compare commits
3 Commits
df66b7d9a3
...
8d94943547
Author | SHA1 | Date |
---|---|---|
|
8d94943547 | |
|
c8ea03359c | |
|
22b4190947 |
|
@ -14,7 +14,7 @@ enum ComponentEnum
|
||||||
CJUMP_COMP_T,
|
CJUMP_COMP_T,
|
||||||
CPLAYERSTATE_T,
|
CPLAYERSTATE_T,
|
||||||
CCONTAINER_T,
|
CCONTAINER_T,
|
||||||
CHITBOX_T,
|
CHITBOXES_T,
|
||||||
CHURTBOX_T,
|
CHURTBOX_T,
|
||||||
};
|
};
|
||||||
typedef enum ComponentEnum ComponentEnum_t;
|
typedef enum ComponentEnum ComponentEnum_t;
|
||||||
|
@ -97,12 +97,12 @@ typedef struct _CContainer_t
|
||||||
ContainerItem_t item;
|
ContainerItem_t item;
|
||||||
}CContainer_t;
|
}CContainer_t;
|
||||||
|
|
||||||
typedef struct _CHitBox_t
|
typedef struct _CHitBoxes_t
|
||||||
{
|
{
|
||||||
Vector2 offset;
|
Rectangle boxes[2];
|
||||||
Vector2 size;
|
uint8_t n_boxes;
|
||||||
bool strong;
|
bool strong;
|
||||||
}CHitBox_t;
|
}CHitBoxes_t;
|
||||||
|
|
||||||
typedef struct _CHurtbox_t
|
typedef struct _CHurtbox_t
|
||||||
{
|
{
|
||||||
|
|
|
@ -12,7 +12,7 @@ static CMovementState_t cmstate_buffer[MAX_COMP_POOL_SIZE];
|
||||||
static CJump_t cjump_buffer[1]; // Only player is expected to have this
|
static CJump_t cjump_buffer[1]; // Only player is expected to have this
|
||||||
static CPlayerState_t cplayerstate_buffer[1]; // Only player is expected to have this
|
static CPlayerState_t cplayerstate_buffer[1]; // Only player is expected to have this
|
||||||
static CContainer_t ccontainer_buffer[MAX_COMP_POOL_SIZE];
|
static CContainer_t ccontainer_buffer[MAX_COMP_POOL_SIZE];
|
||||||
static CHitBox_t chitbox_buffer[MAX_COMP_POOL_SIZE];
|
static CHitBoxes_t chitboxes_buffer[MAX_COMP_POOL_SIZE];
|
||||||
static CHurtbox_t churtbox_buffer[MAX_COMP_POOL_SIZE];
|
static CHurtbox_t churtbox_buffer[MAX_COMP_POOL_SIZE];
|
||||||
|
|
||||||
// Use hashmap as a Set
|
// Use hashmap as a Set
|
||||||
|
@ -40,7 +40,7 @@ static MemPool_t comp_mempools[N_COMPONENTS] =
|
||||||
{cjump_buffer, 1, sizeof(CJump_t), NULL, {0}},
|
{cjump_buffer, 1, sizeof(CJump_t), NULL, {0}},
|
||||||
{cplayerstate_buffer, 1, sizeof(CPlayerState_t), NULL, {0}},
|
{cplayerstate_buffer, 1, sizeof(CPlayerState_t), NULL, {0}},
|
||||||
{ccontainer_buffer, MAX_COMP_POOL_SIZE, sizeof(CContainer_t), NULL, {0}},
|
{ccontainer_buffer, MAX_COMP_POOL_SIZE, sizeof(CContainer_t), NULL, {0}},
|
||||||
{chitbox_buffer, MAX_COMP_POOL_SIZE, sizeof(CHitBox_t), NULL, {0}},
|
{chitboxes_buffer, MAX_COMP_POOL_SIZE, sizeof(CHitBoxes_t), NULL, {0}},
|
||||||
{churtbox_buffer, MAX_COMP_POOL_SIZE, sizeof(CHurtbox_t), NULL, {0}},
|
{churtbox_buffer, MAX_COMP_POOL_SIZE, sizeof(CHurtbox_t), NULL, {0}},
|
||||||
};
|
};
|
||||||
static MemPool_t ent_mempool = {entity_buffer, MAX_COMP_POOL_SIZE, sizeof(Entity_t), NULL, {0}};
|
static MemPool_t ent_mempool = {entity_buffer, MAX_COMP_POOL_SIZE, sizeof(Entity_t), NULL, {0}};
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
#define PLAYER_C_YOFFSET (PLAYER_HEIGHT - PLAYER_C_HEIGHT)
|
#define PLAYER_C_YOFFSET (PLAYER_HEIGHT - PLAYER_C_HEIGHT)
|
||||||
#define PLAYER_C_XOFFSET (PLAYER_WIDTH - PLAYER_C_WIDTH)
|
#define PLAYER_C_XOFFSET (PLAYER_WIDTH - PLAYER_C_WIDTH)
|
||||||
|
|
||||||
#define PLAYER_MAX_SPEED 1000
|
#define PLAYER_MAX_SPEED 800
|
||||||
#define Y_FRICTION 0.98
|
#define Y_FRICTION 0.98
|
||||||
#define X_FRICTION 0.85
|
#define X_FRICTION 0.85
|
||||||
|
|
||||||
|
|
|
@ -68,16 +68,19 @@ static void level_scene_render_func(Scene_t* scene)
|
||||||
}
|
}
|
||||||
DrawRectangle(p_ct->position.x, p_ct->position.y, p_bbox->size.x, p_bbox->size.y, colour);
|
DrawRectangle(p_ct->position.x, p_ct->position.y, p_bbox->size.x, p_bbox->size.y, colour);
|
||||||
CHurtbox_t* p_hurtbox = get_component(&scene->ent_manager, p_ent, CHURTBOX_T);
|
CHurtbox_t* p_hurtbox = get_component(&scene->ent_manager, p_ent, CHURTBOX_T);
|
||||||
CHitBox_t* p_hitbox = get_component(&scene->ent_manager, p_ent, CHITBOX_T);
|
CHitBoxes_t* p_hitbox = get_component(&scene->ent_manager, p_ent, CHITBOXES_T);
|
||||||
if (p_hitbox != NULL)
|
if (p_hitbox != NULL)
|
||||||
{
|
{
|
||||||
Rectangle rec = {
|
for (uint8_t i=0;i<p_hitbox->n_boxes;++i)
|
||||||
.x = p_ct->position.x + p_hitbox->offset.x,
|
{
|
||||||
.y = p_ct->position.y + p_hitbox->offset.y,
|
Rectangle rec = {
|
||||||
.width = p_hitbox->size.x,
|
.x = p_ct->position.x + p_hitbox->boxes[i].x,
|
||||||
.height = p_hitbox->size.y,
|
.y = p_ct->position.y + p_hitbox->boxes[i].y,
|
||||||
};
|
.width = p_hitbox->boxes[i].width,
|
||||||
DrawRectangleLinesEx(rec, 1.5, ORANGE);
|
.height = p_hitbox->boxes[i].height,
|
||||||
|
};
|
||||||
|
DrawRectangleLinesEx(rec, 1.5, ORANGE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (p_hurtbox != NULL)
|
if (p_hurtbox != NULL)
|
||||||
{
|
{
|
||||||
|
@ -129,6 +132,10 @@ static void level_scene_render_func(Scene_t* scene)
|
||||||
CMovementState_t* p_mstate = get_component(&scene->ent_manager, p_ent, CMOVEMENTSTATE_T);
|
CMovementState_t* p_mstate = get_component(&scene->ent_manager, p_ent, CMOVEMENTSTATE_T);
|
||||||
sprintf(buffer, "Pos: %.3f\n %.3f", p_ct->position.x, p_ct->position.y);
|
sprintf(buffer, "Pos: %.3f\n %.3f", p_ct->position.x, p_ct->position.y);
|
||||||
DrawText(buffer, tilemap.width * TILE_SIZE + 1, 15, 12, BLACK);
|
DrawText(buffer, tilemap.width * TILE_SIZE + 1, 15, 12, BLACK);
|
||||||
|
sprintf(buffer, "Vel: %.3f\n %.3f", p_ct->velocity.x, p_ct->velocity.y);
|
||||||
|
DrawText(buffer, tilemap.width * TILE_SIZE + 128, 15, 12, BLACK);
|
||||||
|
//sprintf(buffer, "Accel: %.3f\n %.3f", p_ct->accel.x, p_ct->accel.y);
|
||||||
|
//DrawText(buffer, tilemap.width * TILE_SIZE + 128, 60, 12, BLACK);
|
||||||
sprintf(buffer, "Jumps: %u", p_cjump->jumps);
|
sprintf(buffer, "Jumps: %u", p_cjump->jumps);
|
||||||
DrawText(buffer, tilemap.width * TILE_SIZE + 1, 60, 12, BLACK);
|
DrawText(buffer, tilemap.width * TILE_SIZE + 1, 60, 12, BLACK);
|
||||||
sprintf(buffer, "Crouch: %u", p_pstate->is_crouch);
|
sprintf(buffer, "Crouch: %u", p_pstate->is_crouch);
|
||||||
|
@ -181,9 +188,22 @@ static void spawn_player(Scene_t *scene)
|
||||||
add_component(&scene->ent_manager, p_ent, CPLAYERSTATE_T);
|
add_component(&scene->ent_manager, p_ent, CPLAYERSTATE_T);
|
||||||
add_component(&scene->ent_manager, p_ent, CTILECOORD_COMP_T);
|
add_component(&scene->ent_manager, p_ent, CTILECOORD_COMP_T);
|
||||||
add_component(&scene->ent_manager, p_ent, CMOVEMENTSTATE_T);
|
add_component(&scene->ent_manager, p_ent, CMOVEMENTSTATE_T);
|
||||||
CHitBox_t* p_hitbox = add_component(&scene->ent_manager, p_ent, CHITBOX_T);
|
CHitBoxes_t* p_hitbox = add_component(&scene->ent_manager, p_ent, CHITBOXES_T);
|
||||||
p_hitbox->size = Vector2Add(p_bbox->size, (Vector2){2,2});
|
p_hitbox->n_boxes = 2;
|
||||||
p_hitbox->offset = (Vector2){-1, -1};
|
p_hitbox->boxes[0] = (Rectangle)
|
||||||
|
{
|
||||||
|
.x = p_bbox->size.x / 4,
|
||||||
|
.y = -1,
|
||||||
|
.width = p_bbox->size.x / 2,
|
||||||
|
.height = p_bbox->size.y + 2,
|
||||||
|
};
|
||||||
|
p_hitbox->boxes[1] = (Rectangle)
|
||||||
|
{
|
||||||
|
.x = -1,
|
||||||
|
.y = p_bbox->size.y / 4,
|
||||||
|
.width = p_bbox->size.x + 2 ,
|
||||||
|
.height = p_bbox->size.y / 2,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static void toggle_block_system(Scene_t *scene)
|
static void toggle_block_system(Scene_t *scene)
|
||||||
|
|
|
@ -34,18 +34,26 @@ typedef struct TileArea
|
||||||
unsigned int tile_y2;
|
unsigned int tile_y2;
|
||||||
}TileArea_t;
|
}TileArea_t;
|
||||||
|
|
||||||
static bool check_collision(unsigned int self_idx, Vector2 pos, Vector2 bbox_sz, TileArea_t area_to_check, TileGrid_t* grid, EntityManager_t* p_manager)
|
typedef struct CollideEntity
|
||||||
{
|
{
|
||||||
for(unsigned int tile_y = area_to_check.tile_y1; tile_y <= area_to_check.tile_y2; tile_y++)
|
unsigned int idx;
|
||||||
|
Rectangle bbox;
|
||||||
|
TileArea_t area;
|
||||||
|
}CollideEntity_t;
|
||||||
|
|
||||||
|
// ------------------------- Collision functions ------------------------------------
|
||||||
|
static bool check_collision(const CollideEntity_t *ent, TileGrid_t* grid, EntityManager_t* p_manager)
|
||||||
|
{
|
||||||
|
for(unsigned int tile_y = ent->area.tile_y1; tile_y <= ent->area.tile_y2; tile_y++)
|
||||||
{
|
{
|
||||||
for(unsigned int tile_x = area_to_check.tile_x1; tile_x <= area_to_check.tile_x2; tile_x++)
|
for(unsigned int tile_x = ent->area.tile_x1; tile_x <= ent->area.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 ent_idx;
|
||||||
sc_map_foreach_value(&grid->tiles[tile_idx].entities_set, ent_idx)
|
sc_map_foreach_value(&grid->tiles[tile_idx].entities_set, ent_idx)
|
||||||
{
|
{
|
||||||
if (self_idx == ent_idx) continue;
|
if (ent->idx == ent_idx) continue;
|
||||||
Entity_t * p_ent = get_entity(p_manager, 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);
|
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);
|
CBBox_t *p_bbox = get_component(p_manager, p_ent, CBBOX_COMP_T);
|
||||||
|
@ -54,7 +62,7 @@ static bool check_collision(unsigned int self_idx, Vector2 pos, Vector2 bbox_sz,
|
||||||
//if (p_bbox->solid && !p_bbox->fragile)
|
//if (p_bbox->solid && !p_bbox->fragile)
|
||||||
if (p_bbox->solid)
|
if (p_bbox->solid)
|
||||||
{
|
{
|
||||||
if (find_AABB_overlap(pos, bbox_sz, p_ctransform->position, p_bbox->size, &overlap))
|
if (find_AABB_overlap((Vector2){ent->bbox.x, ent->bbox.y}, (Vector2){ent->bbox.width, ent->bbox.height}, p_ctransform->position, p_bbox->size, &overlap))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -69,27 +77,89 @@ static bool check_collision(unsigned int self_idx, Vector2 pos, Vector2 bbox_sz,
|
||||||
static bool check_collision_at(unsigned int ent_idx, Vector2 pos, Vector2 bbox_sz, TileGrid_t* grid, Vector2 point, EntityManager_t* p_manager)
|
static bool check_collision_at(unsigned int ent_idx, Vector2 pos, Vector2 bbox_sz, TileGrid_t* grid, Vector2 point, EntityManager_t* p_manager)
|
||||||
{
|
{
|
||||||
Vector2 new_pos = Vector2Add(pos, point);
|
Vector2 new_pos = Vector2Add(pos, point);
|
||||||
TileArea_t area = {
|
CollideEntity_t ent =
|
||||||
.tile_x1 = (new_pos.x) / TILE_SIZE,
|
{
|
||||||
.tile_y1 = (new_pos.y) / TILE_SIZE,
|
.idx = ent_idx,
|
||||||
.tile_x2 = (new_pos.x + bbox_sz.x - 1) / TILE_SIZE,
|
.bbox = (Rectangle){new_pos.x, new_pos.y, bbox_sz.x, bbox_sz.y},
|
||||||
.tile_y2 = (new_pos.y + bbox_sz.y - 1) / TILE_SIZE
|
.area = (TileArea_t){
|
||||||
|
.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(ent_idx, new_pos, bbox_sz, area, grid, p_manager);
|
return check_collision(&ent, 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)
|
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;
|
return check_collision_at(ent_idx, pos, bbox_sz, grid, (Vector2){0, 1}, p_manager);
|
||||||
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(ent_idx, pos, bbox_sz, area, grid, p_manager);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool check_collision_and_move(EntityManager_t* p_manager, TileGrid_t* tilemap,
|
||||||
|
unsigned int ent_idx, 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(ent_idx, p_ct->position, sz, tilemap, offset, p_manager))
|
||||||
|
if (other_solid)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static Vector2 shift_bbox(Vector2 bbox, Vector2 new_bbox, AnchorPoint_t anchor)
|
static Vector2 shift_bbox(Vector2 bbox, Vector2 new_bbox, AnchorPoint_t anchor)
|
||||||
{
|
{
|
||||||
Vector2 p1;
|
Vector2 p1;
|
||||||
|
@ -179,11 +249,13 @@ void player_movement_input_system(Scene_t* scene)
|
||||||
if (!in_water)
|
if (!in_water)
|
||||||
{
|
{
|
||||||
p_pstate->player_dir.y = 0;
|
p_pstate->player_dir.y = 0;
|
||||||
p_ctransform->accel = Vector2Scale(Vector2Normalize(p_pstate->player_dir), MOVE_ACCEL/1.2);
|
p_ctransform->accel = Vector2Scale(Vector2Normalize(p_pstate->player_dir), MOVE_ACCEL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
p_ctransform->accel = Vector2Scale(Vector2Normalize(p_pstate->player_dir), MOVE_ACCEL);
|
// Although this can be achieved via higher friction, i'll explain away as the player is not
|
||||||
|
// good with swimming, resulting in lower movement acceleration
|
||||||
|
p_ctransform->accel = Vector2Scale(Vector2Normalize(p_pstate->player_dir), MOVE_ACCEL/1.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Short Hop
|
// Short Hop
|
||||||
|
@ -297,66 +369,14 @@ void player_bbox_update_system(Scene_t *scene)
|
||||||
set_bbox(p_bbox, new_bbox.x, new_bbox.y);
|
set_bbox(p_bbox, new_bbox.x, new_bbox.y);
|
||||||
p_ctransform->position = Vector2Add(p_ctransform->position, offset);
|
p_ctransform->position = Vector2Add(p_ctransform->position, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CHitBoxes_t* p_hitbox = get_component(&scene->ent_manager, p_player, CHITBOXES_T);
|
||||||
|
p_hitbox->boxes[0].height = p_bbox->size.y + 2;
|
||||||
|
p_hitbox->boxes[1].y = p_bbox->size.y / 4;
|
||||||
|
p_hitbox->boxes[1].height = p_bbox->size.y / 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool check_collision_and_move(unsigned int ent_idx, 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(ent_idx, 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};
|
||||||
|
@ -392,7 +412,7 @@ void tile_collision_system(Scene_t *scene)
|
||||||
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
|
||||||
|
|
||||||
check_collision_and_move(ent_idx, &scene->ent_manager, &tilemap, p_ctransform, p_bbox->size, other, TILE_SZ, true, &collision_value);
|
check_collision_and_move(&scene->ent_manager, &tilemap, ent_idx, p_ctransform, p_bbox->size, other, TILE_SZ, true, &collision_value);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -412,7 +432,7 @@ 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 (check_collision_and_move(ent_idx, &scene->ent_manager, &tilemap, p_ctransform, p_bbox->size, p_other_ct->position, p_other_bbox->size, p_other_bbox->solid, &collision_value))
|
if (check_collision_and_move(&scene->ent_manager, &tilemap, ent_idx, p_ctransform, p_bbox->size, p_other_ct->position, p_other_bbox->size, p_other_bbox->solid, &collision_value))
|
||||||
{
|
{
|
||||||
uint32_t collision_key = ((ent_idx << 16) | other_ent_idx);
|
uint32_t collision_key = ((ent_idx << 16) | other_ent_idx);
|
||||||
sc_map_put_32(&data->collision_events, collision_key, collision_value);
|
sc_map_put_32(&data->collision_events, collision_key, collision_value);
|
||||||
|
@ -527,33 +547,37 @@ void global_external_forces_system(Scene_t *scene)
|
||||||
|
|
||||||
|
|
||||||
// Zero out acceleration for contacts with sturdy entites and tiles
|
// Zero out acceleration for contacts with sturdy entites and tiles
|
||||||
Vector2 new_pos = p_ctransform->position;
|
//Vector2 new_pos = p_ctransform->position;
|
||||||
new_pos.x--;
|
CollideEntity_t ent =
|
||||||
TileArea_t area = {
|
{
|
||||||
.tile_x1 = (p_ctransform->position.x - 1) / TILE_SIZE,
|
.idx = ent_idx,
|
||||||
.tile_y1 = (p_ctransform->position.y) / TILE_SIZE,
|
.bbox = (Rectangle){p_ctransform->position.x - 1, p_ctransform->position.y, p_bbox->size.x, p_bbox->size.y},
|
||||||
.tile_x2 = (p_ctransform->position.x - 1) / TILE_SIZE,
|
.area = (TileArea_t){
|
||||||
.tile_y2 = (p_ctransform->position.y + p_bbox->size.y - 1) / TILE_SIZE,
|
.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(ent_idx, new_pos, p_bbox->size, area, &data->tilemap, &scene->ent_manager) && p_ctransform->accel.x < 0) p_ctransform->accel.x = 0;
|
if (check_collision(&ent, &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
|
ent.bbox.x += 2; // 2 to account for the previous subtraction
|
||||||
area.tile_x1 = (p_ctransform->position.x + p_bbox->size.x + 1) / TILE_SIZE;
|
ent.area.tile_x1 = (p_ctransform->position.x + p_bbox->size.x + 1) / TILE_SIZE;
|
||||||
area.tile_x2 = area.tile_x1;
|
ent.area.tile_x2 = ent.area.tile_x1;
|
||||||
if (check_collision(ent_idx, new_pos, p_bbox->size, area, &data->tilemap, &scene->ent_manager) && p_ctransform->accel.x > 0) p_ctransform->accel.x = 0;
|
if (check_collision(&ent, &data->tilemap, &scene->ent_manager) && p_ctransform->accel.x > 0) p_ctransform->accel.x = 0;
|
||||||
|
|
||||||
new_pos.x -= 2;
|
ent.bbox.x -= 2;
|
||||||
new_pos.y--;
|
ent.bbox.y--;
|
||||||
area.tile_x1 = (p_ctransform->position.x) / TILE_SIZE,
|
ent.area.tile_x1 = (p_ctransform->position.x) / TILE_SIZE,
|
||||||
area.tile_x2 = (p_ctransform->position.x - 1) / TILE_SIZE,
|
ent.area.tile_x2 = (p_ctransform->position.x - 1) / TILE_SIZE,
|
||||||
area.tile_y1 = (p_ctransform->position.y - 1) / TILE_SIZE,
|
ent.area.tile_y1 = (p_ctransform->position.y - 1) / TILE_SIZE,
|
||||||
area.tile_y1 = area.tile_y2;
|
ent.area.tile_y1 = ent.area.tile_y2;
|
||||||
if (check_collision(ent_idx, new_pos, p_bbox->size, area, &data->tilemap, &scene->ent_manager) && p_ctransform->accel.y < 0) p_ctransform->accel.y = 0;
|
if (check_collision(&ent, &data->tilemap, &scene->ent_manager) && p_ctransform->accel.y < 0) p_ctransform->accel.y = 0;
|
||||||
|
|
||||||
new_pos.y += 2;
|
ent.bbox.y += 2;
|
||||||
area.tile_y1 = (p_ctransform->position.y + p_bbox->size.y + 1) / TILE_SIZE,
|
ent.area.tile_y1 = (p_ctransform->position.y + p_bbox->size.y + 1) / TILE_SIZE,
|
||||||
area.tile_y1 = area.tile_y2;
|
ent.area.tile_y1 = ent.area.tile_y2;
|
||||||
if (check_collision(ent_idx, new_pos, p_bbox->size, area, &data->tilemap, &scene->ent_manager) && p_ctransform->accel.y > 0) p_ctransform->accel.y = 0;
|
if (check_collision(&ent, &data->tilemap, &scene->ent_manager) && p_ctransform->accel.y > 0) p_ctransform->accel.y = 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -723,73 +747,79 @@ void hitbox_update_system(Scene_t *scene)
|
||||||
TileGrid_t tilemap = data->tilemap;
|
TileGrid_t tilemap = data->tilemap;
|
||||||
|
|
||||||
unsigned int ent_idx;
|
unsigned int ent_idx;
|
||||||
CHitBox_t* p_hitbox;
|
CHitBoxes_t* p_hitbox;
|
||||||
//sc_map_foreach_value(&scene->ent_manager.entities_map[PLAYER_ENT_TAG], p_player)
|
//sc_map_foreach_value(&scene->ent_manager.entities_map[PLAYER_ENT_TAG], p_player)
|
||||||
sc_map_foreach(&scene->ent_manager.component_map[CHITBOX_T], ent_idx, p_hitbox)
|
sc_map_foreach(&scene->ent_manager.component_map[CHITBOXES_T], ent_idx, p_hitbox)
|
||||||
{
|
{
|
||||||
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);
|
||||||
Vector2 hitbox_pos = Vector2Add(p_ctransform->position, p_hitbox->offset);
|
for (uint8_t i=0;i<p_hitbox->n_boxes;++i)
|
||||||
|
|
||||||
unsigned int tile_x1 = (hitbox_pos.x) / TILE_SIZE;
|
|
||||||
unsigned int tile_y1 = (hitbox_pos.y) / TILE_SIZE;
|
|
||||||
unsigned int tile_x2 = (hitbox_pos.x + p_hitbox->size.x - 1) / TILE_SIZE;
|
|
||||||
unsigned int tile_y2 = (hitbox_pos.y + p_hitbox->size.y - 1) / TILE_SIZE;
|
|
||||||
|
|
||||||
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++)
|
Vector2 hitbox_pos = {
|
||||||
|
.x = p_ctransform->position.x + p_hitbox->boxes[i].x,
|
||||||
|
.y = p_ctransform->position.y + p_hitbox->boxes[i].y,
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned int tile_x1 = (hitbox_pos.x) / TILE_SIZE;
|
||||||
|
unsigned int tile_y1 = (hitbox_pos.y) / TILE_SIZE;
|
||||||
|
unsigned int tile_x2 = (hitbox_pos.x + p_hitbox->boxes[i].width - 1) / TILE_SIZE;
|
||||||
|
unsigned int tile_y2 = (hitbox_pos.y + p_hitbox->boxes[i].height - 1) / TILE_SIZE;
|
||||||
|
|
||||||
|
for (unsigned int tile_y=tile_y1; tile_y <= tile_y2; tile_y++)
|
||||||
{
|
{
|
||||||
unsigned int tile_idx = tile_y * tilemap.width + tile_x;
|
for (unsigned int tile_x=tile_x1; tile_x <= tile_x2; tile_x++)
|
||||||
unsigned int other_ent_idx;
|
|
||||||
memset(checked_entities, 0, sizeof(checked_entities));
|
|
||||||
sc_map_foreach_key(&tilemap.tiles[tile_idx].entities_set, other_ent_idx)
|
|
||||||
{
|
{
|
||||||
if (other_ent_idx == ent_idx) continue;
|
unsigned int tile_idx = tile_y * tilemap.width + tile_x;
|
||||||
if (checked_entities[other_ent_idx]) continue;
|
unsigned int other_ent_idx;
|
||||||
|
memset(checked_entities, 0, sizeof(checked_entities));
|
||||||
Entity_t *p_other_ent = get_entity(&scene->ent_manager, other_ent_idx);
|
sc_map_foreach_key(&tilemap.tiles[tile_idx].entities_set, other_ent_idx)
|
||||||
if (!p_other_ent->m_alive) continue; // To only allow one way collision check
|
|
||||||
if (p_other_ent->m_tag < p_ent->m_tag) continue; // To only allow one way collision check
|
|
||||||
|
|
||||||
CHurtbox_t *p_other_hurtbox = get_component(&scene->ent_manager, p_other_ent, CHURTBOX_T);
|
|
||||||
if (p_other_hurtbox == NULL) continue;
|
|
||||||
CTransform_t *p_other_ct = get_component(&scene->ent_manager, p_other_ent, CTRANSFORM_COMP_T);
|
|
||||||
Vector2 hurtbox_pos = Vector2Add(p_other_ct->position, p_other_hurtbox->offset);
|
|
||||||
|
|
||||||
Vector2 overlap;
|
|
||||||
if (find_AABB_overlap(hitbox_pos, p_hitbox->size, hurtbox_pos, p_other_hurtbox->size, &overlap))
|
|
||||||
{
|
{
|
||||||
if (!p_other_hurtbox->fragile) continue;
|
if (other_ent_idx == ent_idx) continue;
|
||||||
if (p_other_ent->m_tag == CRATES_ENT_TAG)
|
if (checked_entities[other_ent_idx]) 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
|
||||||
|
if (p_other_ent->m_tag < p_ent->m_tag) continue; // To only allow one way collision check
|
||||||
|
|
||||||
|
CHurtbox_t *p_other_hurtbox = get_component(&scene->ent_manager, p_other_ent, CHURTBOX_T);
|
||||||
|
if (p_other_hurtbox == NULL) continue;
|
||||||
|
CTransform_t *p_other_ct = get_component(&scene->ent_manager, p_other_ent, CTRANSFORM_COMP_T);
|
||||||
|
Vector2 hurtbox_pos = Vector2Add(p_other_ct->position, p_other_hurtbox->offset);
|
||||||
|
|
||||||
|
Vector2 overlap;
|
||||||
|
if (find_AABB_overlap(hitbox_pos, (Vector2){p_hitbox->boxes[i].width, p_hitbox->boxes[i].height}, hurtbox_pos, p_other_hurtbox->size, &overlap))
|
||||||
{
|
{
|
||||||
|
if (!p_other_hurtbox->fragile) continue;
|
||||||
CBBox_t * p_bbox = get_component(&scene->ent_manager, p_ent, CBBOX_COMP_T);
|
if (p_other_ent->m_tag == CRATES_ENT_TAG)
|
||||||
CPlayerState_t * p_pstate = get_component(&scene->ent_manager, p_ent, CPLAYERSTATE_T);
|
|
||||||
if (
|
|
||||||
// TODO: Check Material of the crates
|
|
||||||
p_ctransform->position.y + p_bbox->size.y <= p_other_ct->position.y
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
p_ctransform->velocity.y = -400;
|
|
||||||
if (p_pstate->jump_pressed)
|
CBBox_t * p_bbox = get_component(&scene->ent_manager, p_ent, CBBOX_COMP_T);
|
||||||
|
CPlayerState_t * p_pstate = get_component(&scene->ent_manager, p_ent, CPLAYERSTATE_T);
|
||||||
|
if (
|
||||||
|
// TODO: Check Material of the crates
|
||||||
|
p_ctransform->position.y + p_bbox->size.y <= p_other_ct->position.y
|
||||||
|
)
|
||||||
{
|
{
|
||||||
p_ctransform->velocity.y = -600;
|
p_ctransform->velocity.y = -400;
|
||||||
CJump_t * p_cjump = get_component(&scene->ent_manager, p_ent, CJUMP_COMP_T);
|
if (p_pstate->jump_pressed)
|
||||||
p_cjump->short_hop = false;
|
{
|
||||||
p_cjump->jumped = true;
|
p_ctransform->velocity.y = -600;
|
||||||
|
CJump_t * p_cjump = get_component(&scene->ent_manager, p_ent, CJUMP_COMP_T);
|
||||||
|
p_cjump->short_hop = false;
|
||||||
|
p_cjump->jumped = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
CTileCoord_t *p_tilecoord = get_component(&scene->ent_manager, p_other_ent, CTILECOORD_COMP_T);
|
CTileCoord_t *p_tilecoord = get_component(&scene->ent_manager, p_other_ent, CTILECOORD_COMP_T);
|
||||||
for (size_t i=0;i<p_tilecoord->n_tiles;++i)
|
for (size_t i=0;i<p_tilecoord->n_tiles;++i)
|
||||||
{
|
{
|
||||||
// Use previously store tile position
|
// Use previously store tile position
|
||||||
// Clear from those positions
|
// Clear from those positions
|
||||||
unsigned int tile_idx = p_tilecoord->tiles[i];
|
unsigned int tile_idx = p_tilecoord->tiles[i];
|
||||||
sc_map_del_64(&(tilemap.tiles[tile_idx].entities_set), other_ent_idx);
|
sc_map_del_64(&(tilemap.tiles[tile_idx].entities_set), other_ent_idx);
|
||||||
|
}
|
||||||
|
remove_entity(&scene->ent_manager, other_ent_idx);
|
||||||
}
|
}
|
||||||
remove_entity(&scene->ent_manager, other_ent_idx);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue