Last active
February 9, 2017 04:48
-
-
Save timetocode/59edb652c4c1362333b4 to your computer and use it in GitHub Desktop.
An entity with some of its logic in a physics and collider component, and the rest (weapon, hitpoints) just written directly in SumoShip entity
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var nengi = require('../../nengi/nengi') | |
var Vector2 = nengi.Vector2 | |
function PhysicsComponent(gameObject, config) { | |
nengi.Component.call(this, gameObject, config) | |
// force applied from external sources | |
this.externalForce = new Vector2() | |
// force applied from own entity (e.g. engine or movement abilities) | |
this.internalForce = new Vector2() | |
// velocity of this entity | |
this.velocity = new Vector2() | |
this.mass = 1000 | |
this.frictionCoef = 3 | |
} | |
PhysicsComponent.prototype = Object.create(nengi.Component.prototype) | |
PhysicsComponent.prototype.constructor = PhysicsComponent | |
PhysicsComponent.prototype.initialize = function() { | |
} | |
PhysicsComponent.prototype.addInternalForce = function(force) { | |
this.internalForce.add(force) | |
} | |
PhysicsComponent.prototype.addExternalForce = function(force) { | |
//console.log('addExternalForce', force) | |
this.externalForce.add(force) | |
} | |
PhysicsComponent.prototype.update = function(delta, tick, now) { | |
var externalAcceleration = new Vector2( | |
this.externalForce.x / this.mass, | |
this.externalForce.y / this.mass | |
) | |
var internalAcceleration = new Vector2( | |
this.internalForce.x / this.mass, | |
this.internalForce.y / this.mass | |
) | |
// artificial friction to make the controls nice | |
this.velocity.x += (externalAcceleration.x - this.frictionCoef * this.velocity.x) * delta | |
this.velocity.y += (externalAcceleration.y - this.frictionCoef * this.velocity.y) * delta | |
this.velocity.x += (internalAcceleration.x - this.frictionCoef * this.velocity.x) * delta | |
this.velocity.y += (internalAcceleration.y - this.frictionCoef * this.velocity.y) * delta | |
this.position.add(this.velocity) | |
// set forces to 0 | |
this.externalForce.x = 0 | |
this.externalForce.y = 0 | |
this.internalForce.x = 0 | |
this.internalForce.y = 0 | |
} | |
module.exports = PhysicsComponent |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var nengi = require('../../nengi/nengi') | |
var PhysicsComponent = require('./PhysicsComponent') | |
var CircleColliderComponent = require('./CircleColliderComponent') | |
var Projectile = require('./Projectile') | |
function SumoShip() { | |
nengi.Entity.call(this) | |
this.addComponent('physics', new PhysicsComponent(this)) | |
this.addComponent('collider', new CircleColliderComponent(this)) | |
this.collider.tags = ['player'] | |
this.collider.collideWithTags = ['asteroid', 'projectile'] | |
// consider making LifeComponent | |
this.hp = 100 | |
this.isAlive = true | |
// consider making WeaponComponent | |
this.isWeaponCharging = false | |
this.weaponChargeLevel = 1 | |
this.weaponChargeTimestamp = Date.now() | |
} | |
SumoShip.prototype = Object.create(nengi.Entity.prototype) | |
SumoShip.prototype.constructor = SumoShip | |
SumoShip.prototype.update = function(delta) { | |
if (this.isWeaponCharging) { | |
var elapsed = Date.now() - this.weaponChargeTimestamp | |
var tier = Math.floor(elapsed/1000) + 1 | |
if (tier > 3) { tier = 3 } | |
this.weaponChargeLevel = tier | |
} else { | |
this.weaponChargeLevel = 1 | |
} | |
} | |
SumoShip.prototype.move = function(move) { | |
if (!this.isAlive) return | |
if (move.W) { | |
this.physics.addInternalForce({ x: 0, y: -15000 }) | |
} | |
if (move.A) { | |
this.physics.addInternalForce({ x: -15000, y: 0 }) | |
} | |
if (move.S) { | |
this.physics.addInternalForce({ x: 0, y: 15000 }) | |
} | |
if (move.D) { | |
this.physics.addInternalForce({ x: 15000, y: 0 }) | |
} | |
} | |
SumoShip.prototype.chargeWeapon = function(charge) { | |
if (!this.isAlive) return | |
// fires a shot instantly, and begins charging a larger shot | |
var dx = this.x - charge.x | |
var dy = this.y - charge.y | |
this.rotation = Math.atan2(dy, dx) + 90 * Math.PI/180 | |
this.isWeaponCharging = true | |
this.weaponChargeTimestamp = Date.now() | |
var projectile = new Projectile() | |
projectile.owner = this | |
projectile.tier = 1 | |
projectile.launch( | |
new nengi.Vector2(this.x, this.y), | |
new nengi.Vector2(charge.x, charge.y), | |
600 | |
) | |
var kickback = new nengi.Vector2(dx, dy) | |
kickback.normalize() | |
this.physics.addExternalForce({ | |
x: kickback.x * 250000, | |
y: kickback.y * 250000 | |
}) | |
this.instance.addEntity(projectile) | |
} | |
SumoShip.prototype.dischargeWeapon = function(charge) { | |
if (!this.isAlive) return | |
// how long have we been charging? | |
var elapsed = Date.now() - this.weaponChargeTimestamp | |
var tier = Math.floor(elapsed/1000) + 1 | |
if (tier > 3) { tier = 3 } | |
// do not discharge unless charge reached tier 2 (at least 1 second of charging) | |
if (tier < 2) { | |
this.isWeaponCharging = false | |
return | |
} | |
// a larger shot was released | |
this.isWeaponCharging = false | |
//this.weaponChargeLevel = 1 | |
var dx = this.x - charge.x | |
var dy = this.y - charge.y | |
this.rotation = Math.atan2(dy, dx) + 90 * Math.PI/180 | |
var projectile = new Projectile() | |
projectile.owner = this | |
projectile.tier = tier | |
projectile.launch( | |
new nengi.Vector2(this.x, this.y), | |
new nengi.Vector2(charge.x, charge.y), | |
600 | |
) | |
var kickback = new nengi.Vector2(dx, dy) | |
kickback.normalize() | |
this.physics.addExternalForce({ | |
x: kickback.x * 250000 * tier, | |
y: kickback.y * 250000 * tier | |
}) | |
//console.log('discharged', tier, elapsed) | |
this.instance.addEntity(projectile) | |
} | |
// specify which properties should be networked, and their value types | |
SumoShip.prototype.netSchema = nengi.createEntitySchema({ | |
'id': nengi.UInt16, | |
'type': nengi.UInt8, | |
'x': nengi.Int16, | |
'y': nengi.Int16, | |
'isAlive': { binaryType: nengi.Boolean, interp: false }, | |
'rotation': nengi.Rotation, | |
'weaponChargeLevel': { binaryType: nengi.UInt8, interp: false } | |
}, { | |
'x': { delta: true, binaryType: nengi.Int8 }, | |
'y': { delta: true, binaryType: nengi.Int8 } | |
}) | |
module.exports = SumoShip | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment