Jump to content

Importing Image in Phaser with ES6


Joetan83
 Share

Recommended Posts

Hi everyone,

I am currently using Phaser,io with ES6 syntax , gulp, babelify, browserify and browsersync that is something similar to the ES6 boilerplate but I am using my own gulp file.

I am encountering a bug where I import an image there is a green square behind it and there is a warning of "Phaser.Cache.getImage: Key "player" not found in Cache." on the Chrome browser debug tool show on the attached image. 

I have a GameState.js file as so:

import Player from "../objects/Player";


class GameState extends Phaser.State {
    constructor(){
        super();

    }
    preload(){
      
        let lander = new Player(this.game,0, 0);
        lander.loadImage();
    }
    create() {
        let lander = new Player(this.game,0,0);
        lander.setSprite();

    }

}

export default GameState;

I am importing the image from the Player.js file:

import {Images} from "../global";
class Player extends Phaser.Image {

    constructor(game, x, y, key,frame){
        super(game, x, y, key, frame);
        this.loadImage();
        this.setSprite();
    }

    loadImage(){
        this.game.load.image("player", Images.lander);
    }

    setSprite(){
        this.game.add.sprite(10,10,"player");
    }

}

export default Player;

the global.js file contains variables like so:

var gameScreen = {
    Width: window.innerWidth,
    Height: window.innerHeight
};

var Images = {
    lander: '/images/player.png'
};


export {gameScreen, Images};

Is there anyway to fix this bug?

Thanks

 

 

ball-bug.jpg

Link to comment
Share on other sites

That's not how the Phaser Loader works. You're assuming the file is available instantly after asking it to load, and trying to set it right away. But in reality all you've done is add a single file to the load queue, and not started the queue off, and the code isn't listening for its complete signal or similar before trying to use it, so by the time setSprite is called, the file still won't have been loaded, even if the Loader had been started.

Files should be loaded as a batch, not on a per Sprite basis, ideally in a Preloader state, so they're available in the Cache. Your Sprites should then pull the images they require from the Cache, not the Loader.

I'm also not sure why your Player extends Phaser.Image, and then goes and creates a brand new Sprite on the display list anyway (in setSprite). You've now effectively got 2 Sprites for your Player.

Link to comment
Share on other sites

Hi Rich,

Thank you for your reply.

Well for the Player extends Phaser.Image I was trying to keep all of the player assets and coded attributes in a separate file called Player.js as seen on the example of Daneil's Belohlavek boilerplate template on the link in the first post. His RainbowText extends Phaser.Text is a very good example for keeping RainbowText codded attributes in its own module and imported into the GameState module.

I've seen other examples that uses ES6 to import images but they all involved loading images into GameState.js, not very good way of making efficient use of ES6 plus there are hundereds of lines of code within GameState file itself. 

What you have stated out the way Phaser imports images my guess it is the limits of the Phaser itself ( I could be wrong as I am still a beginner using Phaser). 

Don't get me wrong, I really appreciated what you have done for Phaser and its a very good HTML5 game framework, but I am putting up my own standards as I am a front-end developer by profession.  

Still I have manage to fix my own problem from what I gather from you reply but it isn't entirely the answer seek.

Its just a different way to import an image into Phaser's GameState with ES6.

I have changed the GameState.js to be this:

import {Images} from "../global";
import GetImages from "../objects/GetImages";

class GameState extends Phaser.State {
    constructor(){
        super();

    }
    preload(){
            let image = new GetImages(this.game,0,0);
            image.loadImage("player", Images.lander);

    }
    create() {

        let player = this.game.add.sprite(1,1,"player");         

    }

}

export default GameState;

The Player.js is changed to GetImages.js

class GetImages extends Phaser.Image {

    constructor(game, x, y, key,frame){
        super(game, x, y, key, frame);

    }

    loadImage(key,frame){
        this.game.load.image(key, frame);
    }

}

export default GetImages;

the code in global.js is the same.

I am still open to suggestions on how to keep things modular if the HTML5 game dev community has any?

 

import-image-fix.jpg

Link to comment
Share on other sites

It's not very clear from your last post whether you managed to load your image or not. If not, it's probably because you never reached the GameState state. Did you checked whether its preload() and create() functions are executed?

By the way, there's nothing in Phaser keeping you from use whatever well structured or modular code style. I'm not using ES6 but requirejs modules and though I had to spend some time figuring out how Phaser works and how to using in my own style it was not difficult at all. I have a module for each state (init, preload, menu, play, etc,.) plus some others which help to process a high ammount of confiiguration data.

I'm not saying Phaser has no bugs, but nothing as basic as you are describing. My guess is that you are doing something wrong which we'll gladly help you to fix if you provide more details.

Link to comment
Share on other sites

Hi Glantucan,

Thank you for your post.

I have manage to fix it but not exactly the way I wanted it.

Ideally I would like the snippet below: 

this.game.load.image("player", Images.lander);

on its own file as Player.js and imported into the GameState.js. A good example would be from RainbowText.js  which is placed into the GameState.js of the ES6 boilerplate.

ES6 has a distinct pattern which needs to be followed in order for it to work with Phaser.io and I am just asking if anyone here has done it in ES6.

I could stick to ES5 with gulp + browserify which works in a similar way as require.js however it defeats the purpose. 

That's all the code I've pasted on my recent post as workable on Chrome browser.

Link to comment
Share on other sites

The issue isn't the use of ES6, it's a lack of understanding how the Phaser Loader and States work, which is understandable because like you said, you only just started with it.

The Loader uses a parallel load queue, automatically populated and started by preload methods in a State. Alternatively you can populate the Loader queue yourself, and then start the load process going. As long as you listen for the Signals that are dispatched on completion you can then use those assets, but not before, as they're not yet loaded. You would never do this on a per object basis: i.e. having every game object (Player, baddies, etc) actually invoke the loader, add an image, start that going, wait for the signal then create themselves, is insanity I'm afraid.

What you could do is have all of your objects add the files they need to the Loader, and once you've created all of those objects, you then start the Loader going. At least this way you benefit from parallel loads, and decreased drain on the browser.

I take issue with "ES6 has a distinct pattern which needs to be followed". It really doesn't. This is just one you're choosing to implement. There are many others.

Link to comment
Share on other sites

12 hours ago, rich said:

You would never do this on a per object basis: i.e. having every game object (Player, baddies, etc) actually invoke the loader, add an image, start that going, wait for the signal then create themselves, is insanity I'm afraid.

What you could do is have all of your objects add the files they need to the Loader, and once you've created all of those objects, you then start the Loader going. At least this way you benefit from parallel loads, and decreased drain on the browser.

Ah okay I got it.

12 hours ago, rich said:

I take issue with "ES6 has a distinct pattern which needs to be followed". It really doesn't. This is just one you're choosing to implement. There are many others.

Correct its one way I am choosing to implement as I have my own coding style and the industry representation itself.

Well as they all say if you can't make something perfect, have to make something workable. I'll make use of what you suggest and finish the game.

Thanks again for your comments. 

Link to comment
Share on other sites

Just in case it is usefull to you or anyone.

What I usually do is to have just one PreloadState to do all the loading for every level or menu in the game.

Every level or menu is a state itself which, on the init() function, overwrites the preload() function of the PreloadState.

Then I change to the PreloadState passing it the current state as a parameter so it does know what state to go back after al the loading is finished.

That way I get to say what every state (be a class or a module) needs to load in the state init() function. And to have al preloading animations, loading or parsing error checking in the PreloadState, which is also a class or a module. 

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...