Adjusting linear velocity of kinematic bodies

Topics: Developer Forum, User Forum
Mar 21, 2012 at 4:42 PM

Hey,

I'm creating a game, where I need to move a kinematic body only on "X' axis based on the user input from touch screen.

The value from the user input comes from:

gesture.Delta.X  //a vector2 type

Now the problem is, I have no idea how to set the velocity.

Can anyone please explain the function which is used to set the velocity and values that it takes?

 

Thanks in advance

Mar 21, 2012 at 9:00 PM

Try Body.ApplyLinearImpulse(YourVector);

Mar 21, 2012 at 9:11 PM

What should that vector hold? cause I passed "gesture.Delta" - which is a vector of position - to it and there is no response.

Mar 21, 2012 at 10:02 PM
Edited Mar 21, 2012 at 10:03 PM

Try to multiply yourVector with a high value like 10000 is there still no response?

Gesture.Delta should work i think

Mar 21, 2012 at 10:26 PM

nope, still nothing

Mar 21, 2012 at 11:05 PM
Edited Mar 21, 2012 at 11:19 PM

Just set Body.LinearVelocity=YourVector*timeStep (to make it move in one frame). Kinematic bodies have infinite mass (actually 0 is stored for mass and inverse mass by the engine) so you have to move them by setting their positions (teleporting) or velocities manually.

Mar 22, 2012 at 8:14 AM
jerrysb wrote:

Just set Body.LinearVelocity=YourVector*timeStep (to make it move in one frame). Kinematic bodies have infinite mass (actually 0 is stored for mass and inverse mass by the engine) so you have to move them by setting their positions (teleporting) or velocities manually.

Could this also be a solution to solve my Problem here: http://farseerphysics.codeplex.com/discussions/349421

My arrow bodies are moving, but really slow.

I set the bodies to dynamic before i aplly the linear impulse

Mar 22, 2012 at 8:52 AM
jerrysb wrote:

Just set Body.LinearVelocity=YourVector*timeStep (to make it move in one frame). Kinematic bodies have infinite mass (actually 0 is stored for mass and inverse mass by the engine) so you have to move them by setting their positions (teleporting) or velocities manually.

Thanks, this one works. But I've got some problem now.

First, How do I make sure the body doesn't go out of the screen bound? I had this piece of code which works for non-farseer objects, but since Position is not a variable on Farseer, it won't work in its current form.

player.Position.X = MathHelper.Clamp(player.Position.X, 0, GraphicsDevice.Viewport.Width - player.Width);
player.Position.Y = MathHelper.Clamp(player.Position.Y, 0, GraphicsDevice.Viewport.Height - player.Height);

Second, I'm using freedrag as a gesture input from touch screen. which makes the object move anywhere on the screen. But I want it to move only on X axis.

Again I can use gesture.Delta.X for non-farseer objects but that wont work here. VerticalDrag and HorizontalDrag don't have any response also.

Mar 22, 2012 at 3:03 PM

Position is in fact a property of FarseerPhysics.Dynamics.Body and you can set it. You can also set the "transform" which is position and rotation. But convert your units always from pixels to meters and vice-versa. Never use pixels as a rule of thumb. 

If you want your body to go from it's current position to position+delta you can:

1. Teleport it by setting the new position=current+new Vector2(ConvertToSimUnits(gesture.delta.x),0)

OR

2. Set it's velocity so that it arrives at the new position according to some equation depending on gesture.delta.x. This is actually called "tweening" in the general case. You have to do some calculation what the velocity will have to be frame by frame. The simplest form is making it go there in one frame (similar to teleporting with the difference that you do it "physically" which is better for the engine). You can search on the net for some advanced tweening algorithms and choose the ones most suitable. For a visual example all animations jQuery does on html elements (called effects) use tweening algorithms.

Of course if it has to move only on the X axis just kill the Y velocity.

Mar 22, 2012 at 4:19 PM

Finally, I fucking got it!!!!

Using MathHelper.Clamp I managed to restrict its Y position so that It can't move outside of the specified range.

Teleporting resulted in strange behaviors, so I didn't use it.

Thanks jerrysp.

One last question though, right now the body moves when I do freedraging on the touch screen but the problem is, it keeps going into that direction even if I stop dragging, instead I want it to immediately stop at its position when I stop dragging. Is such thing possible? How?

 

Thanks a million in advance.

Mar 22, 2012 at 9:08 PM
Edited Mar 22, 2012 at 9:08 PM

I think you can check for TouchState released at handle input and stop the body by setting the current velocity values to zero.

Mar 23, 2012 at 12:07 PM
CSharper76 wrote:

I think you can check for TouchState released at handle input and stop the body by setting the current velocity values to zero.

I couldn't find any "Released" TouchState on XNA, so I tried to do it this way:

  while (TouchPanel.IsGestureAvailable)
            {
                GestureSample gesture = TouchPanel.ReadGesture();
                if (gesture.GestureType == GestureType.FreeDrag)
                {
                    player.LinearVelocity = gesture.Delta * 10 * (float)gameTime.ElapsedGameTime.TotalSeconds;
                }
                else
                    player.LinearVelocity = zero;
            }

But again there's no response. 

Note that "zero" is a vector2 (0, 0).

Mar 23, 2012 at 12:25 PM

I don't have experience with touch but are you  sure you don't have a logic error in the code? What happens if there is no gesture (because you read it and removed it from the queue). The while loop won't execute and you won't set the velocity to 0. With you current code after you finish dragging tap the screen - the body should stop because the "while" loop will be entered and since it's not FreeDrag but Tap the "else" will be executed.

Mar 23, 2012 at 12:30 PM

You can try

 

foreach ( TouchLocation l in input.TouchState )
            {
                 if ( l.State == TouchLocationState.Released )
                      { ....

Mar 23, 2012 at 3:38 PM

Got it, I put 

player.LinearVelocity = zero;

before the while and now it works fine.

 

Thank you both.