Jump to content
  • Advertisement
Sign in to follow this  
Bru

sliding on walls

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

If you intended to correct an error in the post then please contact us.

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


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


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


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


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

Image Hosted by ImageShack.us

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


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


Link to post
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

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!