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?
