4 Replies - 3450 Views - Last Post: 23 February 2013 - 04:53 AM

#1 LiberLogic969  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 34
  • View blog
  • Posts: 85
  • Joined: 03-September 12

Line vs Circle Collision Response

Posted 21 February 2013 - 11:02 PM

Hello forums,

Iím working on a 2d top-down game and I am having some issues with collision response. In the game I plan on using line segments to define walls that entities collide with. The entities collision shapes are circles (position and radius). I have a working demo set up that lets me collide a sphere into a line segment and stop the entities movement by setting its current position to its previous position when a collision is detected.

Now the issue is when an entity is against a wall it will begin to rapidly tremble depending on how fast it can accelerate. I cant seem to figure out how to make it smooth. Also, when I try to move the entity along the wall it will bounce and lag. Anyone have any ideas?

Here is the Entity class Update method :

public void Update(GameTime gameTime, List<LineSegment> walls)
        {
            float elapsedTime = (float)gameTime.ElapsedGameTime.TotalSeconds;

            if (!InputManager.IsThumbstickIdle(TriggerType.Left))
            {
                direction = InputManager.ThumbstickVector(TriggerType.Left);
                angle = InputManager.ThumbstickAngle(TriggerType.Left);
                velocity = (direction * _speed);
                
                for (int i = 0; i < walls.Count; i++)
                {
                    LineSegment line = walls[i];
                    
                    if (CollisionSolver.CirlceIntersectsLine(circle, line))
                    {
                        position = previousPosition + (line.Normal * Vector2.One);
                        circle.Position = position;
                    }
                }
            }
            else
            {
                velocity = Vector2.Multiply(velocity, _damping);
            }

            previousPosition = position;
            position += velocity * elapsedTime;
            circle.Position = position;
        }



If more of the code is needed just let me know and I will post it. Thanks in advance for any help!

Is This A Good Question/Topic? 0
  • +

Replies To: Line vs Circle Collision Response

#2 lordofduct  Icon User is offline

  • I'm a cheeseburger
  • member icon


Reputation: 2538
  • View blog
  • Posts: 4,641
  • Joined: 24-September 10

Re: Line vs Circle Collision Response

Posted 22 February 2013 - 08:37 AM

the trembling is because you're moving in and back out of the wall over and over... and there's slight imperfections in the number inherently (it's one of the downsides to floating point values), combined with accelerative forces, you got a situation all physics engines have to deal with.

First things first, when colliding with a wall you need to reset the velocity. In simple engines it means setting the velocity to zero, in more complicated simulations with mass and elasticity you may 'bounce' the velocity off the surface (usually this bounce will have a low side cut-off... so if the bounce velocity is to low, or if the bounce velocity continues heading into the wall it gets set to zero).

This could also be caused by gravity too, because you'll land on a surface which will constantly have gravity pulling it down. Some engines will put the entity into an 'at-rest' state when this happens. The object then temporarily gets ignored by the simulation process, no gravity effecting it and it doesn't get its position updated at all (not even calculated, as opposed to just adding a 0 velocity over and over). Then when it gets touched by another dynamic entity, it gets taken out of the 'at-rest' state and dynamic calculations start up again until it comes to rest yet again.
Was This Post Helpful? 1
  • +
  • -

#3 LiberLogic969  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 34
  • View blog
  • Posts: 85
  • Joined: 03-September 12

Re: Line vs Circle Collision Response

Posted 22 February 2013 - 01:47 PM

Thanks for the reply lordofduct.

When I set the entity velocity to Vector2.Zero when a collision occurs it will not be able to move again. I guess this is because its velocity is reduced to zero every frame. When I push the sphere out of the collision by 1 pixel it starts the jittering again. I cant seem to figure out what else to do about this >.</>. This specific game doesnít need any kind of complex physics, just a way to get the collisions to smooth out a bit. Im gonna give a few of my bad ideas a try again lol.
Was This Post Helpful? 0
  • +
  • -

#4 LiberLogic969  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 34
  • View blog
  • Posts: 85
  • Joined: 03-September 12

Re: Line vs Circle Collision Response

Posted 22 February 2013 - 04:09 PM

I've managed to get rid of the jitter. My second issue is that I would like the player to be able to move along the line segment even when there is a collision. What happens now is the player will not move unless the velocity is aligned with the surface normal of the segment. I want it to be "slippery".

Here are the changes that get rid of the jitter.

float elapsedTime = (float)gameTime.ElapsedGameTime.TotalSeconds;
            previousPosition = position;

            if (!InputManager.IsThumbstickIdle(TriggerType.Left))
            {
                direction = InputManager.ThumbstickVector(TriggerType.Left);
                angle = InputManager.ThumbstickAngle(TriggerType.Left);

                velocity = (direction * _speed);
                position += velocity * elapsedTime;
                circle.Position = position;
            }
            else
            {
                velocity = Vector2.Multiply(velocity, _damping);
            }

            for (int i = 0; i < walls.Count; i++)
            {
                LineSegment line = walls[i];

                if (CollisionSolverTwo.CirlceIntersectsLine(circle, line))
                {
                    position = previousPosition;
                    circle.Position = position;
                }
            }



Sorry for double posting. Its not giving me the option to edit my posts :(
Was This Post Helpful? 0
  • +
  • -

#5 LiberLogic969  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 34
  • View blog
  • Posts: 85
  • Joined: 03-September 12

Re: Line vs Circle Collision Response

Posted 23 February 2013 - 04:53 AM

Again, sorry for my flood of posts, it wont let me edit!

My issues have been solved :) I needed to find the intersection depth of the collisions to get the effect I was aiming for. Someone very helpful pointed me to this : http://doswa.com/200...ncollision.html

Incase anyone wants a (sloppy) C# port, here it is :

public static class Collisionhelper
    {
        static Collisionhelper()
        { }

        private static void ClosestPointFromCircle(Circle circle, LineSegment line, out Vector2 closest)
        {
            closest = Vector2.Zero;
            Vector2 segmentVector = line.End - line.Start;
            Vector2 circleRelative = circle.Position - line.Start;

            if (segmentVector.Length() <= 0)
                throw new ApplicationException("Length of line segment must be greater than 0");

            Vector2 segmentUnit;
            Vector2.Normalize(ref segmentVector, out segmentUnit);

            float projection = Vector2.Dot(circleRelative, segmentUnit);
            if (projection <= 0)
            {
                closest = line.Start;
                return;
            }
            if (projection >= segmentVector.Length())
            {
                closest = line.End;
                return;
            }

            Vector2 projectionVector = segmentUnit * projection;
            closest = projectionVector + line.Start;
        }
        public static void SolveCircleSegmentCollision(Circle circle, LineSegment line, out Vector2 depth)
        {
            depth = Vector2.Zero;

            Vector2 closest;
            ClosestPointFromCircle(circle, line, out closest);

            Vector2 distanceVector = circle.Position - closest;
            if (distanceVector.Length() > circle.Radius)
            {
                return;
            }
            if (distanceVector.Length() <= 0)
            {
                throw new ApplicationException("Circle center is exactly on line segment");
            }

            Vector2 unitDist;
            Vector2.Normalize(ref distanceVector, out unitDist);
            depth = unitDist * (circle.Radius - distanceVector.Length());
        }
    }


Was This Post Helpful? 0
  • +
  • -

Page 1 of 1