[SOLVED] Moving physics objects with Mouse

Topics: Developer Forum, User Forum
Apr 11, 2010 at 8:41 PM
Edited Apr 11, 2010 at 9:08 PM

Hey,

I have some simple objects in my game level (well, just trying with one right now - a crate) which I would like the player to be able to pick up and drag around with the mouse at will, so as to help them overcome obstacles and generally progress through the level.
I started out with some very primitive code which was simply based on mouse position:

if(InputManager.Mouse.IsOn(sprite.CollisionAxisAlignedRectangle) && InputManager.Mouse.ButtonDown(MouseButtons.LeftButton))
{
     body.Position = new Vector2(InputManager.Mouse.WorldXAt(0), InputManager.Mouse.WorldYAt(0)); 
}

That bit of code is run in the game loop, and all it does is update the physics Body position to be at the mouse cursor's position. I quickly saw some real weird behaviour with the crate when I tested it out. One of the major ones being that I had to drag quite slowly in order for the crate to stay with the mouse. If I did a slightly fast drag, the object would drop from the mouse position. In addition to that, if while dragging around I happened to touch the crate to another physics object, it would do some crazy rotation on the spot like as though something's given it a real hard spin. And there's probably more stuff I haven't discovered yet...

I've had a sweep of the forums here, and have noticed plenty of threads related to mouse control, with quite a few posing the same/similar question. However, none of them had a fitting way to achieve this.
What I want is the ability to click on and drag objects around without a lag or springy effect like the Farseer demos do. The object should be spot-on with the mouse position, and it should have its regular physics behaviours intact.

Can someone who has gotten this functionality working, or someone more experienced with the engine please help out with this? Any logic, code, pseudo-code that could get me started would be great.
I'm using Farseer with FlatRedBall XNA Game Engine.

Thanks muchly. 

 

Apr 11, 2010 at 9:50 PM

If you want to move an object with the mouse, and you don't want it to affect the world around it,

then you need to first disable the body or bodies that are being moved, and re-enable them when

you want to drop it or them.

Apr 13, 2010 at 9:08 PM

@ oranjoose:

Yup, am aware of that fact, but I actually want the exact opposite of what you said, i.e., I do want the object to retain all its physics behaviour while being picked up and dragged around.
That's the fact that's making it difficult, having it work without the physics would be quite straightforward...

Anymore help would be very welcome as it is much needed! 

Apr 13, 2010 at 10:51 PM

I would recommend using springs like the ones in the examples from the testbed,

otherwise, if you follow the mouse perfectly, then really weird stuff will happen when

you *want this block exactly here* even if it's in the middle of a static body, or something

else that should move easily.

The spring or mouseJoint will keep the physics straight, and the spring will just stretch.

Like I said, review the samples for how they do this.

 

 

Apr 13, 2010 at 11:22 PM

@ oranjoose:

Thanks for the prompt reply. I see what you're saying about having weird reactions if the user were to move an object "into" another one. But this is exactly why I wanted to have a way to have precise mouse control AND physics behaviour at the same time, so that even if the user tried to break the mechanics (who doesn't love doing that to games!? :P) by placing objects within each other, their collisions would prevent them from doing so...

Anyhow, since I require this functionality quite urgently, I guess I shall look up how to do it using a Spring from the Farseer examples, as you suggested. Thanks.

If anyone else reading this has implemented perfect mouse control without springy behaviour, please do share your methods, as I would still be interested if that's possible.

Cheers. 

Apr 14, 2010 at 4:07 AM
Edited Apr 14, 2010 at 4:09 AM

You can try to move the object to where the mouse is by using impulse.

 

        public bool MoveTo(ref Vector2 point)
        {
            if ((objPosition - point).Length() < 10) // If it is 10 units from the destination, we consider it has arrived
                return true;

            Vector2 amount = (point - objPosition);
            amount.X = (float)Math.Round(Math.Cos((float)Math.Atan2(amount.Y, amount.X)), 2) * Force;
            amount.Y = (float)Math.Round(Math.Sin((float)Math.Atan2(amount.Y, amount.X)), 2) * Force;

            geom.Body.ApplyImpulse(ref amount);

            return false;
        }

