Jump to content

Best practice for objects custom variables?


Toasted
 Share

Recommended Posts

I'm used to having one class per entity type, so I usually extend my sprites as shown here: http://phaser.io/examples/v2/sprites/extending-sprite-demo-1

and then I add my own variables. Example:

Player = function (health) {    Phaser.Sprite.call(this, game);    this.health = 10;    this.moveSpeed = 5.0;};Player.prototype = Object.create(Phaser.Sprite.prototype);Player.prototype.constructor = Player;

But since Javascript doesn't really have private/public variables, everything is just shared within the object, and it kinda feels dirty, especially coming from other languages like Java/C#/C++.

 

So I found myself doing something like this:

Player = function (health) {    Phaser.Sprite.call(this, game);    this._ = {};    this._.health = 10;    this._.moveSpeed = 5.0;};Player.prototype = Object.create(Phaser.Sprite.prototype);Player.prototype.constructor = Player;

Then I can just access the variables by using

object._.varName

or I could just dump every custom variables with

console.log(object._)

but I'm not sure if it's how I'm supposed to handle it.

 

 

I was actually wondering how you guys were doing it, and if there was a "better way" to do it or not.

Link to comment
Share on other sites

It might not be a super satisfying answer, but I'd say don't worry about. The benefits of encapsulation within a dynamic, weakly-typed language don't outweigh the potential performance penalty of adding object traversals to get to commonly used properties, i.e. what you're doing with object._.health.

 

In other words: "Welcome to the jungle, we got fun and games..."

 

Another approach to consider is using Object.defineProperty to define getters and setters in your constructor function. The getters and setters will be scoped to the "inside" of your ctor and so will have access to "private" variables. I think, at this moment, the performance of properties in JS isn't great but you should test to find out.

 

Really, though, I wouldn't worry about it. ( =

Link to comment
Share on other sites

I usually use aggregation and encapsulate phaser sprite inside my logic classes. 

var Tile = Class({    init: function (){        this.dx = 1;        this.view = null;    },    destroy: function (){        this.dispose();    },    update: function (){        this.view.x += this.dx;    },    render: function (){        this.dispose();        this.view = this.game.add.sprite(0, 0, 'blabla');        this.view.update = _.bind(this.update, this);    },    dispose: function (){        if (this.view){           this.view.destroy();           this.view = null;        }    }});// usagevar tile = new Tile();tile.render();tile.destroy();
Link to comment
Share on other sites

@drhayes

Thansk for your answer, also you're probably right about the performance cost

My main concern was more about how weird and awkward it feels using object._, so I was wondering what you guys were using instead.

 

@bilboon 's solution looks interesting, I'll try it and see how it goes.

I'll also take a look at Object.defineProperty.

Link to comment
Share on other sites

For me, the main advantage of encapsulating Phaser's display objects inside logic classes, is the ability to define an API which feets my game requirements without clobbering Phaser API and the possibility to manage different type of views (Sprite, Image, Group, ...) transparently. For exemple a grid component can have a view of type Group with multiple sprite children:

var Grid = Class({    init: function (size, w, h){        this.width = w;        this.height = h;        this.cell_size = size;        this.events = {            onCellClicked: new Phaser.Signal()        };        this.view = null;    },    destroy: function (){        this.events.onCellClicked.removeAll();        this.dispose();    },    render: function (){        this.dispose();        this.view = this.game.add.group();        // create all cells        for (var i=0; i<this.width; i++){            for (var j=0; j<this.height; j++){                  var cell = this.game.make.sprite(i*this.cell_size, j*this.cell_size, 'cell_texture');                cell.inputEnabled = true;                cell.events.onInputDown.add(function (){                    this.events.onCellClicked.dispatch(i, j);                }, this);                this.view.add(cell);            }         }    },    dispose: function (){        if (this.view){            this.view.destroy();            this.view = null;        }    }});var grid = new Grid(50, 10, 10);grid.events.onCellClicked.add(function (i, j){    console.log("cell "+i+" "+j+" clicked");});grid.render();
 

Bonus, i post here the function Class that i writed for simpler Class definition, and allowing simili heritage:

var Helpers = {    createClass: function (prototype, ParentClass){                        var Klass =  ParentClass ? function (){            ParentClass.apply(this, arguments);        } : function (){            this.init.apply(this, arguments);        };        var parent_prototype = ParentClass ? ParentClass.prototype : {            init: function (){}        };                Klass.prototype = {};        _.assign(Klass.prototype, parent_prototype, prototype, {constructor: Klass});        return Helpers.extendable(Klass);    },    extendable: function (Klass){        Klass.extend = function (prototype){            return Helpers.createClass(prototype, Klass);        };        return Klass;    }};var Class = Helpers.createClass;//------------------------------------// usage var A = Class({    init: function (){        this.name = 'A';    },    print: function (){        console.log(this.name);    }});var B = A.extend({   init: function (){       this.name = 'B';   }});var a = new A();var b = new B();a.print(); // -> Ab.print(); // -> B
Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

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