Using animations in a class

I have an animation that when my bullet hits enemy, an explosion animation plays. The enemies have a setVelocity(100, 0) however whenever the explosion animation plays, it explodes at the position where the enemy spawned instead of where it was last positioned.

//enemy hit callback - called in the update of my enemy class constructor

function enemyHitCallback(enemyHit, bulletHit)
{
// Reduce health of enemy
if (bulletHit.active === true && enemyHit.active === true)
{
enemyHit.health = enemyHit.health - 1;
console.log("Enemy hp: ", enemyHit.health);

            // Kill enemy if health <= 0
            if (enemyHit.health <= 0)
            {   
              
               var destroyed = []; 
               this.enemy.setActive(false).setVisible(false);
               this.turret.setActive(false).setVisible(false);
               this.shadow.setActive(false).setVisible(false);                  
               
            }

            if (destroyed)
            {
                this.anims.play('kaboom');
            }

                
    
            // Destroy bullet
            bulletHit.setActive(false).setVisible(false);
        }
        
    }

//explosion pool - called in my create function
this.anims.create({
key: ‘kaboom’,
frames: this.anims.generateFrameNames(‘explosive’, {start: 0, end: 23})
});

Do you use the explosion animation anywhere else in the game? It could be useful to create the explosion as a separate object, which will replace the enemy when it’s destroyed (you can also do that for parts on the enemy to create some cool effects)
Here’s some code you might find useful:

class Explosion extends Phaser.GameObjects.Sprite{
    constructor(scene,x,y){
        super(scene,x,y,"explosive");
        scene.add..existing(this);
        this.play("kaboom");
    }
}

in the function where the enemy is hit or desroyed, add the following:

var explosion = new Explosion(this, this.enemy.x, this.enemy.y);

this way the explosion will spawn at the enemy’s coordinates at time of destruction

I got the code from this video tutorial.


Check out the rest of them, I’m sure they will help :slight_smile:

I tried the above code that you provided and now I get this error:

phaser-arcade-physics.min.js:1 Uncaught TypeError: Cannot read property ‘queueDepthSort’ of undefined
at Explosion.initialize [as constructor] (phaser-arcade-physics.min.js:1)
at new initialize (phaser-arcade-physics.min.js:1)
at new Explosion (Entity.js:3)
at Enemy.enemyHitCallback (Entity.js:80)
at initialize.collideSpriteVsGroup (phaser-arcade-physics.min.js:1)
at initialize.collideHandler (phaser-arcade-physics.min.js:1)
at initialize.collideObjects (phaser-arcade-physics.min.js:1)
at initialize.collide (phaser-arcade-physics.min.js:1)
at Enemy.update (Entity.js:58)
at initialize.h.emit (phaser-arcade-physics.min.js:1)

Where did you add it to? It looks like you’re getting errors at line 3, 80 and 58. What function calls are on those lines?

function enemyHitCallback(enemyHit, bulletHit)
{
// Reduce health of enemy
if (bulletHit.active === true && enemyHit.active === true)
{
enemyHit.health = enemyHit.health - 1;
console.log("Enemy hp: ", enemyHit.health);

            // Kill enemy if health <= 0
            if (enemyHit.health <= 0)
            {                   
               this.enemy.setActive(false).setVisible(false);
               this.turret.setActive(false).setVisible(false);
               this.shadow.setActive(false).setVisible(false);
               this.enemy.setVelocityX(0);
               var explosion = new Explosion(this, this.enemy.x, this.enemy.y); 
               

                               
            }
             
    
            // Destroy bullet
            bulletHit.setActive(false).setVisible(false);
        }
        
    }

This is my function located in my update of my Enemy class object

Line 3 - super(scene, x, y, ‘explosive’);

Line 80 -var explosion = new Explosion(this, this.enemy.x, this.enemy.y);

Line 58 - this.scene.physics.world.collide(this.enemy, playerBullets, enemyHitCallback, null, this);

