0
\$\begingroup\$

The player should be able to move a Farseer body with it's fingers. How can I do that? What is the best way to create a Farseer body for the player's finger so that the player can move other Farseer bodies with it? I don't know how to do that.

If the player pushes a body(for example windmill sail) hard with it's finger, then the body should move/rotate faster.

UPDATE:

I want to move the body RectangleA1 with my finger/cursor. But something isn't working. If I press somewhere on the screen and move the cursor/finger a little bit around, then I get very often an error message in this line:

world.Step(Math.Min(elapsed, (1f / 60f)));

An exception of type 'System.NullReferenceException' occurred in FarseerForWindowsPhone.DLL but was not handled in user code

Additional information: Object reference not set to an instance of an object.

What is wrong? Why am I getting this error message?

My code:

    World world;
    Body RectangleA1, RectangleA2;
    Texture2D RectangleA1Sprite, RectangleA2Sprite;
    Body body;
    Fixture fixture;
    bool MouseJointAktiv = false;
    FarseerPhysics.Dynamics.Joints.FixedMouseJoint MouseJoint;
    private static float _displayUnitsToSimUnitsRatio = 100f;

    public static Vector2 ToDisplayUnits(Vector2 simUnits)
    {
        return simUnits * _displayUnitsToSimUnitsRatio;
    }   

    RectangleA1 = BodyFactory.CreateRectangle(world, 1.50f, 0.50f, 1.0f);
    RectangleA1.BodyType = BodyType.Dynamic;
    RectangleA1.Mass = 20;
    RectangleA1.Position = new Vector2(4f, 1f);
    RectangleA1.Rotation = 0f;
    RectangleA1.CollisionCategories = Category.Cat5;

    RectangleA2 = BodyFactory.CreateRectangle(world, 3.50f, 0.50f, 1.0f);
    RectangleA2.BodyType = BodyType.Static;
    RectangleA2.Mass = 40;
    RectangleA2.Position = new Vector2(4f, 3f);
    RectangleA2.Rotation = 0f;
    RectangleA2.CollisionCategories = Category.Cat10;


    protected override void Update(GameTime gameTime)
    {
      float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
      world.Step(Math.Min(elapsed, (1f / 60f)));

      TouchCollection touchCollection = TouchPanel.GetState();
      foreach (TouchLocation tl in touchCollection)
      {
        if ((tl.State == TouchLocationState.Pressed))
        {
          fixture = world.TestPoint(ConvertUnits.ToSimUnits(new Vector2(tl.Position.X, tl.Position.Y))); 
          if (fixture != null)
          {
            body = fixture.Body;
            MouseJoint = new FarseerPhysics.Dynamics.Joints.FixedMouseJoint(body, new Vector2(tl.Position.X, tl.Position.Y));
            MouseJoint.MaxForce = 1000 * body.Mass;
            world.AddJoint(MouseJoint);
            body.Awake = true;
            }
          }

          if ((tl.State == TouchLocationState.Moved))
          {
            if (MouseJointAktiv == true)
              MouseJoint.WorldAnchorB = ConvertUnits.ToSimUnits(new Vector2(tl.Position.X, tl.Position.Y));
          }

          if ((tl.State == TouchLocationState.Released))
          {
            world.RemoveJoint(MouseJoint);
            MouseJoint = null;
            MouseJointAktiv = false;
          }
        }

        base.Update(gameTime);
    }
\$\endgroup\$
  • \$\begingroup\$ I created a FixedMouseJoint for the player's finger but I can't move the windmill's sails with that FixedMouseJoint. \$\endgroup\$ – Homer_Simpson Jun 18 '14 at 9:17
  • \$\begingroup\$ Not enough info. Also: You can probably make the sails from a single body with multiple fixtures, then use a single revolute joint. \$\endgroup\$ – Andrew Russell Jun 18 '14 at 10:34
  • \$\begingroup\$ What is the best way to create a body for the player's finger? Should I use a FixedMouseJoint or should I do that without a joint? \$\endgroup\$ – Homer_Simpson Jun 18 '14 at 12:12
1
\$\begingroup\$

Documentation, again. This time for FixedMouseJoint:

A mouse joint is used to make a point on a body track a specified world point. This a soft constraint with a maximum force. This allows the constraint to stretch and without applying huge forces.

NOTE: this joint is not documented in the manual because it was developed to be used in the testbed. If you want to learn how to use the mouse joint, look at the testbed.

In other words, a FixedMouseJoint attaches an arbitrary point in the world (this is what the "Fixed" versions of the joints do), to a point on a body. It is used extensively in the Farseer samples.

(There is no body associated with the user's finger.)


Given a Vector2 position giving the Farseer world-space position of the user's finger (or mouse cursor), you can create a FixedMouseJoint like so:

Fixture fixture = world.TestPoint(position); // what was touched?
if(fixture != null)
{
    Body body = fixture.Body;
    mouseJoint = new FixedMouseJoint(body, position);
    mouseJoint.MaxForce = 1000 * body.Mass; // <- tune this for your game
    world.AddJoint(mouseJoint);
    body.Awake = true;
}

As usual, when the touch/mouse button comes up, destroy the joint with:

world.RemoveJoint(mouseJoint);
mouseJoint = null;

Every frame that the joint is active, update the anchor position like so:

mouseJoint.WorldAnchorB = position;

Use a single RevoluteJoint for your windmill, using a single body (with multiple fixtures) for your sails.

If the windmill sails are not slowing down as you would like, consider adding a FrictionJoint with the same anchor position on each body as the revolute joint.

(If your windmill sails are free-standing (not attached to another body), you could use the Fixed versions of these joints.)

\$\endgroup\$
  • \$\begingroup\$ Great answer, fixed mouse joint is definitely the right way to go. \$\endgroup\$ – Gustavo Maciel Jun 18 '14 at 15:00
  • \$\begingroup\$ I always get an error message in this line: body = fixture.Body; An exception of type 'System.NullReferenceException' occurred in GameName1.DLL but was not handled in user code. My fixture is always null. How should I create the fixture in this case? I'm not sure how to do that. \$\endgroup\$ – Homer_Simpson Jun 18 '14 at 22:31
  • \$\begingroup\$ That means that World.TestPoint is returning null - because the user is not actually touching a fixture in the world. So simply don't create a joint in that case. (I've updated my code to reflect this.) \$\endgroup\$ – Andrew Russell Jun 19 '14 at 4:24
  • \$\begingroup\$ If I press somewhere on the screen and move the cursor/finger a little bit around, then I get very often an error message. \$\endgroup\$ – Homer_Simpson Jun 19 '14 at 12:39
  • \$\begingroup\$ @Homer_Simpson Well, debug it! \$\endgroup\$ – Andrew Russell Jun 19 '14 at 15:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.