UNPKG

elation-engine

Version:
153 lines (135 loc) 5.99 kB
elation.component.add("engine.things.turret", function(args) { this.postinit = function() { //this.initControllable(); this.defineProperties({ 'pitch': { type: 'angle', default: 0 }, 'yaw': { type: 'angle', default: 0 }, 'pitchspeed': { type: 'angle', default: Math.PI / 2 }, 'yawspeed': { type: 'angle', default: Math.PI / 2 }, 'maxpitchdegrees': { type: 'angle', default: 90 }, 'minpitchdegrees': { type: 'angle', default: -44 }, 'reloadtime': { type: 'int', default: 2000 }, 'muzzleoffset': { type: 'vector3', default: [0,0,0] }, 'muzzlespeed': { type: 'float', default: 150.0 }, 'range': { type: 'float', default: 300.0 }, 'render.scene': { type: 'string', default: '/media/space/models/turret/A1 Turret.js' }, }); this.defineActions({ 'pitch': this.pitch, 'yaw': this.yaw, 'fire': this.fire, 'aim': this.aim }); this.lastfire = 0; this.pitchvel = new THREE.Vector3(); this.yawvel = new THREE.Vector3(); elation.events.add(this, 'thing_load', this); } this.pitch = function(amount) { this.pitchvel.set(amount * this.properties.pitchspeed,0,0); this.hinges['gun'].updateState(); } this.yaw = function(amount) { this.yawvel.set(0, 0, amount * this.properties.yawspeed); this.hinges['mount'].updateState(); } this.fire = function(amount) { var now = new Date().getTime(); if (now > this.lastfire + this.properties.reloadtime) { var aim = this.aim(); var bullet = this.spawn('turret_bullet', null, {position: aim.position.toArray(), velocity: aim.velocity.multiplyScalar(this.properties.muzzlespeed).toArray()}, true); setTimeout(elation.bind(bullet, bullet.die), this.properties.reloadtime * 4); this.lastfire = now; } } this.aim = function() { if (!this.parts || !this.parts['Turret_gun']) return; var aimpos = this.parts['Turret_gun'].localToWorld(this.properties.muzzleoffset.clone()); var gunpos = new THREE.Vector3().getPositionFromMatrix(this.parts['Turret_gun'].matrixWorld); var aimvel = this.parts['Turret_gun'].localToWorld(new THREE.Vector3(0,1,0)).sub(gunpos).normalize(); return {position: aimpos, velocity: aimvel}; } this.thing_load = function(ev) { this.hinges = {}; this.hinges['gun'] = new elation.physics.rigidbody({ position: this.parts['Turret_gun'].position, orientation: this.parts['Turret_gun'].quaternion, mass: 0, angular: this.pitchvel, object: this }); elation.physics.system.add(this.hinges['gun']); this.hinges['mount'] = new elation.physics.rigidbody({ position: this.parts['Turret_mount'].position, orientation: this.parts['Turret_mount'].quaternion, mass: 0, angular: this.yawvel, object: this }); elation.physics.system.add(this.hinges['mount']); this.spawn("turretcontroller", null, {persist: false}); } }, elation.engine.things.generic); /* BEGIN AI */ elation.component.add("engine.things.turretcontroller", function(args) { this.postinit = function() { this.initAIController(); this.defineActions({ 'setTarget': this.setTarget }); this.defineProperties({ 'target': { type: 'thing', comment: 'Active target' } }); this.addBehavior('track_and_fire', this.track_and_fire, 100); this.setBehavior('track_and_fire'); //this.engine.systems.world.scene['world-3d'].add(this.helpers.aim); } this.track_and_fire = function() { // Ideal solution: // - calculate flighttime for projectile to reach target, given muzzle velocity // - extrapolate target position + target velocity * flighttime // - determine necessary pitch/yaw amounts var deadzone = Math.PI/32; // FIXME - target is hardcoded as camera for now; need proper target acquisition logic var turret = this.parent, target = this.engine.systems.render.views['main'].camera; //this.properties.target; if (turret && target) { var aim = turret.aim(); if (!aim) return; var dist = aim.position.distanceTo(target.position); if (dist < turret.properties.range) { var targetpos = new THREE.Vector3().getPositionFromMatrix(target.matrixWorld); var mypos = new THREE.Vector3().getPositionFromMatrix(this.parent.objects['3d'].matrixWorld); var targetdir = turret.parts['Turret_mount'].worldToLocal(targetpos).normalize(); var aimdir = turret.parts['Turret_mount'].worldToLocal(aim.velocity.clone().add(mypos)).normalize(); var t = new THREE.Vector3(targetdir.x, 0, targetdir.y).normalize(); var a = new THREE.Vector3(aimdir.x, 0, aimdir.y).normalize(); var yaw = Math.atan((t.x - a.x) / (t.z - a.z)); var yaw2 = Math.acos(t.dot(a)); var yawspeed = yaw / (turret.properties.yawspeed * this.thinktime/1000); var yaw3 = yaw2 * (yaw / Math.abs(yaw)) / (turret.properties.yawspeed * this.thinktime/1000); //console.log('yaw is', yaw, yaw2, yaw3); yawspeed = yaw3; turret.yaw(this.deadzone(yawspeed, deadzone, 1)); /* var curpitch = new THREE.Vector3().setEulerFromQuaternion(turret.parts['Turret_gun'].quaternion); if ((curpitch.x > turret.properties.maxpitchdegrees * Math.PI/180 && pitch > 0) || (curpitch.x < turret.properties.minpitchdegrees * Math.PI/180) && pitch < 0) { turret.pitch(0); } else { turret.pitch(this.deadzone(pitch, deadzone, 1)); } */ if (Math.abs(yaw3) < deadzone) { turret.fire(); } //turret.state['firing'] = false; } else { //turret.state['firing'] = false; } } } this.deadzone = function(angle, deadzone, max) { return (Math.abs(angle) < deadzone ? 0 : Math.max(-max, Math.min(max, angle))); } }, elation.engine.things.aicontroller);