HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Component-based system for JavaScript game

Submitted by: @import:stackexchange-codereview··
0
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 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.

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 null here , not bad in itself, except that you return false in addComponent. You might want to consider reviewing your code and standardizing on false or null.



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.