What kind of Sprite Object is your enemy? If it’s Phaser.GameObjects.Sprite, I can try and fiddle with this code, if it’s Phaser.Physics.Arcade.Sprite, then you’ll need to change the type in the Explosion object.

Also, try moving this line
var explosion = new Explosion(this, this.enemy.x, this.enemy.y);
before
this.enemy.setActive(false).setVisible(false);
so that the game still knows the coordinates of the enemy, before it’s made inactive

Im using Phaser.Physics.Arcade.Sprite for my enemy class.

I changed the explosion object to:

class Explosion extends Phaser.GameObjects.Sprite{
constructor(scene,x,y,type){
super(scene,x,y,type);
scene.add.existing(this);
this.play(“kaboom”);
}
}

and added the line to the correct spot mentioned:

var explosion = new Explosion(this, this.enemy.x, this.enemy.y, ‘explosive’);

However I’m still getting this error:

image

change the object to Phaser.Physics.Arcade.Sprite to match your enemy sprite
and considering your this binding, try changing the line

var explosion = new Explosion(this, this.enemy.x, this.enemy.y);

to

this.explosion = new Explosion(this, this.enemy.x, this.enemy.y);

it also looks like you’ve made a new js file for the explosion object. Is this added to the game properly?

Tried that but still no luck and yes I did, I referenced the js file in my index. Can’t seem to fix the error as it keeps coming up the same. Appreciate your help a lot

That’s a shame… Is there a github or a codepen where this code is, so it’s possible to see the whole thing? I think there might be an issue somewhere else, which might not be clear from the snippets in this thread.

Is the function enemyHitCallback called in the update function?

I greatly appreciate your help, the github is here:

Sorry for the mess in my code, I plan to fix after I have fixed this issue.

Once again thanks.

Hi,
I got it to work.
First, i moved functions enemyHitCallback, playerHitCallback, enemyFire outside of the update loop and make them methods instead.
And the error come from enemyHitCallback, when you instantiate a class with
let explosion = new Explosion(this, this.enemy.body.x, this.enemy.body.y);
you need to know what ‘this’ refers to, i changed this -> this.scene.
let explosion = new Explosion(this.scene, this.enemy.body.x, this.enemy.body.y);
Hope this helps :wink:

the entire Entity.js here:

Summary
class Enemy extends Phaser.Physics.Arcade.Sprite {
    constructor(scene, x, y, key, type) {
        super(scene, x, y, key, type);
        this.scene = scene;
        this.x = x;
        this.y = y;

        this.enemy = this.scene.physics.add.sprite(x, y, 'player2', 'tank1');
        this.enemy.setOrigin(0.5, 0.5);
        this.enemy.body.immovable = false;
        this.enemy.body.collideWorldBounds = true;
        this.enemy.body.bounce.setTo(1, 1);
        this.enemy.health = 3;
        this.enemy.alive = true;
        this.enemy.lastFired = 0;

        this.turret = this.scene.add.image(x, y, 'player2', 'turret');
        this.turret.setOrigin(0.3, 0.5);


        this.shadow = this.scene.add.image(x, y, 'player2', 'shadow');
        this.shadow.setOrigin(0.5, 0.5);
        this.shadow.setAlpha(0.7);

        this.scene.add.existing(this);
        this.scene.physics.add.existing(this);
        this.scene.events.on('update', this.update, this);

    }
    update(time, delta) {



        this.turret.x = this.enemy.x;
        this.turret.y = this.enemy.y;

        this.shadow.x = this.enemy.x;
        this.shadow.y = this.enemy.y;

        this.enemy.setVelocityX(100);

        this.scene.physics.world.collide(this.enemy, player);
        this.scene.physics.world.collide(this.enemy, playerBullets, this.enemyHitCallback, null, this);
        this.scene.physics.world.collide(player, enemyBullets, this.playerHitCallback, null, this);

        this.turret.rotation = Phaser.Math.Angle.Between(this.turret.x, this.turret.y, player.x, player.y);






        this.enemyFire(this.enemy, player, time, this);




    }

