How do I create a fixture to fit my texture?

Aug 23, 2010 at 4:54 AM
Edited Aug 23, 2010 at 5:31 AM

I'm been trying Farseer 3.0 and I still haven't figure out how should I create a fixture which will fit the texture.

 

Previously what I did in Farseer 2.1 is:

( Assuming the texture size is = 256 x 256 )

rectBody = BodyFactory.Instance.CreateRectangleBody(PhysicsSimulator, rectTexture.Width, rectTexture.Height, 1);

rectGeom = GeomFactory.Instance.CreateRectangleGeom(PhysicsSimulator, rectBody, rectTexture.Width, rectTexture.Height);

 

But in Farseer 3.0, when I do something like this, it will generate a very big mass for the object and it needs very big force only can move the object.

 

rectFixture = FixtureFactory.CreateRectangle(world, rectTexture.Width , rectTexture.Height , 1);

 

Although I have set the mass to 1.

So what should I do in order to get the fixture fit the texture and it is still movable if there is force applied on it.

Aug 23, 2010 at 5:40 AM

Previously actually I'd ask about this problem before and genbox told me there might be the world.step causing the problem but I'm using exactly the same as the Farseer 3.0 example which is:

world.Step(Math.Min((float)gameTime.ElapsedGameTime.TotalMilliseconds * 0.001f, (1f / 30f)));

But it still didn't work.

 

I try on my own project, if I set the gravity to (0.0f, 10.0f) then it will move down very slowly.

But if I set the gravity to (0.0f, 10.0f) on the Farseer 3.0 sample, it will move faster than on my own project.


I really don't understand what had happened or maybe some settings I have missed out?

Aug 23, 2010 at 6:21 AM
Edited Aug 23, 2010 at 6:32 AM

Your problem is scale.  The samples have small object sizes, so your gravity isn't going to make it feel the same.  If you are making objects that large, they definitely will fall "slowly."  It would be like watching a building fall.  It really depends on the scale you want to use and the camera you have setup for your game.  Using Texture.Width is creating a 256 METER fixture, which is a single object that will be larger than a football field.  It's like a feather if it is that large with such a small mass.  

Rather than doing that, you need to select your own scale.  When I transitioned my code form FP2.x to FP3, I had a similar problem.  It took me a while and a lot of tinkering before I got it all worked out.  I think I am using a 1/200 scale per pixel right now. where that same sized object would be 1.28 units (which is 1.28 meters).  You also have to make the call about different objects as well.  Some objects will be seen under zoom, while others might not, so your pixel scale isn't always going to be the same.  My game starts out at 100x zoom level because I scale my textures to fit the small unit sizes (so my textures are scaled at 0.005).

Here is an example:

//You can still set your origin this way
_objectOrigin = new Vector2(_objectTexture.Width / 2f, _objectTexture.Height / 2f);  
//my textures are 128, so .32 as a half width is .64 width  (keep in mind that is still ~2 feet)
Vertices box = PolygonTools.CreateRectangle(0.32f, 0.32f, new Vector2(0, 0), 0);  
PolygonShape quarter1 = new PolygonShape(box);

_blonkBody.CreateFixture(quarter1);

Then in my draw:
spriteBatch.Draw(_objectTexture, new Vector2(_objectBody.Position.X, -_objectBody.Position.Y), null, Color.White,
                -_objectBody.Rotation, _objectOrigin, 0.005f, SpriteEffects.None, 0f);
Aug 23, 2010 at 7:30 AM

If you scale down your texture by 0.005 isn't it become very small ?

How do you do the zooming ? 

 

Aug 23, 2010 at 7:49 AM

With your camera, assuming you are using one.  I'm using a variation of RogueCommanderIX's camera class (which is posted here on these forums).  This is done using a Matrix for your spritebatch transformations.  When you do spriteBatch.Begin, it takes a transformation Matrix.  Here is the one from the camera class, which works well for me:

Matrix.Identity *
Matrix.CreateTranslation(new Vector3(-_position.X, _position.Y, 0)) *
Matrix.CreateScale(_zoom) *
Matrix.CreateRotationZ(_rotation) *
Matrix.CreateTranslation(new Vector3(_size / 2, 0));

If you don't have your own camera class, you can declare that in your Update() if you like as something like Matrix matrix = (the code above).  Then, in your spriteBatch.Begin, you give it matrix.  Then you can tie your zoom value to a key press (page up, page down, or whatever).  My initial zoom is 100, with a max of 150 and a minimum of 75.  There are other ways of doing this too, so maybe someone else will chime in.

Aug 23, 2010 at 9:29 AM

So this is the only way I can do?

BTW, I would like to ask why the movement in Farseer 3.0 is not as smooth as in Farseer 2.x?

(From what I've seen in the simple samples)

Aug 24, 2010 at 3:37 AM

It's not the the only way you can do it.  You could up your gravity and make things large, but you would be going against what is recommended by the people who wrote the engine.  Box2d states that things are most stable when you keep things small, and when you consider 1.0  is 1 meter, then you just need to adjust what scale you are making things.  You then need to make sure that whatever your texture size is, that you make it comply with the scale you choose.  You can adjust your game to do this, or use a camera class like I showed you here.  It's all up to you, but you really need to understand what the values are, which is the first step.  No matter which way you go, you need to know why you are doing it.  I recommend playing around with it until you understand what it is you are doing.

Aug 24, 2010 at 3:47 AM

I'd try with the way you say but the problem I found is when I zoom in the camera and scale down the texture, is that means the texture position has to be scaling down to fit the camera?

Aug 24, 2010 at 5:15 AM

As long as you set the origin properly (like I showed you above), and you pass the origin into your draw, everything should be fine.  That way your objectBody's position and your texture.position are the same.

Aug 24, 2010 at 5:21 AM

Yea, I did follow the origin and I draw based on origin, but if I didn't divide the position by the scale, I cannot see the object but once I scale the position down based on the scale, I only can see the object.

Is it something wrong with my stuffs or perhaps I shall post my code here.