Skip to content

Instantly share code, notes, and snippets.

@timetocode
Last active November 11, 2015 03:02
Show Gist options
  • Save timetocode/17b050c1c2feb9883e3a to your computer and use it in GitHub Desktop.
Save timetocode/17b050c1c2feb9883e3a to your computer and use it in GitHub Desktop.
nengi.GameObject and nengi.GameComponent - prototype of component based design
function GameComponent(gameObject, config) {
this.gameObject = gameObject
this.position = gameObject.position
this.initialize()
if (config) {
this.configure(config)
}
}
GameComponent.prototype.constructor = GameComponent
GameComponent.prototype.setup = function(gameObject) {
this.gameObject = gameObject
this.position = gameObject.position
}
GameComponent.prototype.initialize = function() {
}
/*
* Uses an object to set values within the gameObject
* Accepts x,y,rotation without an explicit position. An explicit position ref
* is allowed as well ( config.position )
* @method configure
* @param {Object} config Key-value-pair to copy into gameObject
*/
GameComponent.prototype.configure = function(config) {
for (var prop in config) {
this[prop] = config[prop]
}
}
/*
* Fetches a fellow component from the parent gameObject. Merely a shortcut for
* access to other components within component scope.
* @method getComponent
* @return {GameComponent} component
*/
GameComponent.prototype.getComponent = function(name) {
return this.gameObject.getComponent(name)
}
/*
* Shorthand access to gameObject.position.x via component.x
*/
Object.defineProperty(GameComponent.prototype, 'x', {
get: function() { return this.position.x },
set: function(value) { this.position.x = value }
})
/*
* Shorthand access to gameObject.position.y via component.y
*/
Object.defineProperty(GameComponent.prototype, 'y', {
get: function() { return this.position.y },
set: function(value) { this.position.y = value }
})
/*
* Shorthand access to gameObject.position.rotation via component.rotation
*/
Object.defineProperty(GameComponent.prototype, 'rotation', {
get: function() { return this.position.rotation },
set: function(value) { this.position.rotation = value }
})
module.exports = GameComponent
var Vector2 = require('./Vector2')
function GameObject(config) {
// this.id set when added ot an instance
// this.instance set when added to an instance
this.initialize()
if (config) {
this.configure(config)
}
}
GameObject.prototype.constructor = GameObject
GameObject.prototype.initialize = function() {
this.id = null
this.position = new Vector2(0, 0)
this.state = null
/* components for iteration */
this.components = []
/* components are also added to the gameObject directly as properties
* e.g.
* this.bodyCollider = colliderComponent
*/
}
/*
* Uses an object to set values within the gameObject
* Accepts x,y without an explicit position. An explicit position ref
* is allowed as well ( pass in config.position )
* @method configure
* @param {Object} config Key-value-pair to copy into gameObject
*/
GameObject.prototype.configure = function(config) {
for (var prop in config) {
if (prop === 'x' || prop === 'y') {
// adding: x, y
this.position[prop] = config[prop]
} else if (prop === 'position') {
// adding: predefined position
this['position'] = config['position']
} else {
// adding: component
this.addComponent(config[prop])
}
}
}
/*
* Adds a component to the gameObject. The gameObject may only have one component
* with a given name. To add two of the same type of component to the gameObject
* one of the components must be renamed, e.g. collider.name = 'specialCollider'
* @method addComponent
* @param {GameComponent} component
*/
GameObject.prototype.addComponent = function(name, component) {
if (!this[name]) {
this[name] = component
this.components.push(component)
} else {
throw 'Cannot add same component to gameObject twice.'
}
}
/*
* Removes a component from the gameObject by name
* @method removeComponent
* @param {String} name
*/
GameObject.prototype.removeComponent = function(name) {
if (this[component.name]) {
var removeIndex = -1
for (var i = 0; i < this.components.length; i++) {
if (this.components[i].name === component.name) {
removeIndex = i
}
}
if (removeIndex !== -1) {
this.components.splice(removeIndex, 1)
delete this[component.name]
} else {
throw 'Failed to remove component.'
}
}
}
/*
* Returns a component by name
* @method getComponent
* @param {String} name
* @return {GameComponent}
*/
GameObject.prototype.getComponent = function(name) {
if (this[name]) {
return this[name]
} else {
throw 'Could not get component.'
}
}
/* not implemented nor used: changeComponent */
/*
* Shorthand access to gameObject.position.x via gameObject.x
*/
Object.defineProperty(GameObject.prototype, 'x', {
get: function() { return this.position.x },
set: function(value) { this.position.x = value }
})
/*
* Shorthand access to gameObject.position.y via gameObject.y
*/
Object.defineProperty(GameObject.prototype, 'y', {
get: function() { return this.position.y },
set: function(value) { this.position.y = value }
})
/*
* Shorthand access to gameObject.position.rotation via gameObject.rotation
*/
Object.defineProperty(GameObject.prototype, 'rotation', {
get: function() { return this.position.rotation },
set: function(value) { this.position.rotation = value }
})
GameObject.prototype._update = function(delta, tick, now) {
if (this.update) {
this.update(delta, tick, now)
}
for (var i = 0; i < this.components.length; i++) {
var component = this.components[i]
if (component.update) {
component.update(delta, tick, now)
}
}
}
module.exports = GameObject
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment