# Smooth movementy along walls.

This topic is 4419 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I'm using the following code to stop my character in an FPS from going through walls.
void CPlayer::Collision(){
double sh, ch, X, Z, x, y, z;

for(double j = 0; j < 360; ++j){

X = m_X + 4.0 * ch;
Z = m_Z + 4.0 * -sh;

for(int i = 0; i < m_Walls->Count(); ++i){
m_Walls->GetXYZ(i, x, y, z);
if ((X > x && X < x + 16.0)
&& (Z > z - 16.0 && Z < z)){
sh = sin((m_DirH + 180) * DEGTORAD);
ch = cos((m_DirH + 180) * DEGTORAD);

m_X -= m_Speed * -ch;
m_Z -= m_Speed * sh;

sh = sin((m_DirH - 90) * DEGTORAD);
ch = cos((m_DirH - 90) * DEGTORAD);

m_X -= m_Strafe * -ch;
m_Z -= m_Strafe * sh;

}
}
}
}
}

It works by first updating the x,z of the character, then, if he's collided with a wall, they move the x,z back and re-render. This works resonably well except that, once the character hits the wall he just stops. I want him to slide along the wall if hes facing diagonally at the wall. IE: | /| | | || | | O | It's kinda hard to visualise but maybe you can understand what i'm trying to achieve, does anyone know how to do this? I don't want to totally recode my collision system though unless it's totally necessary.

##### Share on other sites
First, don't move back and re-render, test first if you're going to hit a wall, and don't render to begin with if you are.

As for your problem, if updating z would put the character through a wall, you can still test and possible update y and vice versa.

##### Share on other sites
From your code it looks like your player is a circle and your walls are square tiles. Here's some code based on that assumption that you might try - you can just comment yours out and drop this in, and see if it works (no guarantees):

void CPlayer::Collision(){    double radius = 4.0;    for(int i = 0; i < m_Walls->Count(); ++i){        m_Walls->GetXYZ(i, x, y, z);        double minx = x;        double maxx = minx + 16.0;        double maxz = z;        double minz = maxz - 16.0;                double cx = m_X;        if (cx < minx) {            cx = minx;        } else if (cx > maxx) {            cx = maxx;        }        double cz = m_Z;        if (cz < minz) {            cz = minz;        } else if (cz > maxz) {            cz = maxz;        }                // The following assumes that although the player circle may be intersecting        // the wall, the player center is outside the wall. This is a reasonable        // assumption if the player velocity is not too great.        double dx = m_X-cx;        double dz = m_Z-cz;        double length = sqrt(dx*dx+dz*dz);        if (length < radius) {            dx /= length;            dz /= length;            double dist = radius - length + 0.01;            m_X += dx * dist;            m_Z += dz * dist;        }    }}

##### Share on other sites
thanks thats perfect, i will try and make it so it checks if it will hit the wall, and then move it the position is empty

##### Share on other sites

This topic is 4419 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.