patternjavascriptMinor
Component-based system for JavaScript game
Viewed 0 times
javascriptsystemgameforbasedcomponent
Problem
I'm creating a JavaScript/WebGL based game and would like you all to take a look at the current entity component system which I created for it. I've used it once before on another project, and while I was very happy with the results, there were parts of it I did not feel 100% good about.
In particular, sometimes a component needs to call the
When I intercept the properties, I currently wrap intercepted function calls into a closure (see
Things I've used as reference:
Full source code can be found here.
Base Component
```
(function() {
ChuClone.namespace("ChuClone.components");
ChuClone.components.BaseComponent = function() {
this.interceptedProperties = {};
return this;
};
ChuClone.components.BaseComponent.prototype = {
/**
* Array of properties intercepted, this is used when detaching the component
* @type {Array}
*/
interceptedProperties : null,
/**
* @type {ChuClone.GameEntity}
*/
attachedEntity : null,
/**
* @type {Number}
*/
detachTimeout : 0,
/**
* Unique name for this component
* @type {String}
*/
displayName : "BaseComponent",
/**
* If a component can stack, then it doesn't matter i
In particular, sometimes a component needs to call the
attachedEntities version of a function it has overridden. For example handleInput might call the attachedEntities handleInput functions and then with the new movementVector multiply them by negative 1 so now all input while this component is active is reversed.When I intercept the properties, I currently wrap intercepted function calls into a closure (see
basecomponent.intercept()) so that the this object can refer to the component itself. Without that the this object was still being referred to as the attachedEntity (from within the components version of that function), so to get the components properties I had to run a query.Things I've used as reference:
- http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/
- http://gameprogrammingpatterns.com/component.html
- http://blog.bengarney.com/2010/06/12/composition-vs-inheritance/
Full source code can be found here.
Base Component
```
(function() {
ChuClone.namespace("ChuClone.components");
ChuClone.components.BaseComponent = function() {
this.interceptedProperties = {};
return this;
};
ChuClone.components.BaseComponent.prototype = {
/**
* Array of properties intercepted, this is used when detaching the component
* @type {Array}
*/
interceptedProperties : null,
/**
* @type {ChuClone.GameEntity}
*/
attachedEntity : null,
/**
* @type {Number}
*/
detachTimeout : 0,
/**
* Unique name for this component
* @type {String}
*/
displayName : "BaseComponent",
/**
* If a component can stack, then it doesn't matter i
Solution
Your code requires a ton of domain knowledge to properly review. I went to your Github repository to try and be more familiar with what you have.
Entity support for components
You asked specifically for this one, and I did find some things to ponder upon.
-
-
-
This code confuses me. It seems built with multiple instances of the same component in mind, but then it
-
You can merge the 2 loops here in to 1 loop:
can be
Entity support for components
You asked specifically for this one, and I did find some things to ponder upon.
addComponent-
existingVersionOfComponent -> a better name could be existingInstanceofComponent or even simpler instance, as there is no versioning.-
// Remove existing version, for me it is confusing that the component can stack, but you still only allow 1 instance of it. Maybe you should find a better name/descriptor than stack.addComponentAndExecute- You return
nullhere , not bad in itself, except that you returnfalseinaddComponent. You might want to consider reviewing your code and standardizing onfalseornull.
removeComponentWithName-
This code confuses me. It seems built with multiple instances of the same component in mind, but then it
breaks out the for loop. It seems you could write this code with 1 loop.-
You can merge the 2 loops here in to 1 loop:
removeComponentWithName: function(aComponentName) {
var len = this.components.length;
var removedComponents = [];
for (var i = 0; i < len; ++i) {
if (this.components[i].displayName === aComponentName) {
removedComponents.push(this.components.splice(i, 1));
break;
}
}
// Detach removed components
if (removedComponents) {
i = removedComponents.length;
while (i--) {
removedComponents[i].detach();
}
}
},can be
removeComponentWithName: function(componentName) {
var len = this.components.length,
removedComponent;
for (var i = 0; i < len; ++i) {
if (this.components[i].displayName === componentName) {
removedComponent = this.components.splice(i, 1).pop();
removedComponent.detach();
break;
}
}
},Code Snippets
removeComponentWithName: function(aComponentName) {
var len = this.components.length;
var removedComponents = [];
for (var i = 0; i < len; ++i) {
if (this.components[i].displayName === aComponentName) {
removedComponents.push(this.components.splice(i, 1));
break;
}
}
// Detach removed components
if (removedComponents) {
i = removedComponents.length;
while (i--) {
removedComponents[i].detach();
}
}
},removeComponentWithName: function(componentName) {
var len = this.components.length,
removedComponent;
for (var i = 0; i < len; ++i) {
if (this.components[i].displayName === componentName) {
removedComponent = this.components.splice(i, 1).pop();
removedComponent.detach();
break;
}
}
},Context
StackExchange Code Review Q#3287, answer score: 5
Revisions (0)
No revisions yet.