Toasted Posted April 8, 2015 Share Posted April 8, 2015 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-1and 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 usingobject._.varNameor I could just dump every custom variables withconsole.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 More sharing options...
drhayes Posted April 8, 2015 Share Posted April 8, 2015 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. ( = druphoria 1 Link to comment Share on other sites More sharing options...
bilboon Posted April 8, 2015 Share Posted April 8, 2015 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(); c75 1 Link to comment Share on other sites More sharing options...
Toasted Posted April 9, 2015 Author Share Posted April 9, 2015 @drhayesThansk for your answer, also you're probably right about the performance costMy 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 More sharing options...
bilboon Posted April 10, 2015 Share Posted April 10, 2015 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 More sharing options...
Recommended Posts