# Make an object slide around an obstacle

I have path areas set up in a game I'm making for canvas/html5 and have got it working to keep the player within these areas. I have a function isOut(boundary, x, y) that returns true if the point is outside the boundary. What I do is check only the new position x/y separately with the corresponding old position x/y. Then if each one is out I assign them the past value from the frame before. The old positions are kept in a variable from a closure I made.

like this:

opos = [x,y];//old position
npos = [x,y];//new position

if(isOut(bound, npos[0], opos[1])){
npos[0] = opos[0]; //assign it the old x position
}
if(isOut(bound, opos[0], npos[1])){
npos[1] = opos[1]; //assign it the old y position
}


It looks nice and works good at certain angles, but if your boundary has diagonal regions it results in jittery motion. What's happening is the y pos exits the area while x doesn't and continues pushing the player to the side, once it has moved the player to the side a bit the player can move forward and then the y exits again and the whole process repeats. Anyone know how I may be able to achieve a smoother slide? I have access to the player's velocity vector, the angle, and the speed(when used with the angle). I can move the play with either angle/speed or x/yvelocities as I've built in backups to translate one to the other if either have been altered manually.

• I think you need to start using vector math, and since I don't know how your objects move right now, I can't really advise you further. In general terms, you should figure out how deep you are into a wall, then apply a force to the object's velocity vector to move them away from the wall. – John McDonald Nov 10 '11 at 18:00
• Yes I do, I kinda lack in the mathematics area. I've made up for it in research, but it only goes so far. I never had money for college so I never got the mathematics education I needed. – Isaiah Nov 10 '11 at 18:23
• basically down to it the velocity vector is added every frame to the position. I use angle/speed by doing speedMath.cos(angle/180*Math.PI); and speedMath.sin(angle/180*Math.PI); for x/y. And work it backwards if someone modifies the velocity vector to find the new speed and find the new angle with my direction(v1,v2) function, from my last question, passing the current position and the current + the new velocity vector – Isaiah Nov 10 '11 at 18:29

assuming that path is created from a polyline, your isOut function can do more than just returning whether player is outside of the path or not. it's almost easy to determine which line your player passed when it moved outside, and then it's easy to calculate a vector perpendicular to crossed line and exact position where player went out of boundary. using these data you can create a new movement function which won't go out of path.

another way is the code I'm posting here, it's a code we once used to solve slide problem in a game and it worked well enough. hope you can convert this code:

NiPoint3 CTerrainController::GetSlideMovement(NiPoint3 &pOrigin, NiPoint3 &pDir)
{
const unsigned int SearchCount = 5;
float start, end;
float rang;
NiPoint3 rh, lh;

NiPoint3 right;
start = 0.0f;
end = -NI_PI / 2.0f;
rh = pOrigin;
rh.z -= CHARACTER_WAIST_HEIGHT;
for (unsigned int i = 0; i < SearchCount; i ++)
{
float ang = (start + end) / 2.0f;
NiMatrix3 rot;
rot.MakeZRotation(ang);
right = rot * pDir;
right *= (pDir * right) / right.SqrLength();
if (mPick.PickObjects(pOrigin + right, -NiPoint3::UNIT_Z) && mPick.GetResults().GetAt(0)->GetAVObject()->GetName() != "collision_no walk")
{
end = ang;
rh = mPick.GetResults().GetAt(0)->GetIntersection();
}
else
start = ang;
}
rang = -end;

NiPoint3 left;
start = 0.0f;
end = NI_PI / 2.0f;
lh = pOrigin;
lh.z -= CHARACTER_WAIST_HEIGHT;
for (unsigned int i = 0; i < SearchCount; i ++)
{
float ang = (start + end) / 2.0f;
NiMatrix3 rot;
rot.MakeZRotation(ang);
left = rot * pDir;
left *= (pDir * left) / left.SqrLength();
if (mPick.PickObjects(pOrigin + left, -NiPoint3::UNIT_Z) && mPick.GetResults().GetAt(0)->GetAVObject()->GetName() != "collision_no walk")
{
end = ang;
lh = mPick.GetResults().GetAt(0)->GetIntersection();
}
else
start = ang;
}

if (rang < end)
return rh;
return lh;
}


some notes:

this function gets player origin and velocity as input and then returns velocity after applying slide effect. it's trying to find some free space in front of player and tells player to move in that specific direction. if statement which checks for picked objects is almost equivalent of if(!isOut(pOrigin + right))