Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411595 Posts in 69387 Topics- by 58445 Members - Latest Member: gravitygat

May 08, 2024, 06:52:30 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)Problems With Circle-AABB Collision/Resolution Algorithm
Pages: [1]
Print
Author Topic: Problems With Circle-AABB Collision/Resolution Algorithm  (Read 527 times)
kabbotta
Level 0
**


View Profile WWW
« on: January 29, 2016, 05:22:27 PM »

I have very simple collision requirements. I need circles to collide with circles and circles to collide with 1x1 tiles. I have written up a method to try and handle the circle-tile collisions and it isn't quite working. Any help would be appreciated.

First, I scan for collisions depending on which way the entity is moving.
Code:
void PhysicsSystem::scan_collisions(DynamicEntity& entity)
{
  int px, py;

  px = (int)std::floor(entity.pos.x());
  py = (int)std::floor(entity.pos.y());

  if (entity.vel.x() > 0)
  {
    for (auto y = py - 1; y <= py + 1; ++y)
    {
      if ((px + 1) < 0 || (px + 1) >= MAP_SIZE_X || y < 0 || y >= MAP_SIZE_Y)
continue;

      if (map_system.get_tile((px + 1), y, entity.floor).solid)
resolve_collision(entity, (px + 1), y);
    }
  }
  else if (entity.vel.x() < 0)
  {
    for (auto y = py - 1; y <= py + 1; ++y)
    {
      if ((px - 1) < 0 || (px - 1) >= MAP_SIZE_X || y < 0 || y >= MAP_SIZE_Y)
continue;

      if (map_system.get_tile((px - 1), y, entity.floor).solid)
resolve_collision(entity, (px - 1), y);
    }
  }

  ... [same for y-direction]
}

And here is the resolution method:

Code:
void PhysicsSystem::resolve_collision(DynamicEntity& entity, int x, int y)
{
  Vector2f tile_pos(x, y);
  Vector2f nearest(entity.pos);
  Vector2f min(x, y), max(x + 1, y + 1);

  if (nearest.x() < min.x()) nearest.x() = min.x();
  else if (nearest.x() > max.x()) nearest.x() = max.x();

  if (nearest.y() < min.y()) nearest.y() = min.y();
  else if (nearest.y() > max.y()) nearest.y() = max.y();

  Vector2f ray(entity.pos - nearest);
  auto length = ray.norm();
  auto depth = entity.size - length;

  if (length != 0 && depth > 0)
  {
    ray.normalize();
    entity.pos += depth * ray;
  }
}

But this collides too soon when the player is walking to the left or walking up and hits a tile.
« Last Edit: January 29, 2016, 05:35:05 PM by kabbotta » Logged

You owe it to yourself to know it to yourself - Dejuan Rice
Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic