If you've tried adding an Arcade Physics Body to a complex Spine animation like the SpineBoy example then you probably ran into problems.
First, scaling down SpineBoy probably resulted in a bounding box with the wrong size.
Then changing direction by inverting scaleX moved SpineBoy out of the bounding box completely. 😬
And if you solved those problems then the physics box kept bouncing up and down. ðŸ˜
Something like this perhaps?
We can solve this by using Phaser's Container class!
SpinePlugin and TypeScript
It is assumed that you've got the SpinePlugin installed and working in your project.
Check out this article if you need help with that.
We will be using TypeScript in this example but the concepts are the same for vanilla or modern JavaScript.
Using a Container
A Phaser.GameObjects.Container lets us put multiple GameObjects under a single parent.
This technique is similar to the one we used for making a homing missle with Arcade Physics.
We will put a SpineGameObject in a Container and then add an Arcade Physics Body to the Container instead of directly on the SpineGameObject.
This lets us adjust and control the physics box regardless of what the Spine animation is doing.
Here's the starting point for our SpineContainer:
|
|
We create a SpineGameObject on line 16 and store it in a class property that can be retrieved with the spine getter.
Then we add a physics body to the SpineContainer on line 18. Notice that we've separated the physics box from the SpineGameObject.
The faceDirection(dir: 1 | -1) method on line 29 is used to change which direction the SpineGameObject is facing so that we can move left or right.
There is a setPhysicsSize(width: number, height: number) on line 39 to allow changing the physics box if using the default bounds from the SpineGameObject is not quite right.
Integrate with GameObjectFactory
We like to keep our code idiomatic to Phaser so we will integrate with the GameObjectFactory.
Check out this article for more details on how to do that.
|
|
We are creating an interface called ISpineContainer that we will use to let TypeScript know about this.add.spineContainer in the snippet below.
Then we add an implements call to the SpineContainer class and add the logic to integrate with the GameObjectFactory.
|
|
This uses Declaration Merging to let TypeScript know about the new spineContainer method we registered.
The second addition to the Container interface removes the error when we try to add a SpineGameObject to it.
Use in a Scene
Be sure to import the SpineContainer class in your Scene and then you can use it in create like this:
|
|
You can then get a reference to the underlying SpineGameObject using the spine property of SpineContainer and handle changing animations to get something that looks like this:
The physics box stays in place and behaves as you'd expect. No erratic shifting, bouncing, or floating!
Next Steps
The example code is tailored to the SpineBoy asset. Specifically, the setPhysicsSize() method that is assuming the anchor or origin point is at the bottom by the feet.
Different Spine animations will probably need that adjusted or the physics box won't end up where you'd expect.
For example, a centered origin point would want width and height divided in half.
Be sure to sign up for our newsletter so you don't miss any future Phaser 3 game development tips and techniques!
Drop your email into the box below.
Don't miss any Phaser 3 game development content
Subscribers get exclusive tips & techniques not found on the blog!
Join our newsletter. It's free. We don't spam. Spamming is for jerks.