Player Physics

Nov 12, 2009 at 9:52 PM
Edited Nov 13, 2009 at 5:04 AM

So I'm giving Oops! a try for my project, and I'm having a bit of trouble figuring out to set up the player.

So the first problem is that when I apply force for movement, the object slides/rolls instead of stopping when I release the button. I could directly affect the velocity, but this interferes with jumping. I also tried using a high friction and angular dampening, but that means I need to apply a lot more force to move the object on the ground, and then you  go really fast through the air. I could also repeatedly update the position of the body, but I feel like this could cause other problems.

This is what I would like to do:
a) Player walks around with wasd, and does not slide when they release the button.
b) Player can jump when on the ground (apply upward force, not sure yet how to detect that player is currently on the ground)
c) Player has reduced movement control while in the air (easy enough after figuring out how to detect that the player is currently on the ground)
d) Player collision shape will most likely be a sphere
e) Player can push objects around, but they cannot push the player (perhaps give the player a large mass compared to other objects)
f) Player can pickup objects and move them around (shouldn't be too hard with contraints?)

So the major issues I currently see are:
1) How do I get the player to not slide when they stop moving?
2) How do I detect whether the player is standing on an object so they can jump?

Does anyone have any ideas on how to do this?
Thank you.

[NOTE]

I originally posted this here: http://forums.xna.com/forums/t/42382.aspx, but it was suggested that I post it here.

Pfo Cubed replied:

i) What I've typically seen engines do for player controllers is that when they are not moving, the friction between the character and the ground surfaces is greatly increased to prevent movement.  The friction forces will calculate the correct velocities to stop your character from sliding, while still allowing it to jump normally.

ii) I imagine Oops has some ability to detect collisions, when a collision happens between the player and the ground, keep track of it to know when the player last collided with the ground.

The first sounds good to me. But a problem I see with the second one is that there is not just one 'ground' object - there is the main world, but there are also blocks that the player should be able to jump off of.

Any thoughts?
Thanks again.

Coordinator
Nov 13, 2009 at 5:49 PM

Hey azurfire, I actually working in the same area for my game - player controls.

What i've determined to work well is to try and create a velocity matching constraint, matching the RigidBody.Velocity to the vector/direction that you want the player to go in.  For example:

Say you press the thumbstick to the right on the game pad.  The direction you want the player to move could be represended with a Vector3 (1.0f, 0.0f, 0.0f).  Multiply this direction by the players maximum speed will give you a target velocity:

Vector3 targetVelocity = controllerDirection * maxSpeed;

This vector is what you want the RigidBody.Velocity to match...BUT don't just set the target velocity to it :

DON'T DO : RigidBody.Velocity = targetVelocity.

This modifies the velocity instantaneously, and clears out any current velocity.  What you want to try to do is change the RigidBody.Velocity to the targetVelocity over a bit of time.  You can make this as complicated as you want but an easy approach is to get the change between the targetVelocity and RigidBody.Velocity and apply the time scale (and elapsed time) to create a value to modify the RigidBody.Velocity with:

Vector3 change = targetVelocity - RigidBody.Velocity.

RigidBody.Velocity += targetVelocity * timeScale * elapsed;

What's cool is that if controllerDirection is zero, the player slows down to a stop.  Friction can remain static, just set it to a value that is enough to make the player not slide when stopped.  To keep the player standing, just set the RigidBody.InertiaTensor to a Matrix with all zeroes and use a different Matrix orientation variable for drawing (and facing, potentially).  This orientation variable can be updated by the RigidBody.Velocity (make sure to take into account no velocity):

this.orientation = Matrix.CreateWorld(Vector3.Zero, Vector3.Normalize(RigidBody.Velocity), Vector3.Up);

If you have any questions, let me know.  There are some steps missing here but it should get you started in the direction I took.  Good luck!

Nov 28, 2009 at 6:47 PM

Hi,
I was also doing this part of the game  and noticed that where you wrote:

RigidBody.Velocity += targetVelocity * timeScale * elapsed;

You probably meant:
RigidBody.Velocity += change * timeScale * elapsed;

I'm also using something like this for player movement.

Cheers

Coordinator
Nov 28, 2009 at 10:25 PM

That is exactly what I meant.  Thanks for the correction.