Sprite not appearing on a specific circumstance

I have this pretty weird issue that the sprite doesn’t show at all in this specific instance and is shown in any other instances. Yes, all the keys are written down as how they appear in the json file. For now this should be using the sprites seen in the image (the hearts).

create(){
       const lifesLayer = this.stage1Tilemap.getObjectLayer('lifes');
        this.lifeAppleSpawn = this.physics.add.group()
        lifesLayer.objects.forEach(obj => {
            if (obj.name === 'heartApple') {
                const heartApple = this.physics.add.sprite(obj.x, obj.y, "heart_full")
                this.heartAppleObj = this.lifeAppleSpawn.create(heartApple);
          }      
}

If you open your browser console, do you see any errors or anything?

Aside of the missing icon from the html (have to add that one) there is no error whatsoever, just this warning:
WebGL warning: texImage: Alpha-premult and y-flip are deprecated for non-DOM-Element uploads.

What’s the name of the texture that’s showing up broken? Can you show the code for the whole scene or perhaps just the preload?

One other thing is, this is part of the UI that shows your lives, right? You probably don’t want or need to use a physics group or add a sprite with physics. You could do it like this (this is just an example):

create() {
    const box = this.add.container(200, 150);

    const bg = this.add.image(0, 0, 'panel');
    const icon = this.add.image(-40, 0, 'coin');
    const character = this.add.image(40, 0, 'player');

    box.add([bg, icon, character]);
}

This adds a container with images.

Oh no, this is not for the lifes hud, it’s for obtaining more hp in-game (in the game scene) using tile object.

This would be the preloader, there’s not too much in here…


export class Preloader extends Phaser.Scene{
    constructor(){
        super({key: "preloader"})
    }
    preload(){
        this.load.pack("stage1Tiles", "assets/stage1/tiles.json")
        this.load.tilemapTiledJSON("stage1Tilemap", "leveldata/stage1.json");

        this.load.pack("sfx", "audio/sfx/sfx.json")
        this.load.pack("music", "audio/music/music.json")
        this.load.spritesheet('bomb_hoots', 'assets/player/bomb.png', {frameWidth: 16, frameHeight: 16})
        this.load.spritesheet('effects_hoots', 'assets/player/dusts.png', {frameWidth: 16, frameHeight: 16})


        this.load.spritesheet("heartHud", "assets/global/hearts.png", {frameWidth: 16, frameHeight: 16})
        this.load.spritesheet('objectHearts', 'assets/global/objects.png', {frameWidth: 16, frameHeight: 16})

        this.load.animation("globalObj", "assets/global/global.json")

        this.load.spritesheet('hoots', 'assets/player/hoots.png', {frameWidth: 16, frameHeight: 16});
        this.load.animation('hootsAnims', 'assets/player/player.json')


        this.load.image('pauseText', 'assets/global/pauseText.png')

    }
    create(){

        this.scene.launch("stage1") //the stages handle the life hud as they need to restart or be created each time you enter one (mostly restarted)
    }
}

So which key has the issue? Is it the player?

No, the issue is not with the key, the issue is with the code snippet I sent you, if I place any other key in, it won’t display, even if the key is functional

Maybe this? I don’t think you’re using the create method right. It needs coordinates and a key.

> create() {
>     const lifesLayer = this.stage1Tilemap.getObjectLayer('lifes');
> 
>     this.lifeAppleSpawn = this.physics.add.group();
> 
>     lifesLayer.objects.forEach(obj => {
>         if (obj.name === 'heartApple') {
>             this.lifeAppleSpawn.create(obj.x, obj.y, 'heart_full');
>         }
>     });
> }

Oh, I already tried using different keys and actual numbers for the coordinatesin the create method, still nothing… I would say the file format is wrong but if I make the key go anywhere else it will actually appear.

Hm… maybe an issue with Phaser itself or the server… (I use the extension “Live server” for fast testing)

Is the code base really big or can you send me the whole thing? I am a little confused as to what it is. From the image you posted, I thought we were working with the heart containers. This part here don’t look right to me:

const heartApple = this.physics.add.sprite(obj.x, obj.y, "heart_full")
this.heartAppleObj = this.lifeAppleSpawn.create(heartApple);

For one thing, that’s inside a loop, so if you’re trying to save a reference to heartAppleObj, you’re overwriting it with each iteration, know what I mean?

Hold on let me try, it’s not as big but it is <350 lines sooo

Some parts are in spanish as I tend to do both english and spanish comments, depending on what I’m doing

import { PlayerBomb } from '../player/bomb_player.js';

import { Player } from '../player/player.js';




export class Stage1 extends Phaser.Scene{

    constructor(){

        super({key: "stage1"})

    }

    init(){

        this.skiddSound

        this.jumpSound

        this.activeStomp = false

        this.playerBombOnScreen = false

        this.sprintDustRepos = true

        this.hpCheck = 3

        this.stageName = "stage1"

        this.gameOver = false

    }

    create(){

        this.cursors = this.input.keyboard.createCursorKeys();

        this.keyS = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.S);

        this.keyD = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.D);

        this.keyA = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.A);

        this.keyW = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.W);

        this.keySPACEBAR = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE);




        this.keyE = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.E);

        this.keyZ = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.Z);

        this.key1 = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.ONE);

        this.key2 = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.TWO);






        this.input.keyboard.on('keydown-ENTER', () =>

        {

                if(!this.player.charstateDead){

                    console.log('Pausing game...')

                    /*this.scene.launch('pause', {

                        score: this.score,

                        bombLoad: this.bombsThatShouldSpawn,

                        level: this.level,

                        stageName: this.stageName,

                    })*/

                    this.scene.pause('stage1')

                    this.scene.launch("pause", {

                        stageName: this.stageName

                    })

                }

                else{

                    console.log("You can't pause the game right now...")

                }

        });




        //sounds

        this.jumpSound = this.sound.add('jump')

        this.skiddSound = this.sound.add('skidd')

        this.activeStomp = this.sound.add('stomp_activate')

        this.sound.add("hurt")

        this.pullOutSound = this.sound.add("pullOut")

        this.throwSound = this.sound.add("throw")

        this.sprintSound = this.sound.add("sprint")

        this.walkSound = this.sound.add("walk")

        this.gameOverJingle = this.sound.add("gameOver")




        this.explosionSound = this.sound.add("explosion1")

        this.wallBreakSound = this.sound.add("wallBreak")

        /*

        const controlConfig = {

            camera: this.cameras.main,

            left: cursors.left,

            right: cursors.right,

            up: cursors.up,

            down: cursors.down,

            acceleration: 1.0,

            drag: 0.0005,

            maxSpeed: 0.0008

        };

        */




        //this.controls = new Phaser.Cameras.Controls.SmoothedKeyControl(controlConfig)




        this.stage1Tilemap = this.add.tilemap('stage1Tilemap');




        const floorTile = this.stage1Tilemap.addTilesetImage("floor", "floor");

        const BCTile = this.stage1Tilemap.addTilesetImage("floor", "floor");

        const breakableWallTile = this.stage1Tilemap.addTilesetImage("breakableWall", "breakableWall");

        const spikeTile = this.stage1Tilemap.addTilesetImage("spike", "spike");





        const spawnPoint = this.stage1Tilemap.findObject("playerSpawn", obj => obj.name === "playerSpawn")




        




        const BCLayer = this.stage1Tilemap.createLayer("BackgroundDeco", BCTile)

        this.breakableWallLayer = this.stage1Tilemap.createLayer("breakableWall", breakableWallTile)

        const spikesLayer = this.stage1Tilemap.createLayer("spike", spikeTile);

        const floorLayer = this.stage1Tilemap.createLayer("platforms", floorTile)




        this.player = new Player(this, spawnPoint.x, spawnPoint.y);

        this.playerBomb = new PlayerBomb(this, 0, 0);

        this.playerBomb.anims.play("bomb", true).setVisible(false)

        

        // Activa colisión en todos los tiles excepto el vacío

        floorLayer.setCollisionByExclusion([-1]);

        spikesLayer.setCollisionByExclusion([-1]);

        this.breakableWallLayer.setCollisionByExclusion([-1]);

        // Convierte la capa en cuerpos físicos

        this.physics.add.collider(this.player, floorLayer);

        this.physics.add.collider(this.player, spikesLayer, (layer, tile) =>{

            if((!this.player.upStun && !this.player.invAfterHit) && (this.player.body.onFloor() || !this.player.body.onFloor())){

                this.player.upStun = true

                let hp = this.registry.get('hp');

                this.registry.set('hp', (hp - 1));

                let hpChecking = this.registry.get('hp');

                this.hpCheck = hpChecking

                this.player.invAfterHit = true

                this.sound.play("hurt")

                this.gameOverHandler()

            };

            

        });




        

        this.physics.add.collider(this.player, this.breakableWallLayer, this.hitTilePlayer, null, this)




        this.physics.add.collider(this.playerBomb, floorLayer)

        this.physics.add.collider(this.playerBomb, spikesLayer)

        this.physics.add.collider(this.playerBomb, this.breakableWallLayer, this.hitTile, null, this)




        //disc obj.

        this.disc = this.stage1Tilemap.createFromObjects("disc", {

            gid: 7,

            key:"disc1"

        })




        //camera

        this.cameras.main.startFollow(this.player, false, 0.5, 0.5);

        





        //effects

        this.effects = this.physics.add.group()




        this.runDust = this.effects.create(0, 0, "sprintDust").setVisible(false)





        //life stuff

        this.scene.launch("lifeSystem")




        this.registry.set('gotHit', false);




    

        const lifesLayer = this.stage1Tilemap.getObjectLayer('lifes');

        this.lifeAppleSpawn = this.physics.add.group()




        

        lifesLayer.objects.forEach(obj => {

            if (obj.name === 'heartApple') {

                const heartAppleConst = this.physics.add.sprite(obj.x, obj.y, "heart_full")

                this.heartApple = this.lifeAppleSpawn.create(heartAppleConst);

                this.heartApple.anims.play("heart_full", true)

                

            }

        });

        

    };

    update(/*delta*/){

        

        if(this.gameOver){

            this.physics.pause()

        }




        const camLock1 = this.stage1Tilemap.findObject("cameraLock", obj => obj.name === "camStart")

            const camLockBoss = this.stage1Tilemap.findObject("cameraLock", obj => obj.name === "camBoss")

            const camLock2 = this.stage1Tilemap.findObject("camlock2", obj => obj.name === "camFinish")

            //camera rebounding

            if(this.player.x < 110){

                this.cameras.main.setBounds(0, camLock1.y, camLock2.x, camLock2.y)

            }

            else if (this.player.x > 110 && !this.bossLockCamera){

                this.cameras.main.setBounds(camLock1.x, camLock1.y, camLock2.x, camLock2.y)

            }

            else if(this.player.x == (camLockBoss.x + 96) || this.bossLockCamera){

                this.cameras.main.setBounds(camLockBoss.x, camLockBoss.y, camLock2.x, camLock2.y)

                this.bossLockCamera = true

        }




        if((this.hpCheck == 0 || this.player.y > camLock2.y + 32) && !this.gameOver){

            this.registry.set('hp', (0));

            this.gameOverHandler()

            this.gameOver = true

            console.log("game over bish")

        }

        this.player.update(this.cursors, this.keyA, this.keyS, this.keyD, this.keyW, this.keySPACEBAR, this.key2, this.skiddSound, this.jumpSound, this.activeStomp, this.gameOver, this.time, this.walkSound, this.sprintSound, this.sprintDustRepos, this.registry);




        if(!this.gameOver){




            //effects




            if(this.sprintDustRepos && this.player.walkSoundPlay && this.player.charstateRun && this.player.body.onFloor() && !this.player.body.blocked.left && !this.player.body.blocked.right){

                this.sprintDustRepos = false

                var substractPos = 0

                if(this.player.facingLeft){

                    this.runDust.setFlipX(true)

                    substractPos = 16

                }

                else if(this.player.facingRight){

                    this.runDust.setFlipX(false)

                    substractPos = -16

                }




                this.runDust.setPosition(this.player.x + substractPos, this.player.y)

                this.runDust.anims.play("sprintDust", true).setVisible(true)

                this.time.delayedCall(100, ()=>{

                                

                    this.sprintDustRepos = true

                })

                

                

            }

            //bombUpdate

            this.playerBomb.update(this.time, this.forcedExplode, this.explosionSound)

            //96

            

            

            this.cameraView = this.cameras.main.worldView

            

            

            if (!this.cameraView.contains(this.playerBomb.x, this.playerBomb.y) && this.playerBombOnScreen == true){

                this.playerBombOnScreen = false

                this.time.delayedCall(500, ()=>{

                    if (!this.cameraView.contains(this.playerBomb.x, this.playerBomb.y)){

                        this.playerBomb.setVisible(false).setVelocityX(0).setVelocityY(0).setGravityY(0)

                        this.abilityCooldown = false

                    }

                    else{

                        this.playerBombOnScreen = true

                    }

                })

            }

                //this.controls.update(delta)




            if(this.keyA.isDown && !this.cursors.down.isDown && !this.player.abilityCooldown && this.playerBomb.bombExploded){




                this.pullOutSound.play()

                this.explosionSound.stop()

                this.forcedExplode = false

                this.playerBomb.setVelocityX(0).setVisible(true).anims.play("bomb", true)

                this.playerBombOnScreen = true

                this.player.charstateThrowing = true

                this.bombExploded = false

                this.bombReposition = true

                this.playerBomb.x = this.player.x

                this.playerBomb.y = this.player.y - 16

                this.time.delayedCall(100, ()=>{




                    this.throwSound.play()

                    if(!this.player.body.onFloor()){

                        this.player.charstateThrowing = false

                    }

                    

                    this.playerBomb.body.setGravityY(600);

                    if(!this.player.charstateRun){

                        if(this.player.facingLeft){

                            this.playerBomb.setVelocityX(-200)

                        }

                        else if(this.player.facingRight){

                            this.playerBomb.setVelocityX(200)

                        }

                    }

                    else if(this.player.charstateRun){

                        if(this.player.facingLeft){

                            this.playerBomb.setVelocityX(-300)

                        }

                        else if(this.player.facingRight){

                            this.playerBomb.setVelocityX(300)

                        }

                        

                    }

                    if(!this.player.body.onFloor()){

                            this.player.coyoteTime = true

                    }

                    this.time.delayedCall(200, ()=>{

                        this.player.charstateThrowing = false

                    })

                })

                

            }




            if(this.playerBombOnScreen && this.playerBomb.visible){

                this.player.abilityCooldown = true

            }

            else if ((!this.playerBombOnScreen && !this.playerBomb.visible) || !this.playerBomb.visible){

                this.player.abilityCooldown = false

                //this.playerBomb.bombExploded = false

                

            }




            if(this.playerBomb.bombExploded.visible && this.playerBomb.bombExploded){

                this.playerBomb.setVisible(false)

            }




            if(this.playerBomb.body.velocity.x == 0){

                this.playerBomb.setVelocityY(0)

                this.playerBomb.body.setGravityY(0);

            }






            if(this.player.abilityCooldown){

                console.log("cooldown")

            }





            //sound manager

            

            if(this.throwSound.isPlaying && this.pullOutSound.isPlaying){

                this.pullOutSound.stop()

            }

            if(this.jumpSound.isPlaying && this.throwSound.isPlaying){

                this.throwSound.stop()

            }

        }

        

    }

    hitTile(playerBomb, tile) {

        if(this.playerBombOnScreen){

            this.forcedExplode = true

            // Remove the tile

            this.breakableWallLayer.removeTileAt(tile.x, tile.y);




            // Destroy the tile object itself to free memory

            tile.destroy(); 




            console.log("Tile destroyed at: " + tile.x + ", " + tile.y);




            if(this.explosionSound.isPlaying){

                this.explosionSound.stop()

            }

            if(!this.wallBreakSound.isPlaying){

                this.wallBreakSound.play()

            }

        }

    }

    hitTilePlayer(player, tile) {

        if(this.player.charstateAbility && this.player.body.onFloor()){

            // Remove the tile

            this.breakableWallLayer.removeTileAt(tile.x, tile.y);




            // Destroy the tile object itself to free memory

            tile.destroy(); 




            console.log("Tile destroyed at: " + tile.x + ", " + tile.y);

        

            if(this.explosionSound.isPlaying){

                this.explosionSound.stop()

            }

            if(!this.wallBreakSound.isPlaying){

                this.wallBreakSound.play()

            }

        }

    }




    gameOverHandler(){

    

        let hp = this.registry.get('hp');

        if(hp == 0){

            this.time.delayedCall (200, ()=>{

                this.gameOverJingle.play()

                this.time.delayedCall (1000, ()=>{//this is strictly for the jingle coherence

                    

                    this.scene.stop("lifeSystem")

                    this.cameras.main.fadeOut(0, 0, 0, 0x000)

                    this.time.delayedCall (2500, ()=>{

                        this.scene.restart("stage1")

                    })

                })

            })




        }

    }

}

If you can, open the browser’s debugger, search for the line

return this.list['__MISSING'];

in phaser.js or similar, put a breakpoint there, run your game with the debugger open, then look at the stack trace where it breaks.

phaser.js can also be phaser.min.js, right?

Yes. It may be a little hard to work through minified code in the debugger, though.

Indeed, I am literally scrolling trough one line to find the return :face_with_bags_under_eyes:

You can switch to phaser.js during development. Just make sure the Phaser versions match.

what’s the difference?

phaser.min.js has no comments (documentation) and the code is squished to be as small as possible. So it’s hard to read or step through in the debugger.

I see, also, I tried looking for the line inside Visual Studio, as I has some doubts and it seems that the line does not exist whatsoever

Possible it’s this.list.__MISSING in the minified one.