Reputation: 413
I am trying to find a clean, readable way to manage variables across functions in a Phaser Class but for various reasons I am unsatisfied with the solutions I've found.
What I am aware is avaiable:
Global Variables
I'm not very fond of this implementation for the possibility of variables being accessible by other files.
var heroes = [];
var play = new Phaser.Class({
Extends: Phaser.Scene,
initialize: function(){
Phaser.Scene.call(this, {key: 'play'});
},
create: function () {
for(var i = 0; i < 5; i++){
heroes.add(new Hero())
}
},
update: function(){
if(!heroes.length){
heroes.add(new Hero())
}
heroes.forEach(function(hero){
if(hero.hp <= 0){
hero.destroy();
}
});
}
});
DataManager class (implemented as registry)
I prefer this since it's more controlled but to me DataManager feels like it's intended for configs, not as a means to process/share data between class methods; also accessing and updating variables feels very heavy-handed with a specific service to get and set its values.
var play = new Phaser.Class({
Extends: Phaser.Scene,
initialize: function(){
this.registry.set('heroes', []);
Phaser.Scene.call(this, {key: 'play'});
},
create: function () {
var heroes = this.registry.get('heroes');
for(var i = 0; i < 5; i++){
heroes.add(new Hero())
}
this.registry.set('heroes', heroes);
},
update: function(){
var heroes = this.registry.get('heroes');
if(!heroes.length){
heroes.add(new Hero())
}
heroes.forEach(function(hero){
if(hero.hp <= 0){
hero.destroy();
}
});
this.registry.set('heroes', heroes);
}
});
Using 'this'
This feels the cleanest way to me so far since this refers to the class object and it's easy enough to update and retrieve values BUT in this context 'this' is shared with some internal Phaser specific variables which I want to separate my variables from. Besides namespacing with this are there any alternative solutions?
var play = new Phaser.Class({
Extends: Phaser.Scene,
initialize: function(){
this.heroes = [];
Phaser.Scene.call(this, {key: 'play'});
},
create: function () {
for(var i = 0; i < 5; i++){
this.heroes.add(new Hero())
}
},
update: function(){
if(!heroes.length){
this.heroes.add(new Hero())
}
this.heroes.forEach(function(hero){
if(hero.hp <= 0){
hero.destroy();
}
});
}
});
Upvotes: 6
Views: 9705
Reputation: 61
Tried to pass some global data between scenes and found the following. Each scene has its own ref to the global registry. Here is the quote from documentation:
This is a game-wide instance of the Data Manager, allowing you to exchange data between Scenes via a universal and shared point.
In the default set-up you can access this from within a Scene via thethis.registry
property.
https://photonstorm.github.io/phaser3-docs/Phaser.Data.DataManager.html Here is the doc with the detailed description of the class. Tried this in a recent game - it's very convenient in use.
Upvotes: 5
Reputation: 413
Just realised another way to do it is using a self-invoking function:
In this example heroes will be scoped to the function and also shouldn't pollute the return object;
var play = new Phaser.Class(function(){
var heroes = [];
return {
Extends: Phaser.Scene,
initialize: function(){
heroes = [];
Phaser.Scene.call(this, {key: 'play'});
},
create: function () {
for(var i = 0; i < 5; i++){
heroes.add(new Hero())
}
},
update: function(){
if(!heroes.length){
heroes.add(new Hero())
}
heroes.forEach(function(hero){
if(hero.hp <= 0){
hero.destroy();
}
});
}
}}());
Upvotes: 1
Reputation: 3747
The cleanest and most readable way in my opinion would be using proper classes (and not instances of Phaser.Class
). You can always extend a Phaser class that you need (like here with Phaser.Scene
).
TypeScript:
class Play extends Phaser.Scene {
private heroes: Hero[] = [];
private create(): void {
for (let i = 0; i < 5; i++) {
this.heroes.push(new Hero());
}
}
private update(): void {
if (!this.heroes.length) {
this.heroes.push(new Hero());
}
this.heroes.forEach((hero) => {
if (hero.hp <= 0) {
hero.destroy();
}
});
}
public initialize(): void {
Phaser.Scene.call(this, { key: 'play' });
}
}
ES6 (same, except for type declarations and access modifiers):
class Play extends Phaser.Scene {
heroes = [];
create() {
for (let i = 0; i < 5; i++) {
this.heroes.push(new Hero());
}
}
update() {
if (!this.heroes.length) {
this.heroes.push(new Hero());
}
this.heroes.forEach((hero) => {
if (hero.hp <= 0) {
hero.destroy();
}
});
}
initialize() {
Phaser.Scene.call(this, { key: 'play' });
}
}
If you're for some reason stuck to ES5, then your last suggestion might be your best bet.
Upvotes: 1