sliding on walls

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

Recommended Posts

hey there! as part of my collision detection i want to handle collision pretty much like many other games with sliding. now i'll show you a picture lets pretend our camera is looking at the character from above, the head is the character and the line is a wall. its pretty easy to slide in the left part of the image since the wall is stright, all i need to do is to say "once you colide with the wall, move only on the y axis" and it works fine. but its not dynamic, i dont want my game to be all squarish just because i am not smart enough to develop a formula to handle not so stright lines. now the best i could do is to understand that i need to do something with the player's movement direction and the wall's 'direction', too bad i am not sure what i should do and too bad i dont know how to find the direction of the wall. on what to do i thought about doing player's direction minus wall direction+90. so, am i in the right direction? is my theory close to what that is actually done to make sliding? and how do i find this wall direction? thanks in advance :) p.s, in the picture you can see a mysterious circle with numbers on it. just wanted to explain that these numbers are the directions(in degrees) and that i use it this way.

Share on other sites
Ok, I can't put up with this I had to sign up to answer this or else I couldn't live with myself, lol.

Well first of all your interpretation is skewed, you should never say "If collided with wall only move on Y axis" thats a cheap in-efficient mess. Your so called "sliding" is just normal collision detection. Collision detection isn't a whole bunch of statements checking for every little thing, that is complete overkill and just a much harder way. The way I would suggest is how most collision detection and response works.

You check for collisions every frame, when it detects the player has gone "through" the wall, then it moves/sends your character back to the nearest point/location before the collision. The whole sliding aspect is just normally what happens with collision detection, you don't need to program it in separately.

If your confused on how to do proper collision detection, look for Bounding Box/Sphere Collision (its fairly simple) check Google and search the gamedev forums, or better yet. Check out the gamedev articles theres plenty of information there that people just neglect.

Good Luck.

Share on other sites
use vectors, they are perfect for that sort of things.

here's a simple vector class

#include <gl/opengl.h>inline float sign(float x){	return (x < 0.0f)? -1.0f : 1.0f;}inline float frand(float x=1.0f){	return (rand() / (float) RAND_MAX) * x;}inline void swapf(float& a, float& b){	float c = a;	a = b;	b = c;}inline float pi(){    static const float g_pi = atan(1.0f) * 4.0f;	return g_pi;}class Vector{public:	float x,y;public:	inline Vector(void)	{}	inline Vector(float Ix,float Iy)	: x(Ix)	, y(Iy)	{}	inline Vector &operator /=(const float Scalar)	{ x /= Scalar; y /= Scalar;		return *this; }	inline Vector &operator *=(const float Scalar)	{ x *= Scalar; y *= Scalar;		return *this; }		inline Vector &operator +=(const Vector &Other) { x += Other.x;	y += Other.y;	return *this; }	inline Vector &operator -=(const Vector &Other) { x -= Other.x;	y -= Other.y;	return *this;	}	inline float operator ^ (const Vector &V)	const	{	return (x * V.y) - (y * V.x); } // cross product	inline float operator * (const Vector &V)	const	{	return (x*V.x) + (y*V.y); } // dot product	inline Vector operator * (float  s)			const	{	return Vector(x*s, y*s); }		inline Vector operator / (float  s)			const	{	return Vector(x/s, y/s); }		inline Vector operator + (const Vector &V)	const	{	return Vector(x+V.x, y+V.y); }			inline Vector operator - (const Vector &V)	const	{	return Vector(x-V.x, y-V.y); }	inline Vector operator -(void) const { return Vector(-x, -y); }		inline float length(void) const { return (float) sqrt(x*x + y*y); }	Vector perp() const { return Vector(-y, x); } // perpendicular vector	float dotProduct(const Vector& other) const { return (*this) * other; }		float crossProduct(const Vector& other) const { return (*this) ^ other; }	friend Vector operator * (float k, const Vector& V) {	return Vector(V.x*k, V.y*k); }		float normalise() { float l = length(); if( l > 1.0E-6f) (*this) /= l; return l; }	Vector normalised() const { Vector temp(*this); temp.normalise(); return temp; }		Vector& rotate(float angle)	{		float tx = x;		x =  x * cos(angle) - y * sin(angle);		y = tx * sin(angle) + y * cos(angle);		return *this;	}	Vector& transform(const Vector& trans, float rot)	{		Vector D = *this;		D.rotate(rot);		*this = trans + D;		return *this;	}	void randomise(const Vector& min, const Vector& max)	{		x = frand(max.x - min.x) + min.x;		y = frand(max.y - min.y) + min.y;	}};

and a collision algorithm between segments and spheres.

segment :
---------

