Entity collision

main
Cameron Murphy Reikes 2 years ago
parent fadae61b2b
commit 8c24344dc9

144
main.c

@ -105,7 +105,7 @@ typedef struct Entity
#define LEVEL_TILES 60
#define TILE_SIZE 32 // in pixels
#define MAX_ENTITIES 128
#define PLAYER_SPEED 3.0f // in meters per second
#define PLAYER_SPEED 3.5f // in meters per second
#define PLAYER_ROLL_SPEED 7.0f
typedef struct Level
{
@ -170,6 +170,23 @@ char *tprint(const char *format, ...)
return to_return;
}
Vec2 entity_aabb_size(Entity *e)
{
if(e->kind == ENTITY_PLAYER)
{
return V2(TILE_SIZE, TILE_SIZE);
}
else if(e->kind == ENTITY_OLD_MAN)
{
return V2(TILE_SIZE*0.5f, TILE_SIZE*0.5f);
}
else
{
assert(false);
return (Vec2){0};
}
}
// tilecoord is integer tile position, not like tile coord
Vec2 tilecoord_to_world(TileCoord t)
{
@ -858,12 +875,18 @@ void line(Vec2 from, Vec2 to, float line_width, Color color)
void dbgline(Vec2 from, Vec2 to)
{
#ifdef DEVTOOLS
line(from, to, 2.0f, RED);
#else
(void)from;
(void)to;
#endif
}
// in world space
void dbgrect(AABB rect)
{
#ifdef DEVTOOLS
const float line_width = 0.5;
const Color col = RED;
Quad q = quad_aabb(rect);
@ -871,65 +894,88 @@ void dbgrect(AABB rect)
line(q.ur, q.lr, line_width, col);
line(q.lr, q.ll, line_width, col);
line(q.ll, q.ul, line_width, col);
#else
(void)rect;
#endif
}
// returns new pos after moving and sliding against collidable things
Vec2 move_and_slide(Vec2 position, Vec2 movement_this_frame, Vec2 collision_aabb_size)
Vec2 move_and_slide(Entity *from, Vec2 position, Vec2 movement_this_frame)
{
Vec2 collision_aabb_size = entity_aabb_size(from);
Vec2 new_pos = AddV2(position, movement_this_frame);
AABB at_new = centered_aabb(new_pos, collision_aabb_size);
Vec2 at_new_size_vector = SubV2(at_new.lower_right, at_new.upper_left);
Vec2 points_to_check[] = {
AddV2(at_new.upper_left, V2(0.0, 0.0)),
AddV2(at_new.upper_left, V2(at_new_size_vector.X, 0.0)),
AddV2(at_new.upper_left, V2(at_new_size_vector.X, at_new_size_vector.Y)),
AddV2(at_new.upper_left, V2(0.0, at_new_size_vector.Y)),
};
//dbgsquare(position);
//dbgsquare(at_new.upper_left);
//dbgsquare(at_new.lower_right);
for(int i = 0; i < sizeof(points_to_check)/sizeof(*points_to_check); i++)
dbgrect(at_new);
AABB to_check[64] = {0};
int to_check_index = 0;
// add tilemap boxes
{
Vec2 *it = &points_to_check[i];
TileCoord to_check = world_to_tilecoord(*it);
Vec2 at_new_size_vector = SubV2(at_new.lower_right, at_new.upper_left);
Vec2 points_to_check[] = {
AddV2(at_new.upper_left, V2(0.0, 0.0)),
AddV2(at_new.upper_left, V2(at_new_size_vector.X, 0.0)),
AddV2(at_new.upper_left, V2(at_new_size_vector.X, at_new_size_vector.Y)),
AddV2(at_new.upper_left, V2(0.0, at_new_size_vector.Y)),
};
for(int i = 0; i < ARRLEN(points_to_check); i++)
{
Vec2 *it = &points_to_check[i];
TileCoord tilecoord_to_check = world_to_tilecoord(*it);
uint16_t tile_id = get_tile(&level_level0, to_check).kind;
if(tile_id == 53 || tile_id == 0 || tile_id == 367 || tile_id == 317 || tile_id == 313 || tile_id == 366 || tile_id == 368)
uint16_t tile_id = get_tile(&level_level0, tilecoord_to_check).kind;
if(tile_id == 53 || tile_id == 0 || tile_id == 367 || tile_id == 317 || tile_id == 313 || tile_id == 366 || tile_id == 368)
{
to_check[to_check_index++] = tile_aabb(tilecoord_to_check);
assert(to_check_index < ARRLEN(to_check));
}
}
}
// add entity boxes
if(!(from->kind == ENTITY_PLAYER && from->is_rolling))
{
for(int i = 0; i < ARRLEN(entities); i++) if(entities[i].exists)
{
dbgsquare(tilecoord_to_world(to_check));
AABB to_depenetrate_from = tile_aabb(to_check);
while(overlapping(to_depenetrate_from, at_new))
{
//while(false)
if(&entities[i] != from)
{
to_check[to_check_index++] = centered_aabb(entities[i].pos, entity_aabb_size(&entities[i]));
}
}
}
for(int i = 0; i < to_check_index; i++)
{
AABB to_depenetrate_from = to_check[i];
dbgrect(to_depenetrate_from);
while(overlapping(to_depenetrate_from, at_new))
{
//dbgsquare(to_depenetrate_from.upper_left);
//dbgsquare(to_depenetrate_from.lower_right);
const float move_dist = 0.05f;
Vec2 to_player = NormV2(SubV2(aabb_center(at_new), aabb_center(to_depenetrate_from)));
Vec2 compass_dirs[4] = {
V2( 1.0, 0.0),
V2(-1.0, 0.0),
V2(0.0, 1.0),
V2(0.0, -1.0),
};
int closest_index = -1;
float closest_dot = -99999999.0f;
for(int i = 0; i < 4; i++)
{
float dot = DotV2(compass_dirs[i], to_player);
if(dot > closest_dot)
{
//dbgsquare(to_depenetrate_from.upper_left);
//dbgsquare(to_depenetrate_from.lower_right);
const float move_dist = 0.05f;
Vec2 to_player = NormV2(SubV2(aabb_center(at_new), aabb_center(to_depenetrate_from)));
Vec2 compass_dirs[4] = {
V2( 1.0, 0.0),
V2(-1.0, 0.0),
V2(0.0, 1.0),
V2(0.0, -1.0),
};
int closest_index = -1;
float closest_dot = -99999999.0f;
for(int i = 0; i < 4; i++)
{
float dot = DotV2(compass_dirs[i], to_player);
if(dot > closest_dot)
{
closest_index = i;
closest_dot = dot;
}
}
Vec2 move_dir = compass_dirs[closest_index];
Vec2 move = MulV2F(move_dir, move_dist);
at_new.upper_left = AddV2(at_new.upper_left,move);
at_new.lower_right = AddV2(at_new.lower_right,move);
closest_index = i;
closest_dot = dot;
}
}
Vec2 move_dir = compass_dirs[closest_index];
Vec2 move = MulV2F(move_dir, move_dist);
at_new.upper_left = AddV2(at_new.upper_left,move);
at_new.lower_right = AddV2(at_new.lower_right,move);
}
}
@ -1114,7 +1160,7 @@ void frame(void)
{
if(player->speed <= 0.01f) player->speed = PLAYER_SPEED;
player->speed = Lerp(player->speed, dt * 3.0f, PLAYER_SPEED);
player->pos = move_and_slide(player->pos, MulV2F(movement, dt * pixels_per_meter * player->speed), V2(TILE_SIZE, TILE_SIZE));
player->pos = move_and_slide(player, player->pos, MulV2F(movement, dt * pixels_per_meter * player->speed));
if(player->is_rolling)
{
draw_animated_sprite(&knight_rolling, player->roll_progress, player->facing_left, character_sprite_pos, WHITE);

Loading…
Cancel
Save