Recommended Utility of Farseer?

Topics: User Forum
Feb 8, 2007 at 3:12 AM
I'm using Farseer for some general gravity functions in a 2d side scroller, and I'm wondering if it's possible to move a physics body in a smooth arc vertically. Initially I was using:

position.Y - (sin(pi/2)(jumptimeElapsed/maxAirtime)) jumpheight

and then allowing farseer's gravity take over, which resulted in a really stilted animation. Is there a way to exert a vertical force on an object that launches it? I tried using physicsbody.force and .applyforce, neither of which seem to be what I'm looking for. Would you recommend tweaking the position manually from liftoff to landing, or is there an easy way to do it with Farseer?
Feb 8, 2007 at 11:54 AM
With a physics engine, you never really want to adjust position outside of setting up the initial positoin. The physics engine is designed to handle all movement.

You should be able to just apply a force in the direction you want to jump using YourRigidBody.ApplyForce(new Vector2(10,-10)) (the 10's are arbitrary) this will apply a force to the left and up at 45 degrees.

If you can elaborate on what problem you are having with ApplyForce, I might be able to help.
Feb 8, 2007 at 7:50 PM
It doesn't seem to do anything. I've got a non-static RectangleRigidBody(x, y, 100), a PhysicsSimulator(0, 300). Both are set to update during the game loop, and there is a graphic image attached to the position of the RigidBody (of course). I've got an update loop in my Player class (which extends Sprite, which has just a graphic and a rigidbody) that checks to see if the left, right, or space are pressed. Left and right update the position of the rigidbody by in/decrementing the x values. Based on your comments, I'll try next to remove that, but it shouldn't be directly affecting the jump function.

Here's what I've got in player.Update():
if (elapsedAirTime < maxAirTime){
this.physicsBody.ApplyForce(new Vector2(10,-10));
this.airTime += gameTime.ElapsedGameTime.Milliseconds;

I know the gravity works fine, because if I initialize the player's position high above a static rigidbody "floor" he'll fall and land on it/walk off the edges and fall. The only other code I've applied to the rigidbody is that when the player stops pressing left or right:

this.physicsBody.LinearVelocity = new Vector2(0f, this.physicsBody.LinearVelocity.Y);

I had to add this because the player acted really floaty around corners (and could climb the corner, which sometimes puts them slightly inside the floor's rigidbody) instead of falling off right away. I still have that problem, but without this code the player would enter a permanent slow slide back towards the corner they "climbed".
Feb 8, 2007 at 8:43 PM
"It doesn't seem to do anything. I've got a non-static RectangleRigidBody(x, y, 100), a PhysicsSimulator(0, 300). Both are set to update during the game loop"

I have questions about this statement. What do you mean you are "Updating Both". You should be updating the PhysicsSimulator once per loop, but the RigidBody should simply be added to the simulator and that's it. You should not be calling update on it.

Also, you might try playing with your "mass" value. You are using 100, it may be that a force of (10,-10) just isn't strong enough to lift the object. So, try decreasing mass or increasing force. Hmmm, just noticed you gravity value is huge too. 300 is pretty high. A force of (10,-10) is never going to overcome a foce of (0,300). Imagine trying to jump on a planet where you weigh 100 and the gravity is 300 and you legs can only exert a force of 10. :-)

As for this: "this.physicsBody.LinearVelocity = new Vector2(0f, this.physicsBody.LinearVelocity.Y);"

Instead of this, you should control you character by increasing the FrictionCoeficent on both your character and the ground. This will make the difference between pushing you character accross an ice like surface vs. a less slippery surface. You should be able to use the FrictionCoeficent adjust how quickly your player comes to rest once you release the move buttons. You may have to play with the amount of force you apply to move the character once you start adjusting friction. Its a matter of finding the right combination of foce and friction.

Just to reiterate, once the simulator is started you should rarely have a need to modify the position or velocity of an object. When you do, the physics simulation becomes discontinuous and that defeats the whole purpose of the engine.

Hope this helps.
Feb 8, 2007 at 9:32 PM
The Update for the sprite class which has a rigidbody just makes sure the graphic is directly on top of the rigidbody. I guess that's extraneous data. The physics engine is being sent .update(.016).

I changed the mass to 10 and gravity to 30, and applied a force of (0, -50) when spacebar is pressed. I commented out any lines in the player class relating to the physicsbody (including lateral movement by altering physicsbody.position). The rigidbody still doesn't move vertically. Predictably, it does make it fall a lot more slowly, but that's about it. I'll try to create a stripped down version of my code that's just a simulation so I can isolate the problem.
Feb 8, 2007 at 9:42 PM
Okay, I got it! I just needed to apply a LOT more force. With a mass of 10 and gravity of 30, I applied -10, -50, -500, and then at -5000 it shot off the screen. Now it's just a matter of tweaking numbers. Thanks for your help! I'm sure you'll see more of me around as I make progress.
Feb 9, 2007 at 11:59 AM
Hmm, seems like you shouldn't need that much force. The "gravity" that gets appied is really just doing an "ApplyForce" internally. I think I know what is going on. Are you applying the force during a key press. I have a feeling you are having to apply such a large force because you are only applying the force for a micro second.

I'm going to go back on what I said before. You effectivly need to apply an impulse rather than a force. You can do this by instantaneously changing the velocity. (I know I said never do that...ignore that.)

So, when you press you button, instead of doing ApplyForce(10,-10). Do LinearVelocity = new Vector(10,-10) Just do that once, when the button is pressed, then let the physics engine take over again. You may need to play with the values.

Hope this helps and sorry for the mis-direction earlier.
Feb 11, 2007 at 6:51 AM
Edited Feb 11, 2007 at 7:03 AM
Nevermind I seem to found the problem.. ( wtf can't delete message :( )