In my game I have a Player
class that holds 2 sprites that are animated when the user runs or jumps.
Everything is working fine but when those sprites first animate they are not aligned correctly.
There is a video with the problem happening with debug turned on to make it better to visualize. (I think that the jump and run sprites’ debug body are bigger because they are a loaded using multi atlas, hence, they have lots of sprites of different things with different dimensions)
I’d like to know how to correctly position those sprites correctly.
// Particles.ts
/**
* Represents a particle used in conjunction with characters or objects
*/
interface Particle {
show(): void
hide(): void
createAnimations(): void
}
export class RunParticles extends Phaser.Physics.Arcade.Sprite
implements Particle {
constructor(
scene: Phaser.Scene,
x: number,
y: number,
texture: string = 'objects'
) {
super(scene, x, y, texture)
this.setActive(false).setVisible(false)
scene.add.existing(this)
scene.physics.world.enableBody(this, 1)
this.createAnimations()
this.on(
`${Phaser.Animations.Events.SPRITE_ANIMATION_COMPLETE}-runParticles`,
this.hide
)
}
show() {
this.setActive(true).setVisible(true)
this.play('runParticles', true)
}
hide() {
this.setActive(false).setVisible(false)
}
createAnimations() {
this.scene.anims.create({
key: 'runParticles',
frames: this.scene.anims.generateFrameNames('objects', {
prefix: 'particles/run-particles/',
suffix: '.png',
start: 1,
end: 6,
}),
})
}
}
export class JumpParticles extends Phaser.Physics.Arcade.Sprite
implements Particle {
constructor(
scene: Phaser.Scene,
x: number,
y: number,
texture: string = 'objects'
) {
super(scene, x, y, texture)
this.setActive(false).setVisible(false)
scene.add.existing(this)
scene.physics.world.enableBody(this, Phaser.Physics.Arcade.STATIC_BODY)
this.createAnimations()
this.on(
`${Phaser.Animations.Events.SPRITE_ANIMATION_COMPLETE}-jumpParticles`,
this.hide
)
}
show() {
this.setActive(true).setVisible(true)
this.play('jumpParticles', true)
}
hide() {
this.setActive(false).setVisible(false)
}
createAnimations() {
this.scene.anims.create({
key: 'jumpParticles',
frames: this.scene.anims.generateFrameNames('objects', {
prefix: 'particles/jump-particles/',
suffix: '.png',
start: 1,
end: 6,
}),
})
}
}
// Player.ts
import { RunParticles, JumpParticles } from 'scripts/sprites/Particles'
export class Player extends Phaser.Physics.Arcade.Sprite {
isJumping: boolean = false
runParticle: RunParticles
jumpParticle: JumpParticles
lastRanDirection: string
constructor(
scene: Phaser.Scene,
x: number,
y: number,
texture: string = 'player'
) {
super(scene, x, y, texture)
scene.add.existing(this)
scene.physics.world.enableBody(this, 0)
this.setGravityY(1200)
this.runParticle = new RunParticles(scene, x, y)
this.jumpParticle = new JumpParticles(scene, x, y)
this.createAnimations()
this.play('playerIdle')
}
createAnimations() {
this.scene.anims.create({
key: 'playerIdle',
frames: this.scene.anims.generateFrameNames('player', {
prefix: 'idle/',
suffix: '.png',
start: 1,
end: 26,
}),
repeat: -1,
frameRate: 20,
})
this.scene.anims.create({
key: 'playerRun',
frames: this.scene.anims.generateFrameNames('player', {
prefix: 'run/',
suffix: '.png',
start: 1,
end: 14,
}),
repeat: -1,
frameRate: 20,
})
this.scene.anims.create({
key: 'playerJump',
frames: this.scene.anims.generateFrameNames('player', {
prefix: 'jump/',
suffix: '.png',
start: 1,
end: 4,
}),
repeat: 0,
})
}
update(): void {
super.update()
this.isJumping = !this.body.blocked.down
}
jump(): void {
if (this.isJumping) {
if (this.anims?.currentFrame?.isLast) {
this.anims.pause()
}
} else {
this.play('playerJump', true)
this.setVelocityY(-700)
Phaser.Display.Align.In.BottomCenter(this.jumpParticle, this)
this.jumpParticle.show()
}
}
stopRunning(): void {
this.setVelocityX(0)
!this.isJumping && this.play('playerIdle', true)
}
run(direction: string): void {
if (direction != this.lastRanDirection) {
if (this.body.blocked.down) {
Phaser.Display.Align.In.BottomCenter(this.runParticle, this)
this.runParticle.show()
}
}
switch (direction) {
case 'left':
this.setVelocityX(-300)
this.flipX = true
this.runParticle.flipX = true
!this.isJumping && this.play('playerRun', true)
break
case 'right':
this.setVelocityX(300)
this.flipX = false
this.runParticle.flipX = false
!this.isJumping && this.play('playerRun', true)
break
}
this.lastRanDirection = direction
}
}