Jump to content

Assigning different body to different frames of an animation


NumberOneRobot
 Share

Recommended Posts

I'm trying to create different bodies for my different animation frames on my spritesheet. I tried using PhysicsEditor to do this by creating a different body for each of the frames as it showed up in PhysicsEditor. When I try to put this and PhysicsInfo into my game, however, I see the entire spritesheet all the time, and no animation or movement is possible. Is this because I can't assign multiple bodies to a spritesheet? (this test was done with the example at http://www.photonstorm.com/phaser/tutorial-making-your-first-phaser-game, I added the physics info putting a different polygon around each of the frames in the spritesheet using PhysicsEditor, and added the info file in the preload function)

 

I assumed that if there was a spritesheet frame being shown, only the physics information that falls within the bounds of that frame on the spritesheet would be used, but it looks like that's not the case.

 

If I can't assign different bodies to different frames on a spritesheet, should I instead separate the frames and have the animation then cycle through each of the different frames and change the body each time? I'm trying to animate a character for a fighting game that will have different hitboxes for different frames, but this doesn't seem to be possible without cycling through a bunch of frames and changing the hitbox on each frame. This seems like it'd take a lot of RAM if I have all this for each character and each frame, and it may be slow to change each of the bodies on each frame.

Link to comment
Share on other sites

I don't know why the entire spritesheet showed. I'd have to see some code.

I imagine you are using p2 physics, but even if you are using arcade, I wouldn't recomend creating so many bodies for this. It would be better to simply create one body, add all your shapes to it, and disable them all. Then I would check to see which frame the animator is currently showing and enable only the shapes that are needed for that frame. I imagine you'd have to implement your own paradigm to organize a way to know which shapes go with which frames. I supose you would need multiple shapes for each frame because, even if you are using simple collider shapes, you may need some shapes that are defined as sensors so that, for example, only one foot hurts the other player when a kick is thrown.

That way you do not need to manage multiple bodies, which makes the code much more complex and takes a lot more resources from the computer; but at the same time, you do not have to create and add shapes each frame, which is also bad. Is much more faster then.

P.D.
Also, the more you use sensors instead of full colliders, the easier it will be on the processor.

Link to comment
Share on other sites

Thank you for the response!

 

I'm a bit confused about what you mean by using "sensors instead of full colliders." I've been looking through the docs about sensors, and as far as I can tell, they're something that, when a collision is begun and again when it ends, will raise an event that can then be handled by the onBeginContact and onEndContact handlers.

 

How to disable and enable shapes confuses me as well, but from what I understand about sensors and reading other areas on this forum, I think it means simply set the sensor property for the shape to be false and then it will not detect collisions. Please correct me if I'm wrong!

Link to comment
Share on other sites

Yes. I guess it can be difficult to get because it is not in the phaser documentation. To use sensors, you have to directly access the p2 physics body. The p2 physics in Phaser is just a bridge between the library and the game engine, so for example, in order to access the real p2 body of a body, you have to acces its data property:

body.data;

The real p2 body (you can check its reference here: http://schteppe.github.io/p2.js/docs/classes/Body.html) has a shapes property, which is an array of shapes that belong to that body. Then, you can access each shape; so, for example, this gives you the first shape of a body:

body.data.shapes[0];

From there you can set it as sensor, a sensor will check if it overlaps other bodies' shapes, but wont generate collision data nor calculate forces, so it is easier on the processor. Also, it allows you to check if something overlaps with something without having to do really weird tricks. A note: if you are using the collision data that onBeginContact and onEndContact give to you, you most check if one of the shapes if a sensor, otherwise, it will throw an error beacause that collision data doesn't exist. To set it as sensor, you do
 

body.data.shapes[0].sensor=true;

Accessing the data propertie of a body is useful because some really cool features of p2 physics are not directly implemented in phaser. Also, you can set shape sizes, velocities, forces, position etc. in meters; that can make easier to manage different resolutions of your game, since the numbers you set in meters will adapt to the scale you set for the p2 physics implementation in phaser without having to preprocess them.
 

Disabling the shapes is another matter; a huge matter. I can think of two ways right now:

 

1. You could do as you suggested, since you in phaser you cannot have multiple bodies for one sprite, you would have create a different empty game object for each significant frame you have. Then, add the corresponding shapes to each object. You would have to create a different game object, with the animated sprite and without physics, that follows the active game object with physics. Each frame you remove the past frame's active physics body from the world and add the current frame's active physics body. You would have to manage a more complex contact management, since you'll have a different set of collision events for each body. You would also have to integrate the forces you and the p2 library add to the active body with the rest of the bodies, because the bodies are different between them; the forces and acceleration applied to the active body, do not apply to the rest of them. You'd have to copy the velocity, rotation and position of the active body to the rest before removing it and, depending on how much you use the physics, you would have to be smart when applying accelerations. Each thing you do to the character, you would have to do it to all of its physics bodies. I believe if your game is relatively simple, this could be the easier method to implement, but each layer of complexity you add makes the code harder because the body sincronization problem (and if it is that simple of a game, why not then use just use arcade physics and compare pixel masks for collisions, like old games). Also, you would have to profile to be shure, but I think this would be a much more expensive way; there would be a lot of objects and a lot more process on each update loop.

2. You can store all the shapes you need in an array or an object; and then each different frame you remove the shapes you don't need and add the ones you need (depending on your game and how precise it is, you may need to remove all the shapes each new frame or you may keep a shape that roughly represents the main body in all frames and little sensor shapes that represent atacks). This method requieres more code on the object creation part, but then it is much more easier to manage. You only have one body atached to the sprite you are using. All tweens and all weird physic stuff you do, becames as simple as what you would do with any other body. Also, I believe it would require a lot of less resources from the browser.

To use this method, you would have to do a trick to store the shapes into an array separated from the body. You could import the shapes as you would normally do, copy the shapes array from the data property of the phaser body to an array, and then call clearShapes on the body so that the body is clean and you have a copy of the shapes stored for later use. Note that you would also have to copy the shapeOffsets array of the data property too, because Phaser, in order to do some weird thing with the center of mass of the shapes that I'll explain later, has to apply an offset to the shape in order for it to fit the sprite. So, when readding a shape, you would also have to apply its offset.

Or you could implement your own shape creator, you could look at the source of the loadPolygon method, it's really easy, you can pretty much copy it and instead of adding the shape to the body, add the shape to your array. I believe you could strip it even more; it does a lot of work to center to center the shape around its center of mass, and then it compensates by adding an offset to the position of the shape when it adds it to the p2 body. I don't know why it does that, there is probably a reason, but at first stance it doesn't seem like a really good idea to me; the center of mass is normally important for realistic physics; and centering the shape around it just negates it. I imagine that a fighting game doesn't care for the center of mass of a shape, since you would probably constrain the rotation anyway, but stripping the weird center of mass of the code would allow you to avoid having to manage also a shapeOffsets array and it would simplify your code.

After implementing your shape manager array, (wich could be an array of arrays of shapes, so that you have your shapes organized by frame, or whatever other organization method you want) you would need to update the shapes each frame; do this directly in the phaser body, so that the debug render updates too. If your shapes are completely different each frame, then use first body.clearShapes. If not, you can use remove each shape you need to remove. Then you just have to use body.addShape to add the shapes you need. If you didn't deal with the center of mass offset issue, then, when passing the offset to the addshape method, you have to use the mpxi method inside body.world to convert from p2 units to phaser units.

I tell you all this, because I haven't tried each option, I've never really had to. And I don't have much free time right now. And I'm honestly too lazy to check them, and it seems easier to just write my stream of thought now, but none of them seem to complicated to try. And all of them would work, its a matter of what works better for you, so I give you the information I think you need to decide. Though, I sometimes write in a very confusing way without realizing, so I hope it's not that confusing. And if it is, well, here I am.

Link to comment
Share on other sites

PD. 3. You could have all the shapes from all the frames active at the same time. And only remove from collision groups the shapes that you are not using and add the shapes that your are using. You would still have to manage a separate array of shapes or implement another way of knowing wich shapes work in every frame. I belive this would require roughly the same amount of code than the second way and that it would be moderately more expensive, because the p2 library still has to manage the shapes for all frames at the same time, even if most of them don't collide, but it might be a lot easier to understand because you don't need to manage the bridge between phaser and the p2 library as much.

Link to comment
Share on other sites

Something I'd been considering is loading all the shapes into the body to start, then setting the sensor property to false for each shape that isn't "active" in the current frame. I would keep track of this using an array with the index (into the body's shape array) of each shape relevant to a frame, and then set the sensor property of those shapes to true, and the others to false.

 

This seems simplest to me, and perhaps I don't quite understand what happens if the sensor property is false. I'd assume it'd just register no collision if either shape is set to be a sensor. Is this true, or is a collision registered even if only one of the shapes is a sensor? Even if only one shape is registered as a sensor, I'd assume I could just check if the other shape is a sensor, then I should be able to tell whether this is a collision I should do something about or a collision I can ignore.

 

I'd load up all the shapes by writing an analogous function to the loadPolygon function, that'd take data from the physics editor program output and turn it into a set of shapes for an animation.

 

Does this sound like it'd work, or does this simply reflect a misunderstanding of what exactly a sensor does?

Link to comment
Share on other sites

It is not a bad principle.

If the sensor property is false, it is just a normal shape that collides normally. It is true that sensor shapes don't collide, but they still fire on begin contact event when they overlap with another body and are still managed by the physics engine. The contact functions can fire from both of the shapes that make contact. If A makes contact with B, the event might fire from A making contact with B and from B making contact with A; it doesn't matter if A or B or both or none are sensors.

If you use sensors in this way, not only would it be waisting resources from the machine because it is watching shapes that don't need to be watched, but also you would have to check each time inside the contact functions if the shapes colliding are sensors or not, which seems like unnecessary work. Also, like I said before, you might want to have shapes that are always sensors, no matter what frame it is; for example a move where a character puts a sword through another character might require the sword to detect overlaping on the other player, but also to not push the other player away.

Something along that idea but with a subtle difference that might work better, is my third idea: when a shape is not needed (no matter if it is or it isn't a sensor), instead of making it a sensor, you add it to a collision group that doesn't collide with anything, when a shape is needed you add it to a collision group that makes contact with the things that need to be contacted. All, shapes are still managed by the engine, but at least they are not checked for overlapping with anyother shape; also, you don't have to manage the contact functions so much and you can use sensors for what they were meant to be used: to check if something overlaps with something.

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...