1 decade ago by ape
I'm having some trouble implementing the classic flyweight design pattern (or a variation of that pattern).
Basically here's what I'm trying to do, generally speaking: rather than spawn 100 entities, I spawn 1 entity (really, an "entity model"). On each game update I want to adjust a property of that entity 100 times. (In reality, those numbers are much greater , and in most cases, unknown).
In theory, I should be able to spawn 1 entity with its intrinsic properties (like
I'll show some code, then describe what I'm seeing:
In my
Then in my
And in
When run, what I see are the animations for "Oak", "Yellow", with 3 leaves, and "Pine", "green", with 4 leaves. Essentially the last of each FlyweightTree object.
Any tips?
Basically here's what I'm trying to do, generally speaking: rather than spawn 100 entities, I spawn 1 entity (really, an "entity model"). On each game update I want to adjust a property of that entity 100 times. (In reality, those numbers are much greater , and in most cases, unknown).
In theory, I should be able to spawn 1 entity with its intrinsic properties (like
entity.size
, entity.type
, etc), then update a pool of objects that point to that base entity, each with their own extrinsic properties (like position, animation, etc).I'll show some code, then describe what I'm seeing:
ig.module( 'game.entities.tree' ) .requires( 'impact.entity' ) .defines(function(){ /* FlyweightTree supplies the intrinsic properties, or properties each type of tree will possess. There are four possible types of tree, each type having a combination of a name and color. Like "Oak" and "yellow". We also want each the default properties of an ig.Entity which is why we extend the Entity module. */ FlyweightTree = ig.Entity.extend({ size: {x: 16, y:16}, animSheet: new ig.AnimationSheet( 'media/tree.png', 16, 16), init: function(x, y, settings) { this.parent(x, y, settings); /* Add 16 possible animations - 4 colors, each with a frame showing a single digit between 1 and 4 */ var lc = 0; var cell = 0; var colors = ["green", "red", "yellow", "blue"]; for (var c = 0; c < colors.length; c++) { color = colors[c]; for (lc = 0; lc < 4; lc++) { this.addAnim(color + '_' + (lc+1), 1, [cell]); cell += 1; }; }; this.name = settings.name; this.color = settings.color; } }); /* The factory is a singleton object that allows us to either create a FlyweightTree object if one doesn't exist, or find the existing one. */ var FlyweightFactory = (function() { var flyweights = {}; return { get: function(name, color) { // check to see if we have the object in the pool yet if (!flyweights[name + color]) { // if we're spawning a new object, give it a random position, just for fun var randX = Math.floor(Math.random() * (ig.system.width)); var randY = Math.floor(Math.random() * (ig.system.height)); // add it to the pool of FlyweightTree objects flyweights[name+color] = ig.game.spawnEntity(FlyweightTree, randX, randY, {name: name, color: color}); } // return the object from the pool return flyweights[name+color]; }, getCount: function() { // a helper that'll make iterating over the pool of FlyweightTree's easier var count = 0; for (var f in flyweights) count++; return count; } } })(); /* The TreeCollection manages our pool of Tree objects. It's the main interface to our Tree objects for the game. */ TreeCollection = function() { var trees = {}; var count = 0; return { add: function(name, color, leaves, uid, pos) { trees[uid] = new Tree(name, color, leaves, uid, pos); count++; }, get: function(uid) { return trees[uid]; }, getCount: function() { return count; } } }; /* A Tree object is a combination of the FlyweightTree object, which contains the shared, or instrinsic, details of our tree, as well as the unique, or extrinsic, details of our tree. So while the tree might be a yellow Oak tree, it also has a unique position, and a unique number of leaves, and a unique ID. */ var Tree = function(name, color, leaves, uid, pos) { this.flyweight = FlyweightFactory.get(name, color); // establish a reference to our FlyweightTree this.name = this.flyweight.name; // shortcuts to the name and color this.color = this.flyweight.color; this.leaves = leaves; // apply unique properties this.uid = uid; this.pos = pos; /* tree#update will be called by the main main#update. In theory, it should apply any new properties, then draw our entity using the anim for this tree. */ this.update = function() { var anim = this.flyweight.anims[this.color + '_' + this.leaves]; this.flyweight.currentAnim = anim; this.flyweight.pos = this.pos; this.flyweight.update(); } this.draw = function() { this.flyweight.draw(); } } ig.global.TreeCollection = TreeCollection; });
In my
game.init
I build a collection of Trees like so:this.trees = new TreeCollection(); var randX = function() {return Math.floor(Math.random() * (ig.system.width))}; var randY = function() {return Math.floor(Math.random() * (ig.system.height))}; this.trees.add("Oak", "yellow", 1, 1, {x: randX(), y: randY()}); this.trees.add("Pine", "green", 2, 2, {x: randX(), y: randY()}); this.trees.add("Oak", "yellow", 3, 3, {x: randX(), y: randY()}); this.trees.add("Pine", "green", 4, 4, {x: randX(), y: randY()});
Then in my
game.update
I do this:for (var i = 0; i < this.trees.getCount(); i++) { this.trees.get(i+1).update(); };
And in
game.draw
:this.parent(); for (var i = 0; i < this.trees.getCount(); i++) { this.trees.get(i+1).draw(); };
When run, what I see are the animations for "Oak", "Yellow", with 3 leaves, and "Pine", "green", with 4 leaves. Essentially the last of each FlyweightTree object.
Any tips?