struct Segment{	Segment()	{}	Segment(float worldSize)	{		Vector centre;		Vector dir;		centre.randomise(Vector(0, 0), Vector(worldSize, worldSize));		dir.randomise(Vector(-1000, -1000), Vector(1000, 1000));		dir.normalise();		float length = frand(worldSize / 10) + 20;		m_start = centre - dir * (length * 0.5f);		m_end = centre + dir * (length * 0.5f);	}	void render() const	{		glColor3f(1.0f, 1.0f, 1.0f);		glBegin(GL_LINES);		glVertex2f(m_start.x, m_start.y);		glVertex2f(m_end.x, m_end.y);		glEnd();	}	Vector closestPoint(const Vector& p) const	{		// the 'edge'		Vector e(m_end - m_start);		// the projection of the point on the infinite line passing through the segment		float t = (p - m_start).dotProduct(e) / e.dotProduct(e);		// clamp the projection to [0, 1] so it is on the segment		if(t < 0.0f) t = 0.0f;		if(t > 1.0f) t = 1.0f;		// return closest point		return m_start + e * t;	}	Vector m_start;	Vector m_end;};

character :
-----------

struct Character{	Character()	{}	Character(float worldSize) 	{		m_position.randomise(Vector(0, 0), Vector(worldSize, worldSize));		m_radius = worldSize / 50.0f;		m_velocity = Vector(0.0f, 0.0f);	}	void render() const	{		// render circle		glColor3f(1.0f, 1.0f, 1.0f);		glBegin(GL_LINE_LOOP);		float a = 0.0f;		float da = pi() / 16.0f;		for(int i = 0; i < 32; i ++, a += da)		{			Vector d(cos(a), sin(a));			Vector p = m_position + d * m_radius;			glVertex2f(p.x, p.y);		}		glEnd();	}	// reset velocity to a value (set by inputs).	// example : setVelocity((key - key) * 10.0f, (key[UP] - key[DOWN]) * 10.0f));	void setVelocity(const Vector& velocity)	{		m_velocity = velocity;	}	// move character	void integrate(float dt)	{		// integrate position with velocity, and a time period.		m_position += m_velocity * dt;	}	// check collisions against a list of edges	void checkCollisions(const Segment* segments, int segmentCount)	{		// iterate segments		for(int i = 0; i < segmentCount; i ++)		{			Vector pushVector; // vector neede for collision reponse						// colliding with the segment?			if(collide(segments, pushVector))			{				// apply a 'sliding' collision response				applyCollisionResponse(pushVector);			}		}	}	// test collision witha single edge	bool collide(const Segment& s, Vector& pushVector) const	{		// find closest point on the edge to the character position		Vector closest = s.closestPoint(m_position);				// relative position of closest point to character		Vector delta = (m_position - closest);		// check if the point on the edge inside the radius		float distance_squared = delta.dotProduct(delta);		// nope. closest point on edge not near the character.		// so any other point on edge also outside the character range. no collision.		if(distance_squared > m_radius * m_radius) 			return false;		// compute the vector needed to push the character 		// so that the closest point on the edge is at exactly		// the distance of the character radius.		float distance = sqrt(distance_squared);				pushVector = delta * (m_radius - distance) / distance;		// we have collision		return true;	}	void applyCollisionResponse(const Vector& pushVector)	{		// push the chracter away from the collision.		m_position += pushVector;		// compute the collision normal		Vector collisionNormal = pushVector.normalised();		// slide the velocity along the collision plane.		// basically, remove the part of the velocity vector that is along the plane normal		// so the velocity is then parallel to the collision plane, hence 'sliding'.		m_velocity -= collisionNormal * (m_velocity.dotProduct(collisionNormal));	}	Vector m_position;	// character position	Vector m_velocity;	// character velocity	float  m_radius;	// character radius};

[Edited by - oliii on January 22, 2009 1:20:30 PM]

Share on other sites
You basically want to find the normal to the wall's edge (ie a perpendicular line, 90 degrees from the angle of the wall) and push the player out along this normal until he's no longer inside the wall.

Share on other sites
Make sure you handle the fun corner cases.

Sliding along the wall can create some nasty situations, especially when additional actors are involved. You can get into situations when it is just best to bail out and keep objects where they were.

Share on other sites
There are a few articles in the physics section about friction and bouncing. Should help!

Share on other sites
http://www.peroxide.dk/papers/collision/collision.pdf

This should be a good start in the right direction (is that a pun?)

-=[ Megahertz ]=-

Share on other sites
Well when you throw a puck straight at a wall it Reflects the other way at the angle it was hit at, you also have to take mass of the Object, and speed into calculations, because if you through a block at a wall at 4 MPH, its obviously wont deflect accurately, what happens is when it is going slower and hits the wall its deflection ray is shortened, so say the block was thrown at 50 degree angle its not going to deflect and 50 degree it will prolly deflect into 1/3 of that, because it has more mass then speed. I am not a physicist, I am going to be learning some courses but, I hope that this helps any questions feel free to ask

1. 1
Rutin
46
2. 2
3. 3
4. 4
5. 5
JoeJ
19

• 11
• 14
• 9
• 10
• 12
• Forum Statistics

• Total Topics
633003
• Total Posts
3009830
• Who's Online (See full list)

There are no registered users currently online

×