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?

3 Answers
3

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.

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?
–
WilHallJan 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.
–
WilHallJan 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.
–
JonJan 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?
–
WilHallJan 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.
–
Arcane EngineerJan 24 '12 at 13:46

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.

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
–
WilHallJan 24 '12 at 13:35