Jump to content

How do I load a new scene with Phaser 3 and WebPack?


mhcdotcom
 Share

Recommended Posts

Hey Folks,

I hope you can help. I am fairly new to Phaser 3 and am currently working on a platformer where my character can run, jump and collect collectibles. My game is modularised through WebPack everything else is plain JS along with the Phaser 3 framework. 
I am using Tiled where I export my levels as json files and the initial level loads perfectly with all collision tiles in place and working as expected.

I've hit a road block with loading/starting new levels. I'll try and explain with my code to clarify. I've reduce the code significantly to make it easier to read.  

main.js: Entry file

// Main.js
import 'phaser';

import { Cave } from 'scenes/cave';
import { Playground } from 'scenes/playground';

var config = {...},
  scene: [Cave,Playground]
};
var game = new Phaser.Game(config);

Cave.js. For the sake of conciseness, I've placed the this.scene.start in the update function so the new scene initialisation happens immediately.
MapSetup function is further down.

// Cave.js
import 'phaser';
import MapSetup from 'modules/map-setup.js';
import CollectibleSetup from 'modules/collectible-setup.js';

const mapSetup = new MapSetup();
const collectibleSetup = new CollectibleSetup();

export class Cave extends Phaser.Scene {

constructor () {super('Cave')}

  preload() {
    this.load.tilemapTiledJSON('map', 'assets/levels/cave/cave.json');// map made with Tiled in JSON format
    this.load.spritesheet('cave', 'assets/levels/cave/cave.png', {frameWidth: 64, frameHeight: 64});// tiles in spritesheet
  }

  create() {
    // Setup up map for this scene/level
    var mapObj = mapSetup.sceneMap(this, 'map', 'cave', 'world')
    this.map = mapObj.map;
    this.physics.add.overlap(this.player, this.stars, collectibleSetup.collectStar, null, this);
  }// create

  update () {
    this.scene.start('Playground')
  }

Playground.js

// Playground.js
export class Playground extends Phaser.Scene {

constructor () {super('Playground')}

  preload() {
    this.load.tilemapTiledJSON('map', 'assets/levels/playground/map.json');// map made with Tiled in JSON format
    this.load.spritesheet('tiles', 'assets/levels/playground/tiles.png', {frameWidth: 70, frameHeight: 70});// tiles in spritesheet
  }

  create() {
    // Setup up map for this scene/level
    var mapObj = mapSetup.sceneMap(this, 'map', 'tiles', 'World')
    this.map = mapObj.map;
    this.physics.add.overlap(this.player, this.stars, collectibleSetup.collectStar, null, this);
  }// create

}

MapSetup.js. The issue occurs here when the PlayGround scene is initiated. 

import 'phaser';

export default class MapSetup {

  sceneMap (ctx, key, tileSetImage, dynamicLayer) {
    // Map
    var map = ctx.make.tilemap({key: key});
    console.log('map',map)
    // tiles for the ground layer - tilesets.name`
    var groundTiles = map.addTilesetImage(tileSetImage);
    // create the ground layer - layers[i].name
    var groundLayer = map.createDynamicLayer(dynamicLayer, groundTiles, 0, 0);
    // the player will collide with this layer
    groundLayer.setCollisionByExclusion([-1]);
    // set the boundaries of our game world
    ctx.physics.world.bounds.width = groundLayer.width;
    ctx.physics.world.bounds.height = groundLayer.height;

    return {map:map, groundTiles:groundTiles, groundLayer:groundLayer}
  }

}

I'll try and explain the issue as I understand it. When Playground is initiated, the following error fires in the console and it's because the the groundTiles & groundLayer variables return null so the setCollisionByExclusion doesn't work. 

image.png.157bcb99f865d613f94f02d9ac8f6a74.png

When I console.log the map variable that get's assigned in the sceneMap function it returns: 
image.png.54f25a2b6a1844c08e775f93b7e40b85.png

The tileset name is still referencing the cave json object and not the playground one. I don't understand why that is. My understanding is that a scene is automatically stopped when a new scene is started and that each scene is it's own class so i'm a bit baffled as to why previous references are still in place.
What am I missing?

Any help would be much appreciated. 

Thanks, All

Moe

Link to comment
Share on other sites

Thanks @samme
I think I figured it out. The issue is my misunderstanding of how Tiled is intended to be incorporated into Phaser's framework. 
I have 2 maps(JSON files) built out from 2 different Tiled files. Phaser seems to be intended to load 1 tilemap instance that is used across an entire game build. 

// Where the mapObj variable is assigned in Playground.js
var mapObj = mapSetup.sceneMap(this, 'map', 'tiles', 'World')
// The 'tiles' reference should remain the same as what is assigned in the initial Scene(i.e. 'cave')
var mapObj = mapSetup.sceneMap(this, 'map', 'cave', 'World')

I thought a new instance of the tilemap would be created when a new scene starts but that doesn't seem to be the case as the name 'cave' for the tileset in the console is used and not 'tiles' when the Playground scene starts. 
 
It does makes working with Tiled and building/editing levels more maintainable but wasn't very intuitive to a beginner like me. 
If there is anything I'm off the mark with, please let me know. 

Link to comment
Share on other sites

Loading a tilemap file and creating/instantiating a Tilemap object are different.

You can load as many tilemap files as you need, as long as you use distinct keys. It doesn't matter which scene you load them in, they're all stored in a single game cache.

You can create a Tilemap object from any tilemap file already in the cache. The map belongs to the scene and lasts only as long as the scene does.

 

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

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