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.