Jump to content

Boot/Preloader State based setup


Recommended Posts

I just spent a while trying to restructure my current game to work around this example by Rich ( http://www.html5gamedevs.com/topic/1198-downscaling/?p=7567 ) and it seems to be functioning properly for the most part besides a couple things I'm hoping I could have some guidance in fixing.


Heres my HTML java code:

<script type="text/javascript">function boot() {var game = new Phaser.Game(480, 320);game.state.add('boot', Main.Boot,true);game.state.add('preloader', Main.Preloader);game.state.add('mainMenu', Main.MainMenu);game.state.add('game', Main.Game);}window.onload = function () {boot();}</script>

And my Boot.js looks like this:

var Main = {};Main.Boot = function (game) {this.game = game;};Main.Boot.prototype = {preload: function () {//***this.stage.scaleMode = Phaser.StageScaleMode.SHOW_ALL;this.game.stage.disableVisibilityChange = true;this.game.stage.disablePauseScreen = true;this.game.stage.scale.minWidth = 480;this.game.stage.scale.minHeight = 320;this.game.stage.scale.maxWidth = 960;this.game.stage.scale.maxHeight = 640;this.game.stage.scale.pageAlignHorizontally = true;if (this.game.device.android && this.game.device.chrome == false) {this.game.stage.scaleMode = Phaser.StageScaleMode.EXACT_FIT;this.game.stage.scale.maxIterations = 1;}//***this.load.image('loaderFull', 'assets/UI/loaderFull.png');this.load.image('loaderEmpty', 'assets/UI/loaderEmpty.png');},create: function () {// this.game.stage.enableOrientationCheck(true, false, 'orientation');this.game.state.start('preloader',Main.Preloader);},}

Between the asterisks seems like it belongs in the constructor, but when it's put there I'll get an error to this effect: "Cannot set property 'scaleMode' of undefined " so I just put it in the preload and it seems(?) like it's doing fine being there.

In the Preloader state comes my first minor problem with cropping the rectangles for my loading bar.
Main.Preloader = function (game) {    this.game = game;};Main.Preloader.prototype = {    loaderFull: Phaser.Sprite,    loaderEmpty: Phaser.Sprite,    test:Phaser.Sprite,    preload: function () {        this.loaderEmpty = this.add.sprite(135, 285, 'loaderEmpty');        this.loaderEmpty.crop = new Phaser.Rectangle(0, 0, this.loaderEmpty.width, this.loaderEmpty.height);        this.loaderEmpty.name = 'loaderEmpty';        this.loaderFull = this.add.sprite(135, 285, 'loaderFull');        this.loaderFull.crop = new Phaser.Rectangle(0, 0, 0, this.loaderFull.height);        this.loaderFull.name = 'loaderFull';        //........        //lots of asset loading here        //........        this.load.onFileComplete.add(this.fileLoaded, this);    },    create: function () {                this.game.state.start('mainMenu', Main.MainMenu);    },    fileLoaded: function (progress) {       // console.log(this.loaderFull.crop.width);        this.loaderEmpty.crop.left = (135 / 100) * progress;        this.loaderFull.crop.width = (135 / 100) * progress;    }}

The fileLoaded function works as intended in terms of data, but all I see is an empty loading bar which I have a feeling has to do with rectangles as I've ran into problems getting them to show up before.


The real problem comes after the mainMenu when I start the game and try to create Class sprite instances.  In the create function of my game state, I'm trying to make instances like this:

create: function () {for (var i = 0; i < 2; i++) {            pow = new Main.PowerUp(game, 0, 0, 'powerUps');            pow.name = 'PowerUp: ' + i;            pow.exists = false;            pow.visible = false;           // pow.events.onOutOfBounds.add(spriteOut, this);            gPower.add(pow);        }}

And my Class looks like this:

Main.PowerUp = function (game, x, y) {   Phaser.Sprite.call(this, this.game, x, y, 'powerUps');   this.anchor.setTo(0.5, 0.5);   this.body.setSize(15, 15);   this.takePowerUp = false;   //hacky :X    this.update = function () {        this.angle--;    }};Main.PowerUp.prototype = Phaser.Utils.extend(true, Phaser.Sprite.prototype, PIXI.Sprite.prototype);Main.PowerUp.prototype.constructor = Main.PowerUp;

Which when I try to run will give me this error: "Cannot read property 'cache' of undefined" relating to trying to call or create the sprite.  It works fine with regular sprites, just not with the classes I'm using.


I appreciate any help.  I've been learning a tremendous amount just playing around with Phaser, but it's getting these initial setups right that give me trouble.  :(
Link to comment
Share on other sites

Aah yesyes, thank you!  Don't think I would have realized that.


In addition to that, I had forgotten to change 

pow = new Main.PowerUp(game, 0, 0, 'powerUps');


pow = new Main.PowerUp(this.game, 0, 0, 'powerUps');

and now classes work.


That just leaves the small issue in the preloader with the loading bar rectangles not working.


Additionally I noticed during the preloader screen the game doesn't scale or align untill after the preloading is finished, which I assume is because I moved all the scaling code from the Boot constructor to the Boot preloader since I couldn't get it to work otherwise.

Link to comment
Share on other sites



I would move the stage / scale stuff to the create function in your Boot class.


Also you can now do this for a super-easy preload bar:

this.preloadBar = this.add.sprite(356, 370, 'preloaderBar');this.load.setPreloadSprite(this.preloadBar);

Do the above in the preload function of your Preloader. The sprite is automatically cropped for you based on the % of the load progress :)

Link to comment
Share on other sites

Hmm, after I upgraded to 1.0.5 (also 1.0.6) the preloader stopped working.  The bar will just fill all the way if it's loading only audio or images, and it will fill like 95% of the way if it's loading both audio and images and doesn't throw any errors.  As long as nothing is actually being loaded in the preloader it gets past it just fine, but then obviously leaves all my assets to be loaded in the game.


This is the preloader currently:

Main.Preloader = function (game) {    this.game = game;};Main.Preloader.prototype = {    loaderEmpty: Phaser.Sprite,    preload: function () {        this.load.spritesheet('cloud', 'assets/sprite/cloudAni.png', 73, 53, 30);        //****load lots of image/audio assets****        this.loaderEmpty = this.add.sprite(this.game.world.centerX, 285, 'loaderEmpty');        this.preloadBar = this.add.sprite(this.loaderEmpty.x - this.loaderEmpty.width/2, 285, 'loaderFull');        this.loaderEmpty.anchor.setTo(0.5, 0);        this.load.setPreloadSprite(this.preloadBar);            },    create: function () {               this.game.state.start('mainMenu', Main.MainMenu);    },}
Link to comment
Share on other sites

I've pretty much copied Yoras setup (using v1.0.0), but I can't get farther then the Main.Preloader preloader.

[EDIT] Trying to use setPreloadSprite with phaser-min.js results in "TypeError: this.game.load.setPreloadSprite is not a function", though the function is present at least in build/phaser.js. If I use phaser.js instead I get "IndexSizeError: Index or size is negative or greater than the allowed amount" for "frame.height);" on line 3000 of phaser.js. [/EDIT]

But even when I just load some sprites in the preloader the create function will not be called. The create will only be called if I load nothing at all in the preload function. What am I doing wrong? :blink:


Here is my preloader.js:

Main.Preloader = function (game) {    this.game = game;};Main.Preloader.prototype = {        loaderFull: Phaser.Sprite,    loaderEmpty: Phaser.Sprite,        preload: function () {        console.log("Main.Preloader.preload");                this.loaderEmpty = this.game.add.sprite(this.game.world.centerX, 285, 'loaderEmpty');        this.preloadBar = this.game.add.sprite(this.loaderEmpty.x - this.loaderEmpty.width/2, 285, 'loaderFull');        this.loaderEmpty.anchor.setTo(0.5, 0);        this.game.load.setPreloadSprite(this.preloadBar);        // Load actual stuff            this.game.load.spritesheet('tilemarkups', 'assets/interface/tilemarkups.png', 24, 24);            this.game.load.spritesheet('player', 'assets/sprites/player.png', 24, 24);        this.game.load.spritesheet('rat', 'assets/sprites/rat.png', 24, 24);        this.game.load.spritesheet('effects1', 'assets/sprites/effects1.png', 24, 24);        this.game.load.tilemap('level0', 'assets/sprites/tileset1.png', 'assets/maps/level0.json', null, Phaser.Tilemap.JSON);    },        create: function () {        console.log("Main.Preloader.create");        this.game.state.start('mainMenu', Main.MainMenu);    }};
Link to comment
Share on other sites

Yeah I know what that is - it's the way Pixi copes with crop rects that aren't using rounded-up values. For the time being just remove the setPreloadSprite call and it'll work fine.


Edit: I need to fix this for the client game I'm building at the moment, so it will be done very soon :)

Link to comment
Share on other sites

Good idea x).


I actually just now jumped into IE and firefox to try out my project and ran into a few different problems that I didn't in Chrome and I'm wondering if it's relevant to this at all, or if not just what the problem might be 0.o.


Btw all my sound files are .ogg.


1. IE isn't loading sound at all, throwing me this for each sound file: "Phaser.Loader error loading file: music" (game runs really damn smooth in IE though 0.0)


2. Music looping on FireFox isn't seamless, theres a small delay after it ends before looping.  In Chrome the loops continue seamlessly.


3. FireFox doesn't seem to allow more than one sound to play at the same time like Chrome does (Rapid fire sound effects cut each other off instead of overlapping, or even a separate sprite's sound not playing during another sound).  I'm using a pretty weird setup that maybe I shouldn't be in the first place to have sound overlapping working in Chrome though:

if (ssf2.isPlaying) {            ssf3.play('', 0, 0.5);            ssf.stop();            ssf2.stop();        } else            if (ssf.isPlaying) {                ssf2.play('', 0, 0.5);            } else {                ssf.play('', 0, 0.5);                ssf3.stop();            }

They're all the same sound file, but if one is busy playing another will take its place.  By the time I would need a 4th I have the earlier ones stop towards the end of their duration anyways to make sure they can play again.

4. Not a big deal, but IE doesn't seem to show change when an objects alpha is greater than 1 (which I use for a 'brighter' effect on the sprite).
Link to comment
Share on other sites

I just tried changing the .ogg's to .wav's or .mp3s for IE but it still threw me the same error. :(


I tried a few different ways but currently I'm loading my audio like this in the preloader following an example:

this.load.audio('music', ['assets/audio/music2.wav','assets/audio/music2.ogg']);

(speaking of which, does this automatically play the ogg if it's in Firefox and the wav otherwise or something?)


As for Firefox, that being the case I guess I'll just disable the music and remove/shorten some of the sounds for now if Firefox is being used.


And yeah I thought the alpha thing was weird when I tried it and it worked so I've been using it as a brightening effect, but if that's the case I guess I should look for a different way to get this effect.  :lol:

Link to comment
Share on other sites

mp3s work fine in IE. I just tried the 'music' example in the examples folder on IE10 and it was fine. It doesn't work unless the browser is in IE10 mode, so if you've got an old html tag forcing it into a pre IE9 document mode then it won't load.


Firefox works with ogg! What you should really do is combine your audio into a sound sprite, then use this for firefox/IE and use the "addMarker" function to set-up the fx and clips within the track.

Link to comment
Share on other sites

Aaaha yes thank you, I made a silly when I tested an mp3 in IE and forgot the mp3 version was named 'music' not 'music2' so it works in IE now, x)


I'm trying to figure out how to do your suggestion properly, but I'm a little clueless.  :lol:


Here's my current incorrect guess:

soundTest = this.add.audio('starFire');        soundTest = this.add.audio('music');        //soundTest = this.add.audio('shot');        soundTest.addMarker('fun', 0, 1000, 0.5, false);        soundTest.play('fun',0,0.5,false);

(I don't know what would constitute a 'sound sprite')

Link to comment
Share on other sites

Basically a sound sprite is one long mp3/ogg that contains lots of different shorter effects and bits of music, with at least 1 second of silence between them all. So say you've got an explosion sound from 2.0 seconds to 2.5 seconds and a piece of music from 4 seconds to 8.9 seconds, you'd so:

sound.addMarker('boom', 2.0, 2.5, 1, false);sound.addMarker('triphop', 4.0, 8.9, 1, false);

Then you just play it giving the marker string:

Link to comment
Share on other sites

Aah okay I get it now.  I have my audio file with all my sounds in it now and the markers are working properly.  Though to my current understanding, doing it like this still leaves me only to play 1 sound at a time, unless I'm supposed to be using couple different Game.sound instances (one for music, one for all the sounds)?  Otherwise in IE/Firefox since my music is playing on loop no other sounds will play off a marker of the same Sound object.


I'm still having trouble with a delay in the loop of my music section in IE/Firefox (which lasts roughly 10 seconds) though I'm still playing around with the markers now that I know how to use them.  Here's what the setup looks like:

allSound = this.add.audio('allSound');        allSound.addMarker('music', 0.07, 10.06, 0.2, true);        allSound.addMarker('starFire', 12.6, 13, 0.2, false);        allSound.addMarker('test', 6.00, 10.06, 0.2, false);        allSound.addMarker('test2', 0.07, 6.00, 0.2, false);
Link to comment
Share on other sites

Yes always round the starting position to the nearest second if you can. I also tend to add 2-3 seconds worth of silence at the very start and very end of the file. This helps on mobile devices a lot.


The SoundManager can't yet play more than 1 audio tag at once I'm afraid. I'll consider adding support for it though, but it's certainly a limitation at the moment.

Link to comment
Share on other sites


  • Recently Browsing   0 members

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