Sign in to follow this  
Zmurf

Smooth movementy along walls.

Recommended Posts

Zmurf    100
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){
		sh = sin(j * DEGTORAD);
		ch = cos(j * DEGTORAD);

		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 this post


Link to post
Share on other sites
cowsarenotevil    3005
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 this post


Link to post
Share on other sites
jyk    2094
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 this post


Link to post
Share on other sites
Zmurf    100
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 this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this