Delay/freeze to change game scenes

Hi

On my game scene there are 7200 tiles object, tile size are 352x64 (separate with 4 sprite) to cover the game map. and another object like points, players and obstacles that are less than 100 objects.

tile are loaded as spritesheet

this.load.spritesheet('tiled', 'img/tiles.png', {frameWidth: 88, frameHeight: 64});

If i switch scenes or start another scenes, it’s take about 7 seconds until it’s moved to target scene.
but starting game scene are quite fast, look like there are no delay to process.

is it normal for a delay to switch another scene ?

7200 tile objects is a lot, so it makes sense why it is taking a while to load. I would suggest creating a data map and loading the tiles while the player moves around instead of loading it all at once.

Any example for this ?

I know 7200 object tiles is too much, but it’s just from a single 352x64 image.

It’s somewhat of an advanced topic that I am sure you can find tutorials for and there is more than one way to do it depending on what your needs are.

But a pseudo example would be something like this:
In a json file:

tiles: [
    [`a`,`a`,`a`,`a`,`a`],
    [`a`,`b`,`a`,`b`,`a`],
    [`a`,`a`,`a`,`a`,`a`],
    [`a`,`b`,`a`,`b`,`a`],
    [`a`,`a`,`a`,`a`,`a`],
]

In code:

let myChar_IndexX = 3;
let myChar_IndexY = 3;
let myChar_FoV = 1; //How far the tiles must be from your character in order to be rendered.

for(let x = myChar_IndexX - myChar_FoV; x < myChar_IndexX + myChar_FoV ; x++)
{
    for(let y = myChar_IndexY - myChar_FoV; y < myChar_IndexY + myChar_FoV; y++)
    {
        let tileKey = myJSONFile.tiles[y][x];
        //Associate the a and b characters in the tile map with a class. ex:
        //let tile = new myTileData[tileKey]();
    }
}

There is a lot that I did not include in the above code as this is a much larger topic. However, hopefully the above will give you a general sense of how it can be done. I would definitely suggest you find a tutorial online.

1 Like

Thanks for your code, i really appreciate it, i will put it as an alternative.

Is there no simple way to reduce the delay ?

If someone wanna try my sample project.

My test link http://cdn.redfoc.com/test/p3_tiles

If you go back to previous layout, the long delay are appear here.

My code

class load extends Phaser.Scene {
	constructor(){
		super('load');
	}
	preload(){
		this.load.spritesheet('tiled', 'tiles.png', {frameWidth: 88, frameHeight: 64});
	}
	create(){
		this.scene.start('menu')
	}
}
class main_menu extends Phaser.Scene {
	constructor(){
		super('menu');
	}
	create(){
		this.add.text(20,20, 'Press A to change scene',{fontFamily: 'Arial', fontSize: '30px',color: '#fff'});
		this.input.keyboard.on('keydown', function(e,f){
			if(e.key == 'a'){
				this.scene.start('game')
			}
		}, this);
	}
}
class main_game extends Phaser.Scene {
	constructor(){
		super('game');
	}
	preload(){
		this.load.spritesheet('tiled', 'tiles.png', {frameWidth: 88, frameHeight: 64});
	}
	create(){
		var size = {
	      w: 60,
	      h: 120
	    }
	    for(var y=0; y<size.h;y++){
	      for(var x=0; x<size.w; x++){
	        var o = this.add.sprite(x*88,y*64,'tiled');
	        o.setFrame(Math.round(Math.random()*3));
	      }
	    }
	    this.add.text(20,20, 'Press B to back to previous scene',{fontFamily: 'Arial', fontSize: '30px',color: '#fff'});
		this.input.keyboard.on('keydown', function(e,f){
			if(e.key == 'b'){
				this.scene.start('menu')
			}
		}, this);
	}
}
var config = {
  type: Phaser.AUTO,
  width: 1280,
  height: 720,
  scene: [load, main_menu, main_game],
}
var game = new Phaser.Game(config);

Try using a TileMap instead. I think that does wonders for optimizing lots of tiles on the screen.

1 Like

My game style is isometric

Sprite

tiles

Game

fsdsxc

any idea how to use built-in tilemap with isometric style ?

Ah, just realized that this isn’t an issue with creating the assets, this is an issue with destroying the assets. It looks like Phaser is emitting events and removing events on destroy for all 7200 objects, which is causing it to lag.

Try adding o.destroy = function(){}; in your nested for loop, like so:

for(var y=0; y<size.h;y++){
	for(var x=0; x<size.w; x++){
	    var o = this.add.sprite(x*88,y*64,'tiled');
	    o.setFrame(Math.round(Math.random()*3));
        o.destroy = function(){};
	}
}

Note: This is for testing purposes only, as you would definitely want to destroy your objects for memory management.

1 Like

Wow, it’s so fast

What you mean about for testing purposes ? it’s can’t be used for actual game?

destroy() is a built-in function for all of Phaser’s GameObjects. It removes any listeners, data, etc. that may keep the object from getting garbage collected. If your unused objects don’t get garbage collected, eventually your program will run out of memory and crash. I am not entirely sure what Phaser does to clean up memory, but it is most-likely needed.

You may be able to get by with this quick work-around, but it isn’t the best practice.

Currently this is the only solution i know to fix my current game.

If it’s not the best practice, can you tell me the cons by using destroy = function(){}; after object created ?

Unfortunately this is just how Phaser is processing the destruction of it’s GameObjects. I would suggest creating an issue on Phaser’s Github so others can look into this. Worst case, this is a necessary evil and not an issue. If that is the case, you can choose whether to preference memory (not using destroy = function(){}; or performance (using destroy = function(){};).

Thank you for your time and explanations.

You can try using a Blitter instead.

2 Likes

thank you. and all person who want to help me

a nasty and probably not preferred by pro-coders solution might be to not just use another scene but another page in a game with this size/amount of assets (assuming you’re not working pc-only , on a system with a bare 8gb i doubt you’ll get to 4gb of assets any time soon for a phaser game)

But if its about functionality, not about how it ‘should be done’ (lol does that even exist) it might be a fast hack to make sure (afaik you wont get anything transferred between html page loads(?) do correct me if i’m wrong im just a hobbyist)
I have for instance a hobbyproject … game ive been dabbling on which i expect to have quite some assets over time (atm a meagre 100 mb in all i think)
So ‘between zones’ i use window.location.replace(…); or just a click if auto-refresh won’t work and to the best of my (emphasis, heh) knowledge that takes out all the trash in one and the next page you just load everything you might need for the whole zone up first (i dont know if you can check for available memory either, as i said im a hobbyist and i actually never heard of phaser before i started this thing)

just another idea since people are pitching