# How can I handle transferring a character from one collision surface to another?

I've been trying to modify some slope code from an example I've found but I've come across an issue the way the method is designed it attaches the current slope and then based off that slope determines if the character is on it or not.

 protected CollisionPath attachedPath;


The issue with this though is when you try and lay down several slopes to make one continuous slope it doesn't work properly as this piece of code kicks in and makes you fall off the current slope you are standing on.

if (position.X < attachedPath.MinimumX || position.X > attachedPath.MaximumX)
{
attachedPath = null;
}


While this isn't the case when you jump from one slope to another. I've tried to adapt the code used for jumping to one slope to another to solve the issue to no avail. The method in its entirety is below. any help with this would be really appreciated.

private void HandleSlopeCollisions( GameTime gameTime)
{
collisionPaths = level.collisionPaths;
float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;

if (velocity.Y >= 0)
{
if (attachedPath != null)
{
isOnGround = true;

position.Y = attachedPath.InterpolateY(position.X);
velocity.Y = 0;

if (position.X < attachedPath.MinimumX || position.X > attachedPath.MaximumX)
{
attachedPath = null;
}
}
else
{
Vector2 footPosition = position;
Vector2 expectedFootPosition = footPosition + velocity * elapsed;

CollisionPath landablePath = null;
float landablePosition = float.MaxValue;

foreach (CollisionPath path in collisionPaths)
{
if (expectedFootPosition.X >= path.MinimumX && expectedFootPosition.X <= path.MaximumX)
{
float pathOldY = path.InterpolateY(footPosition.X);
float pathNewY = path.InterpolateY(expectedFootPosition.X);

if (footPosition.Y <= pathOldY && expectedFootPosition.Y >= pathNewY && pathNewY < landablePosition)
{
landablePath = path;
landablePosition = pathNewY;
}
}
}

if (landablePath != null)
{
velocity.Y = 0;
footPosition.Y = landablePosition;
attachedPath = landablePath;

position.Y = footPosition.Y;
}
}
}
else
{
attachedPath = null;
}
}


Are your slopes perfectly in line such that one starts exactly after the other slope? If so, try overlapping them. Overlapping collision surfaces is a very common technique to avoid problems such as yours.

EDIT: You must change your logic a little bit with the above. In the above case, two surfaces will report collisions at some point. Simply add all the surfaces to an array (or stack) and when the array/stack reaches 0, the character should fall.

EDIT2: Something like this: (Note the name of the variables... the code is NOT going to work right off the bat, you will have to declare variables/containers etc.)

private void HandleSlopeCollisions( GameTime gameTime)
{
collisionPaths = level.collisionPaths;
float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;

if (velocity.Y >= 0)
{
if (attachedPathArray.size() > 0)
{
isOnGround = true;

for (unsigned int i = 0; i < attachedPathArray.size(); i++) // convert to foreach
{
position.Y = attachedPathArray[i].InterpolateY(position.X);
velocity.Y = 0;

if (position.X < attachedPathArray[i].MinimumX || position.X > attachedPathArray[i].MaximumX)
{
attachedPathArray.remove(i);
--i; // otherwise we would skip a path because the size just decreased
}
}
}
else
{
Vector2 footPosition = position;
Vector2 expectedFootPosition = footPosition + velocity * elapsed;

CollisionPath landablePath = null;
float landablePosition = float.MaxValue;

foreach (CollisionPath path in collisionPaths)
{
if (expectedFootPosition.X >= path.MinimumX && expectedFootPosition.X <= path.MaximumX)
{
float pathOldY = path.InterpolateY(footPosition.X);
float pathNewY = path.InterpolateY(expectedFootPosition.X);

if (footPosition.Y <= pathOldY && expectedFootPosition.Y >= pathNewY && pathNewY < landablePosition)
{
landablePosition = pathNewY;
}
}
}

if (landablePathArray.size() > 0)
{
velocity.Y = 0;
footPosition.Y = landablePosition;
attachedPath = landablePathArray[?]; // which one would you select in the array? up to you, I can't tell from your code

position.Y = footPosition.Y;
}
}
}
else
{
attachedPath = null;
}
}

• Tried doing that, didn't work unfortunately Oct 14, 2011 at 17:59
• See my additional edit Oct 14, 2011 at 18:21
• Kind of unclear about how you would do the check on the array, do you mind elaborating ? Oct 14, 2011 at 19:08
• See my additional Edit2 Oct 15, 2011 at 3:03
• I've tried that method but due to how the code is structured the entire path disappears the moment it runs. I think I found an alternative solution though Oct 15, 2011 at 10:55