Call the method from your object's update method.. something like "if (obj.IsPickedUp) MoveTo(ref mousePos)"

Applying an impulse will move the object quick. Change the Force variable for the amount of impulse to apply. My only worry is that it may cause a slight jittery effect but it also might not because of the ((objPosition - point).Length() < 10) condition.

good luck :)

Apr 14, 2010 at 8:05 AM
Edited Apr 14, 2010 at 8:08 AM
@ mrmo:

Thanks very much for taking the time to post that, much appreciated! I probably would've never figured all that out from the looks of it, Math not being one of my strong points, hehe. I'll give it a go soon and report back.
Apr 25, 2010 at 10:01 AM
Edited Apr 25, 2010 at 10:03 AM

Ok, so it's been a while since I replied on here, but I wanted to make sure I've tried everything possible before posting again, plus I was bogged down with other work, so...

Unfortunately, the code provided above by mrmo didn't help much with my moving of objects, it just had some very random, weird, jerky behaviour, with the object being picked awkwardly sometimes for only a few seconds, and not being picked at all at other times.
So I decided I'd be a little flexible as I was running out of time, and implement a solution using a joint or spring as hinted at in numerous threads about this issue on the forums, as well as how the examples do.
So I've got a 'dummy' invisible physics body tracking the mouse position, and I tried to create a joint/spring between the object to be picked and the dummy mouse object when the left mouse button is clicked. However, nothing works as it should.

I've tried nearly every single joint and spring for this purpose (fixed, linear, revolute, angle, etc.), and not one of them behaved correctly. I've also been through all the other discussion threads related to this topic, and so far, none of them have actually specified a perfect solution yet. It's a very important mechanic for my game, and hence if anyone here could help me by outlining/posting some code showing how exactly they might've accomplished this
(including the values of any spring/joint properties), I would be much relieved and grateful. I need this mechanic working ASAP in my project.

Thanks to all in advance. 

Developer
Apr 25, 2010 at 12:47 PM

I main problem with a physics engine is it hates to move anything using it position. You need to come up with a method that moves the Body using velocity to the desired position (under the mouse). I tried this method in my editor for 3.x Farseer and could only get a crazy gravitational like pull around the mouse. I'm sure there is some math formula that can find the velocity it takes to move an object a certain distance in a certain amount of time. Problem is you would need to clear that velocity after every frame I think. Mrmo's code attempts this but is not using the correct formula. I will try to find the formula for u.

or

You could take the LinearSpring implementation from in the Samples Framework and increase the SpringConstant and DampingConstant to some ridiculous high number.

 

Developer
Apr 25, 2010 at 1:16 PM

I have found a solution I am just fine tuning an example for you.

 

Developer
Apr 25, 2010 at 1:44 PM

Here is what I've come up with.

http://www.mediafire.com/?yu2ztjlty2u

Let me know if this is what you needed.

Donations are accepted ;)

 

Apr 25, 2010 at 7:03 PM

@ mattbettcher:

First off, a big thanks for taking the time out to check this out!
Secondly, another big thanks for solving my problem!

After I'd made my last post, I went back to my code and tried using a WeldJoint between the dummy mouse object and the object to be moved, and this time, I got it roughly working, with much better though not always stable results than my attempts with all the other Joints/Springs...
But then I saw your post, read up on your code, and adapted it to my project, with the necessary changes, and it works pretty much a treat, even better than the WeldJoint result I got.

So I'm now using your 1st solution - moving the objects by velocity in the direction of the mouse. Working well so far, and I hope it stays that way. If anything crops up, I'll post back, but for now, consider this solved! 
Thanks heaps! :-)
 

Developer
Apr 25, 2010 at 7:25 PM

Glad I could help.