Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I am working on a 2D side-scroller using Farseer Physics Engine v3.3.1.

In order to create a realistic physical skeleton for the player, I am using a method similar to the one explained here (See "Texture to polygon" section).

Below is my code for creating the player body:

uint[] data = new uint[Source.Width * Source.Height];

mTexture.GetData(0, Source, data, 0, Source.Width * Source.Height);

Vertices textureVertices = PolygonTools.CreatePolygon(data, Source.Width, false);

Vector2 centroid = -textureVertices.GetCentroid();
textureVertices.Translate(ref centroid);

mPhysicalDrawOrigin = -centroid;

textureVertices = SimplifyTools.ReduceByDistance(textureVertices, 2.5f);

List<Vertices> list = BayazitDecomposer.ConvexPartition(textureVertices);

Vector2 vertScale = new Vector2(ConvertUnits.ToSimUnits(1)) * Scale;
foreach (Vertices vertices in list)
{
    vertices.Scale(ref vertScale);
}

mBody = BodyFactory.CreateCompoundPolygon(mWorld, list, 1f, BodyType.Dynamic);

The player's sprite is animated, though, so the problem arises when switching states - I.e. the player is crouching or jumping. The physical body created above only reflects one state (currently standing).

Is there a way I could somehow create a body for each sprite and swap them out later?


UPDATE:

As suggested by @Nick Wiggill, I am creating one physical body per player state (I.e. walking, standing, jumping, etc) when the player is loaded, and saving them within my class. All the bodies have .Enabled = false; initially, and are only enabled when the player is in the state that corresponds to that physical body. The Bodies and their corresponding states are stored in parallel lists.

Currently, my class has a function SetState which takes care of changing the physical body when the state is changed:

new protected void SetState(object nState)
{
    //If mBody == null, the player is being loaded for the first time
    if (mBody == null)
    {
        mBody = mBodies[mStates.IndexOf(nState)];
        mBody.Enabled = true;
    }
    else
    {
        //Get the body for the given state
        Body nBody = mBodies[mStates.IndexOf(nState)];
        //Disable the current body
        mBody.Enabled = false;
        //Copy the current body's attributes to the new one
        nBody.Position = mBody.Position;
        nBody.LinearVelocity = mBody.LinearVelocity;
        nBody.AngularVelocity = mBody.AngularVelocity;
        //Set the current body to the new body
        mBody = nBody;
        //Enable the new body
        nBody.Enabled = true;
    }
}

Currently, when the game loads, a NullReferenceException is thrown when calling World.Step: mWorld.Step(Math.Min((float)nGameTime.ElapsedGameTime.TotalSeconds, (1f / 30f)));

In the above function, mBody is just a variable I have to keep track of the current active body. I'm not modifying the body in any other way outside of the above function, and none of the m* variables are referenced or saved anywhere outside of my class. Perhaps I am swapping the bodies incorrectly?


UPDATE: Created a new question with the newer, slightly more specific issue: Farseer Physics - IndexOutOfRangeException when calling World.Step after Enabling/Disabling a body

share|improve this question
add comment

3 Answers 3

up vote 1 down vote accepted

You can have more than one b2World (i.e. standalone Box2D simulation) in place at a given time... this is also used to implement wrap-around worlds. You could store spare bodies there. If you disable/sleep them all, it won't cost much, just a bit of memory.

The other alternative is to create the spare bodies (yech!) in a "no-fly zone", a remote part of the map that will never be traversed in normal play.

The cost per body, as you've probably guessed, is very light. You should be able to safely simulate several thousand bodies at a given time. Unless you are thinking about having huge armies of units in motion at once (which, given the area of interest around the player being limited, would be unlikely anyway after basic optimisation), I wouldn't worry about duplicating bodies too much; it all depends on your figures though.

I remember dealing with a similar issue to yours when prototyping once, and a similar solution came to mind. Can't recall if I got around to trying it, though.

share|improve this answer
1  
But since this would be the player body, I would have to worry about movement...I suppose I could just disable the bodies that weren't being used? –  WilHall Jan 24 '12 at 13:09
    
I modified my player class to enable the body for the state it's in and disable bodies for other states, but I get the error NullReferenceException was Unhandled when stepping my world: mWorld.Step(Math.Min((float)nGameTime.ElapsedGameTime.TotalSeconds, (1f / 30f)));. I verified that none of the variables on that line were null. I got this error previously when I tried to modify fixtures in the player body, seems to happen when I change the player's body during the simulation. –  WilHall Jan 24 '12 at 13:30
    
You cannot move fixtures around, it breaks. If you do that, you need to re-register the fixture to your Body, which will initialize a new fixture (bad for memory). You can, however, move bodies around. –  Jon Jan 24 '12 at 13:32
    
Hm, well currently I'm just enabling/disabling bodies, and still getting that error. If I don't disable/enable then, they error dissapears. Is there any reason doing so would cause that? –  WilHall Jan 24 '12 at 13:38
    
@WilHall Have you tried a simple test case: Nothing but a world and a couple of bodies, and you hitting a key to toggle enablement of each? Just to make sure everything is kosher? Because if all you're doing is that, there should be no breakage to speak of. When that's working, google "teleport b2body" and you'll see how to shift it once enabled/disabled. –  Nick Wiggill Jan 24 '12 at 13:46
show 2 more comments

It is actually really easy

for (int i = 0; i < origin.body.FixtureList.Count; i++)
{
     origin.body.DestroyFixture(origin.body.FixtureList[i]);
}
FixtureFactory.AttachCompoundPolygon(verticeslist, 1f, origin.body, null);

return origin.body;
share|improve this answer
1  
Isn't this a situation where you should be iterating backwards? Or do the indices of each object not move forward? –  Jonathan Hobbs May 7 '12 at 8:14
    
@JonathanHobbs Good point, I'm not sure if the objects actually get removed from the fixture list until the next world step or not, Would have to test –  WilHall May 9 '12 at 2:14
add comment

Your sprites are drawn separate from your physics engine, so unless you need to provide proper collision detection when crouching, you shouldn't have to swap the body. Just draw the crouched texture on top of it.

If you really need to replace the body, you can consider creating all the bodies you need, and then set their position to something like Int.Min so that it doesn't draw on your screen. Then you can simply swap positions with the active body when needed.

Might be a few issues with this method, considering your body is dynamic.

The point though, is to try not to destroy/create bodies everytime your character crouches.

share|improve this answer
    
That was my problem - making the sprite correspond to the body. I don't need the collision body to be 100% perfect, but at least for crouching and jumping I need it to match up enough where the player won't get hit somewhere that isn't within the sprite's bounds. I'm currently trying to create all bodies (disabled to start) and then disabling/enabling them when needed, modifying positions and velocities as needed. Ran into an issue, though, See the comments on @Nick Wiggm's answer –  WilHall Jan 24 '12 at 13:35
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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