    enemyFire(enemy, player, time) {
        if (enemy.active === false) {
            return;
        }

        if ((time - enemy.lastFired) > 2100) {
            enemy.lastFired = time;

            var bullez = enemyBullets.get().setActive(true).setVisible(true);

            if (bullez) {
                bullez.fire(enemy, player);
            }

        }
    }

    //playerhit function
    playerHitCallback(playerHit, bulletHit) {
        if (bulletHit.active === true && playerHit.active === true) {
            playerHit.health = playerHit.health - 1;
            console.log('player hp', playerHit.health);

            if (playerHit.health <= 0) {

                player.setActive(false).setVisible(false);
                playerturret.setActive(false).setVisible(false);
                playershadow.setActive(false).setVisible(false);
                //this.anims.play('kaboom');            

            }
            bulletHit.setActive(false).setVisible(false);
        }

    }

    enemyHitCallback(enemyHit, bulletHit) {
        console.log(enemyHit, bulletHit, this) // <-- console.log this to know what this refers to(this -> Enemy)
        // Reduce health of enemy
        if (bulletHit.active === true && enemyHit.active === true) {
            enemyHit.health = enemyHit.health - 1;
            console.log("Enemy hp: ", enemyHit.health);

            // Kill enemy if health <= 0
            if (enemyHit.health <= 0) {
                let explosion = new Explosion(this.scene, this.enemy.body.x, this.enemy.body.y); // changed this to this.scene
                this.enemy.setActive(false).setVisible(false);
                this.turret.setActive(false).setVisible(false);
                this.shadow.setActive(false).setVisible(false);

            }


            // Destroy bullet
            bulletHit.setActive(false).setVisible(false);
        }

    }

}


var Bullet = new Phaser.Class({
    Extends: Phaser.GameObjects.Image,

    initialize:

        function Bullet(scene) {
            Phaser.GameObjects.Image.call(this, scene, 0, 0, 'bullet');

            this.speed = 0.5;
            this.born = 0;
            this.direction = 0;
            this.xSpeed = 0;
            this.ySpeed = 0;
            this.setSize(12, 12, true);
            this.setScale(0.04);
        },
    fire: function (playerturret, target) {
        this.setPosition(playerturret.x, playerturret.y);
        this.direction = Math.atan((target.x - this.x) / (target.y - this.y))
        if (target.y >= this.y) {
            this.xSpeed = this.speed * Math.sin(this.direction);
            this.ySpeed = this.speed * Math.cos(this.direction);
        } else {
            this.xSpeed = -this.speed * Math.sin(this.direction);
            this.ySpeed = -this.speed * Math.cos(this.direction);
        }
        this.rotation = playerturret.rotation;
        this.born = 0;
        //console.log(this.xSpeed, this.ySpeed);
    },

    update: function (time, delta) {
        this.x += this.xSpeed * delta;
        this.y += this.ySpeed * delta;
        this.born += delta;
        if (this.born > 1200) {
            this.setActive(false);
            this.setVisible(false);
        }
    }
});


class Explosion extends Phaser.Physics.Arcade.Sprite {
    constructor(scene, x, y, texture) {
        super(scene, x, y, texture = 'explosive');
        scene.add.existing(this);
        this.play('kaboom');
    }
}
1 Like

THANK you so much. I am greatly relieved and much grateful for your time to look at my code.

No problem :wink:

1 Like

Hey bro, just another question, do you think you know any way I can make the enemy tanks spawn more spread out. Currently the enemy tanks are too “close together”.

Sorry for the late response, no notification…
When you create your enemies, you call new Enemy( with x and y as the position of enemies)
Try to change the way x and y are choosed