View more

View more

View more

### Image of the Day Submit

IOTD | Top Screenshots

### The latest, straight to your Inbox.

Subscribe to GameDev.net Direct to receive the latest updates and exclusive content.

# 2D Multiple Collision Response SAT

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

6 replies to this topic

### #1mwkenna  Members

Posted 25 October 2013 - 03:45 AM

Hi All

I'm learning GameDev by developing a tile-based game.

I've implemented swept SAT using the great PolyColly tutorials. My "future-collision" response code is working very well but the "current-collision" response code is having trouble when resolving multiple collisions (like on an inside edge). Note that I am disregarding edges that are marked as "empty" as suggested by the great MetaNet tutorials.

I've included 2 screenshots of the problem.

I can provide code on request.

I would really like to understand what is happening here.

Thanks,

Mark.

### #2serumas  Members

Posted 25 October 2013 - 07:48 AM

There is nothing to say without the code you resolve overlaping.

### #3mwkenna  Members

Posted 25 October 2013 - 07:54 AM

Here is the collision code that I am using. Note that I am currently trying to understand it so I'm not worried about that fact that it's not very efficient yet. Also note that it's the current collisions which are not working correctly.

Thanks,

Mark.

protected override void Update(GameTime gameTime)
{
// Allows the game to exit
this.Exit();

//player position update
float amount = 50;
Vector2 offset = Vector2.Zero;
KeyboardState state = Keyboard.GetState();
if (state.IsKeyDown(Keys.Up))
offset += new Vector2(0, -amount);
if (state.IsKeyDown(Keys.Down))
offset += new Vector2(0, amount);
if (state.IsKeyDown(Keys.Left))
offset += new Vector2(-amount, 0);
if (state.IsKeyDown(Keys.Right))
offset += new Vector2(amount, 0);
redPoly.Position += offset;

//player velocity update
Vector2 displacement = new Vector2(0, 0);
MouseState mouseState = Mouse.GetState();
Vector2 mousePos = Vector2.Zero;

if (mouseState.LeftButton == ButtonState.Pressed)
{
mousePos = new Vector2(mouseState.X - (boxWidth / 2), mouseState.Y - (boxHeight / 2));
redPoly.Displacement = mousePos - redPoly.Position;
}

//get the list of collisions
List<CollisionResult> collisions = new List<CollisionResult>();
foreach (Polygon p in polygons)
{
var collision = Collide(redPoly, p, redPoly.Position - p.Position, redPoly.Displacement - p.Displacement);
if (collision != null)
{
}
}

var futureTimes = (from a in collisions where a.CollisionType == CollisionResultType.Future select a.T).ToList();
if (futureTimes.Count > 0)
{
futureTimes.Sort();
collPos = redPoly.Position + redPoly.Displacement * futureTimes.First();
}
else
{
if (mouseState.LeftButton == ButtonState.Pressed)
collPos = mousePos;
}

Vector2 mtd = Vector2.Zero;
var currentCollisions = (from a in collisions where a.CollisionType == CollisionResultType.Current select a).ToList();
if (currentCollisions.Count > 0)
{
collPos = Vector2.Zero;

//find the largest  MTD required to push the player out
foreach (var currentCol in currentCollisions)
{
Vector2 a = currentCol.CollisionNormal * currentCol.T;

if (Math.Abs(a.X) > Math.Abs(mtd.X))
mtd.X = a.X;
if (Math.Abs(a.Y) > Math.Abs(mtd.Y))
mtd.Y = a.Y;
}
}

if (mtd != Vector2.Zero)
redPoly.Position -= mtd;

base.Update(gameTime);
}


### #4serumas  Members

Posted 26 October 2013 - 01:08 AM

As I undertood from code you are doing: first find max overlaping and then resolving it.

Try not searching max overlapping, but resolve collision for each overlaping occure and do it not wit mtd but with redPoly.position:

foreach(bluePoly)

{

if(collides(redPoly,cur_bluePoly))

{

a = ...;

redPoly.Position -=a;

}

}

### #5mwkenna  Members

Posted 26 October 2013 - 03:31 AM

I am trying to accomplish the "Basic Arcade Collision Response" from the PolyColly tutorial, but without the physics. All I want is for it to be basic but correct). This is what I have modified the code to but I'm not getting the functionality that I would expect, the player is sticking to the polygons and sometimes penetrating the surface.

Again.. trying to keep it simple just using the arrow keys to modify the offset of the player (redPoly).

protected override void Update(GameTime gameTime)
{
// Allows the game to exit
this.Exit();

//player position update
float amount = 40;
Vector2 offset = Vector2.Zero;
KeyboardState state = Keyboard.GetState();
if (state.IsKeyDown(Keys.Up))
offset += new Vector2(0, -amount);
if (state.IsKeyDown(Keys.Down))
offset += new Vector2(0, amount);
if (state.IsKeyDown(Keys.Left))
offset += new Vector2(-amount, 0);
if (state.IsKeyDown(Keys.Right))
offset += new Vector2(amount, 0);

//get the list of collisions
List<CollisionResult> collisions = new List<CollisionResult>();
foreach (Polygon p in polygons)
{
float t = 1.0f;
Vector2 N = Vector2.Zero;

Vector2 relPos = redPoly.Position - p.Position;
Vector2 relDisplacement = offset;

if (Collide(redPoly, p, relPos, relDisplacement, ref N, ref t))
{
if (t < 0)
{
ProcessOverlap(ref redPoly, N, t);
}
else
{
ProcessCollision(ref redPoly, N, t, ref offset);
}
}
}

redPoly.Position += offset;

base.Update(gameTime);
}


Does this look correct to you guys?

Thanks,

Mark.

### #6mwkenna  Members

Posted 27 October 2013 - 04:12 AM

After debugging the code further I believe the problem is now a case of how to deal with "touching" collisions.

What's happening is that when I detect a future collision and update the players position to "hug" the colliding object, the collision code is continuously detecting the "touching state" and not applying the position offset.

I have attached my code:

protected override void Update(GameTime gameTime)
{
// Allows the game to exit
this.Exit();

//player position update
float amount = 10;
Vector2 offset = Vector2.Zero;
KeyboardState state = Keyboard.GetState();
if (state.IsKeyDown(Keys.Up))
offset += new Vector2(0, -amount);
if (state.IsKeyDown(Keys.Down))
offset += new Vector2(0, amount);
if (state.IsKeyDown(Keys.Left))
offset += new Vector2(-amount, 0);
if (state.IsKeyDown(Keys.Right))
offset += new Vector2(amount, 0);

foreach (Polygon p in polygons)
{
float t = 1.0f;
Vector2 N = Vector2.Zero;

Vector2 relPos = redPoly.Position - p.Position;
Vector2 relDisplacement = offset;

if (Collide(redPoly, p, relPos, relDisplacement, ref N, ref t))
{
if (t < 0)
{
//process teh current overlap
redPoly.Position -= N * t;
offset = Vector2.Zero;
}
else
{
if (t == 0)
{
//the objects are just touching
}
else
{
//process an overlap forward in time
redPoly.Position += offset * t;
offset = Vector2.Zero;
}
}
}
}

redPoly.Position += offset;

base.Update(gameTime);
}


### #7serumas  Members

Posted 28 October 2013 - 12:00 PM

I dont understand why you need these multiple t checks offset, p reldisplacement....

if there are only quads just check how much red object overlaps the one blue you are checking at the moment and push back red object that overlaping to be gone...

these weird calculations is useless, you dont need process forward in time.

If you still cant make it write to PM...

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.