Page 1 of 1

XNA Collision Gravity Problem

Posted: Thu Jan 22, 2009 12:56 am
by LeonBlade
Hey everyone,

I have currently a player model setup in a GameObject class which stores velocity, position, collision sphere, rotation, etc.

Now, I have gravity kick in by saying...

Code: Select all

player.VelocityY += 0.4f;
player.PositionY = player.VelocityY;
Something like that...

Now, the collision spheres meet...

Code: Select all

if (player.CollisionSphere.Intersects(groundCollision))
{
     player.VelocityY = 0.0f;
}
Basically stopping all Y velocity... but then when I move off of a surface like a sphere, it needs to translate over on X and or Z axis and translate on the Y axis towards the ground and it keeps doing this over and over which slows it down basically giving away the fact that I'm using a sphere...

Someone suggested to limit the velocity (which makes sense) so that I don't keep increasing speed slowing down player.
How would I go about doing this?

I'm pretty sure I got some form of working collision for regular stuff not based on gravity... here is some psuedo code for it, if you can find a better solution or know one (which is most likely true) then tell me what you got.

Code: Select all

if (player.Collision.Intersects(object.Colisision))
{
     if (player.PositionX <= object.PositionX)
     {
          player.PositionX -= 0.1f;
          player.VelocityX = 0.0f;
     }

     // repeat for greater than and Z for less and greater than
}
Something like that... I'm sure that is HORRIBLE way to check for collision but... lol... I'm assuming it at least is functional which is all I care about for right now, unless someone has a better solution...

Thanks,
LeonBlade

Re: XNA Collision Gravity Problem

Posted: Thu Jan 22, 2009 6:49 pm
by LeonBlade
Nobody?

Re: XNA Collision Gravity Problem

Posted: Thu Jan 22, 2009 6:51 pm
by M_D_K
First I have a question. Does XNA update the position based on velocity or do you have to do it yourself?

Re: XNA Collision Gravity Problem

Posted: Thu Jan 22, 2009 7:11 pm
by LeonBlade
It's my own class I have to update it but it's one line position += velocity

Re: XNA Collision Gravity Problem

Posted: Thu Jan 22, 2009 7:36 pm
by M_D_K
OK well gravity isn't directly velocity it affects it but you don't mess with it directly.

Code: Select all

//timems = Delta time
m_velocity.x += m_acceleration.x * timems;
m_velocity.y += m_acceleration.y * timems;
m_velocity.z += m_acceleration.z * timems;
			
m_position.x += m_velocity.x * timems;
m_position.y += m_velocity.y * timems;
m_position.z += m_velocity.z * timems;
That is code I use for my game objects and such. Gravity would be set in acceleration.y in OpenGL I use -9.81(in 3D space). I don't know if its the same in DirectX but still its a starting point.

So what you want to do is add another Vector to your class and use that to manipulate gravity. The result is that when that code updates every frame, objects that a going up will come down again.

Re: XNA Collision Gravity Problem

Posted: Thu Jan 22, 2009 8:37 pm
by LeonBlade
Alright, cool I'll check this out tomorrow.

Re: XNA Collision Gravity Problem

Posted: Fri Jan 23, 2009 11:45 am
by qpHalcy0n
For a very rudimentary collision case (sphere to plane) which is what you're doing I gather, the simplest case would be to calculate a resultant velocity from the collision.

You can evaluate the collision based on a poll of a collision query at time0 (now), and time1 (interpolated for the next frame). The collision becomes a simple dot product of the center of the spheroid to the collider's plane normal. If the collider is a curved surface, the tangent at the nearest point would suffice. This yields the
distance of the sphere to the plane. If the distance > 0, you are on the front-facing side of the plane (guaranteed if your polygons are wound correctly), and < 0 if you are on the backside of the plane. So then obviously if distance at time0 is > 0 and distance at time1 < 0, then an interpolated collision has occured. By accounting for the sphere's radius, you can fine tune the collision time. So that: if distance < radius then a collision has occured. Accounting for high object velocity is why two samples are necessary, because its conceivable that the object may be moving so fast that simply accounting for the sphere's radius at a single time sample may never evaluate.

Since you've determined that a collision has happened you now need to determine a result. Well, in simplest terms, the result is a new velocity vector which is simplified as a reflection of the incoming velocity (before the collision) about the plane's normal. The amount of "deadness" or "absorbance" can be reflected by scaling the resultant vector by a value ranging 0-1. Finding the reflection vector is some basic geometry:

r = result
i = incoming vector
n = plane normal

r = i - 2 * n * dot_product(i, n);

Then the object's new velocity becomes r. You can deaden the "bounciness" by scaling r from 0-1.

This will eliminate that kind of effect you're describing. This is also an extremely fast routine. However, the object's reaction to a planar collision will be VERY simple and obvious (like a bouncy ball bouncing around walls, even though the object it encapsulates may be a cube). It would not take into account complex objects colliding with other complex objects, which can get rather hairy.


In sum:
determine collision at time0
determine collision at time1
if((distance at time0 > 0 && distance at time1 < 0) || distance at time0 < radius)
{
collision has occured...evaluate resultant velocity vector
m_player.velocity = resultant velocity vector
}

m_player->update

Re: XNA Collision Gravity Problem

Posted: Fri Jan 23, 2009 2:54 pm
by MarauderIIC
Now that was useful.

Re: XNA Collision Gravity Problem

Posted: Fri Jan 23, 2009 3:54 pm
by LeonBlade
The BoundingBox and sphere both have an intersect method.
For some reason, I can't stop my player...

Re: XNA Collision Gravity Problem

Posted: Fri Jan 23, 2009 5:07 pm
by qpHalcy0n
Well then you need to be sure that they're behaving as they're expected to and you need to see what you get back. Either way, if then the collision has happened you may still need to go through the routine of obtaining a result velocity from the collision yourself.

Re: XNA Collision Gravity Problem

Posted: Fri Jan 23, 2009 5:31 pm
by LeonBlade
What I'm doing is basically poor but...

Code: Select all

if (player.CollisionSphere.Intersects(groundCollision))
{
     player.VelocityY = 0.0f;
}
else
{
     player.Velocity = -1.0f;
}
Just to see if it works, and sometimes the player doesn't move down at all (which could mean my bounding sphere is HUGE, but I doubt it) and other times it just moves down and under the ground plane...

I don't have the project with me, it's at school, so there isn't really much I can do until Monday and then I can continue whenever I want when I get my new computer.

Like I said before, the position is updated every game frame with

Code: Select all

player.Postition += player.Velocity;
Which works fine, except for the collision stuff... so I'm not sure why I'm getting these problems...
All collision tutorials/sample are height maps... bleh... gay... not what I want...