From 18ac3ac1c39a35240de2e6d0a52d997c3bab2838 Mon Sep 17 00:00:00 2001 From: polygonboutique Date: Thu, 17 Nov 2016 10:09:54 +0100 Subject: [PATCH 01/11] pushed new components (ai + colorlerp) --- src/game-lib-component-colorlerp.js | 60 +++ ...b-component-vehicle-ai-object-avoidance.js | 404 ++++++++++++++++++ ...game-lib-component-vehicle-ai-path-boid.js | 52 +++ ...-lib-component-vehicle-ai-path-steering.js | 236 ++++++++++ src/game-lib-game.js | 3 +- src/game-lib-vector-3.js | 22 + src/game-lib-world.js | 6 +- 7 files changed, 780 insertions(+), 3 deletions(-) create mode 100644 src/game-lib-component-colorlerp.js create mode 100644 src/game-lib-component-vehicle-ai-object-avoidance.js create mode 100644 src/game-lib-component-vehicle-ai-path-boid.js create mode 100644 src/game-lib-component-vehicle-ai-path-steering.js diff --git a/src/game-lib-component-colorlerp.js b/src/game-lib-component-colorlerp.js new file mode 100644 index 0000000..57eaad8 --- /dev/null +++ b/src/game-lib-component-colorlerp.js @@ -0,0 +1,60 @@ +GameLib.D3.ComponentColorLerp = function( + componentId, + startColor, + endColor, + lerpSpeed +) { + this.componentId = componentId || GameLib.D3.Tools.RandomId(); + this.parentEntity = null; + + // Todo: this should be executed somewhere in game-lib-z, so that we don't execute it on every construction of an object. + GameLib.D3.Utils.Extend(GameLib.D3.ComponentColorLerp, GameLib.D3.ComponentInterface); + + this.startColor = startColor || new GameLib.D3.Vector3(0, 0, 0); + this.endColor = endColor || new GameLib.D3.Vector3(1, 1, 1); + this.lerpSpeed = lerpSpeed || 1.0; + + this.lerpTarget = this.endColor; +}; + +///////////////////////// Methods to override ////////////////////////// +GameLib.D3.ComponentColorLerp.prototype.onUpdate = function( + deltaTime, + parentEntity +) { + var t = deltaTime * this.lerpSpeed; + // t = t * t * t * (t * (6.0 * t - 15.0) + 10.0); + + parentEntity.mesh.material.color.r = parentEntity.mesh.material.color.r + (this.endColor.x - parentEntity.mesh.material.color.r) * t; + parentEntity.mesh.material.color.g = parentEntity.mesh.material.color.g + (this.endColor.y - parentEntity.mesh.material.color.g) * t; + parentEntity.mesh.material.color.b = parentEntity.mesh.material.color.b + (this.endColor.z - parentEntity.mesh.material.color.b) * t; + + +/* if( parentEntity.mesh.material.color.r == this.endColor.x + && parentEntity.mesh.material.color.g == this.endColor.y + && parentEntity.mesh.material.color.b == this.endColor.z + ) { + + + console.error("switch target"); + //this.lerpTarget = this.startColor; + + } /!*else if (parentEntity.mesh.material.color.r == this.startColor.x + && parentEntity.mesh.material.color.g == this.startColor.y + && parentEntity.mesh.material.color.b == this.startColor.z) { + + this.lerpTarget = this.endColor; + }*!/*/ + +}; + +GameLib.D3.ComponentColorLerp.prototype.onSetParentEntity = function( + parentScene, + parentEntity +) { + parentEntity.mesh.material.color = new THREE.Color( + this.startColor.x, + this.startColor.y, + this.startColor.z + ); +}; \ No newline at end of file diff --git a/src/game-lib-component-vehicle-ai-object-avoidance.js b/src/game-lib-component-vehicle-ai-object-avoidance.js new file mode 100644 index 0000000..64daedc --- /dev/null +++ b/src/game-lib-component-vehicle-ai-object-avoidance.js @@ -0,0 +1,404 @@ +/** + * + * @param componentId + * @param physicsWorld + * @constructor + */ +GameLib.D3.ComponentVehicleAIObjectAvoidance = function( + componentId, + physicsWorld +) { + this.componentId = componentId || GameLib.D3.Tools.RandomId(); + this.parentEntity = null; + GameLib.D3.Utils.Extend(GameLib.D3.ComponentVehicleAIObjectAvoidance, GameLib.D3.ComponentInterface); + + this.raycastVehicleComponent = null; + this.physicsWorld = physicsWorld || null; + this.sensors = []; + + // debug + this.debugArrows = {}; + + + console.log("constructor for : ComponentVehicleAIObjectAvoidance"); +}; + +///////////////////////////////////////////////////////////////////////// +///////////////////////// Methods to override /////////////////////////// +///////////////////////////////////////////////////////////////////////// +GameLib.D3.ComponentVehicleAIObjectAvoidance.prototype.onSetParentEntity = function( + parentScene, + parentEntity +) { + this.parentEntity = parentEntity; + this.raycastVehicleComponent = parentEntity.getComponent(GameLib.D3.RaycastVehicle); + + console.log("onSetParentEntity for : ComponentVehicleAIObjectAvoidance"); + + + if(!this.raycastVehicleComponent) { + console.warn("NO RAYCAST VEHICLE FOUND!"); + } + + // create sensors + + var boundingBox = this.parentEntity.mesh.geometry.boundingBox; + // this is taken from the main.js. + // this should be configurable inside the editor + var carBoxScaleModifier = { x : 3 / 4, y : 1 / 2, z : 0.90 }; + + var sensorLength = 0.65; + var sensorColor = new THREE.Color(0, 0, 1); + + // . . . . . . . . . . FRONT . . . . . . . . . . + + // right + this.sensors.push( + { + sensorLength : sensorLength, + + sensorColor : sensorColor, + + sensorDirection : new THREE.Vector3( + 1, + 0, + 0 + ).normalize(), + + sensorPositionOffset : new THREE.Vector3( + boundingBox.max.x * this.parentEntity.mesh.scale.x * carBoxScaleModifier.x, + boundingBox.max.z * this.parentEntity.mesh.scale.z * carBoxScaleModifier.z, + boundingBox.max.y * this.parentEntity.mesh.scale.y * carBoxScaleModifier.y // this is still swapped with y, because cannon. + ) + } + ); + + + // left + this.sensors.push( + { + sensorLength : sensorLength, + + sensorColor : sensorColor, + + sensorDirection : new THREE.Vector3( + 1, + 0, + 0 + ).normalize(), + + sensorPositionOffset : new THREE.Vector3( + boundingBox.max.x * this.parentEntity.mesh.scale.x * carBoxScaleModifier.x, + -boundingBox.max.z * this.parentEntity.mesh.scale.z * carBoxScaleModifier.z, + boundingBox.max.y * this.parentEntity.mesh.scale.y * carBoxScaleModifier.y // this is still swapped with y, because cannon. + ) + } + ); + + + // center + this.sensors.push( + { + sensorLength : sensorLength, + + sensorColor : sensorColor, + + sensorDirection : new THREE.Vector3( + 1, + 0, + 0 + ).normalize(), + + sensorPositionOffset : new THREE.Vector3( + boundingBox.max.x * this.parentEntity.mesh.scale.x * carBoxScaleModifier.x, + 0, + 0 + ) + } + ); + + + // . . . . . . DIAGONAL FRONT . . . . . . . . + // right + this.sensors.push( + { + sensorLength : sensorLength, + + sensorColor : sensorColor, + + sensorDirection : new THREE.Vector3( + 0, + 1, + 0 + ).normalize(), + + sensorPositionOffset : new THREE.Vector3( + boundingBox.max.x * this.parentEntity.mesh.scale.x * carBoxScaleModifier.x, + boundingBox.max.z * this.parentEntity.mesh.scale.z * carBoxScaleModifier.z, + boundingBox.max.y * this.parentEntity.mesh.scale.y * carBoxScaleModifier.y // this is still swapped with y, because cannon. + ) + } + ); + + + // left + this.sensors.push( + { + sensorLength : sensorLength, + + sensorColor : sensorColor, + + sensorDirection : new THREE.Vector3( + 0, + -1, + 0 + ).normalize(), + + sensorPositionOffset : new THREE.Vector3( + boundingBox.max.x * this.parentEntity.mesh.scale.x * carBoxScaleModifier.x, + -boundingBox.max.z * this.parentEntity.mesh.scale.z * carBoxScaleModifier.z, + boundingBox.max.y * this.parentEntity.mesh.scale.y * carBoxScaleModifier.y // this is still swapped with y, because cannon. + ) + } + ); + + // right + this.sensors.push( + { + sensorLength : sensorLength, + + sensorColor : sensorColor, + + sensorDirection : new THREE.Vector3( + 0.5, + 0.5, + 0 + ).normalize(), + + sensorPositionOffset : new THREE.Vector3( + boundingBox.max.x * this.parentEntity.mesh.scale.x * carBoxScaleModifier.x, + boundingBox.max.z * this.parentEntity.mesh.scale.z * carBoxScaleModifier.z, + boundingBox.max.y * this.parentEntity.mesh.scale.y * carBoxScaleModifier.y // this is still swapped with y, because cannon. + ) + } + ); + + + // left + this.sensors.push( + { + sensorLength : sensorLength, + + sensorColor : sensorColor, + + sensorDirection : new THREE.Vector3( + 0.5, + -0.5, + 0 + ).normalize(), + + sensorPositionOffset : new THREE.Vector3( + boundingBox.max.x * this.parentEntity.mesh.scale.x * carBoxScaleModifier.x, + -boundingBox.max.z * this.parentEntity.mesh.scale.z * carBoxScaleModifier.z, + boundingBox.max.y * this.parentEntity.mesh.scale.y * carBoxScaleModifier.y // this is still swapped with y, because cannon. + ) + } + ); + + // right + this.sensors.push( + { + sensorLength : sensorLength, + + sensorColor : sensorColor, + + sensorDirection : new THREE.Vector3( + 0.75, + 0.25, + 0 + ).normalize(), + + sensorPositionOffset : new THREE.Vector3( + boundingBox.max.x * this.parentEntity.mesh.scale.x * carBoxScaleModifier.x, + boundingBox.max.z * this.parentEntity.mesh.scale.z * carBoxScaleModifier.z, + boundingBox.max.y * this.parentEntity.mesh.scale.y * carBoxScaleModifier.y // this is still swapped with y, because cannon. + ) + } + ); + + + // left + this.sensors.push( + { + sensorLength : sensorLength, + + sensorColor : sensorColor, + + sensorDirection : new THREE.Vector3( + 0.75, + -0.25, + 0 + ).normalize(), + + sensorPositionOffset : new THREE.Vector3( + boundingBox.max.x * this.parentEntity.mesh.scale.x * carBoxScaleModifier.x, + -boundingBox.max.z * this.parentEntity.mesh.scale.z * carBoxScaleModifier.z, + boundingBox.max.y * this.parentEntity.mesh.scale.y * carBoxScaleModifier.y // this is still swapped with y, because cannon. + ) + } + ); + + + console.log("pushed sensors", this.sensors.length); + +}; + +GameLib.D3.ComponentVehicleAIObjectAvoidance.prototype.onUpdate = function( + deltaTime, + parentEntity +) { + if(this.raycastVehicleComponent && this.physicsWorld) { + var vehicleVelocity = this.parentEntity.getComponent(GameLib.D3.RigidBody).instance.velocity; + var vehicleVelocityLength = 12; + + + // shoot rays for each sensor & check collisions. + var world = this.physicsWorld.instance; + var result = new CANNON.RaycastResult(); + + for(var s = 0, l = this.sensors.length; s < l; ++s) { + var sensor = this.sensors[s]; + + var from = new THREE.Vector3( + this.parentEntity.position.x, + this.parentEntity.position.y, + this.parentEntity.position.z + ).add(new THREE.Vector3( + sensor.sensorPositionOffset.x, + sensor.sensorPositionOffset.y, + sensor.sensorPositionOffset.z + ).applyQuaternion(new THREE.Quaternion( + this.parentEntity.quaternion.x, + this.parentEntity.quaternion.y, + this.parentEntity.quaternion.z, + this.parentEntity.quaternion.w + ))); + + var fromC = new CANNON.Vec3( + from.x, + from.y, + from.z + ); + + var to = new THREE.Vector3( + sensor.sensorDirection.x, + sensor.sensorDirection.y, + sensor.sensorDirection.z + ).applyQuaternion(new THREE.Quaternion( + this.parentEntity.quaternion.x, + this.parentEntity.quaternion.y, + this.parentEntity.quaternion.z, + this.parentEntity.quaternion.w + )).normalize().multiplyScalar(sensor.sensorLength * vehicleVelocityLength); + + + var toC = new CANNON.Vec3( + from.x + to.x, + from.y + to.y, + from.z + to.z + ); + + world.raycastClosest( + fromC, + + toC, + + { + collisionFilterMask : 2 // check only group 2 (track) + }, + + result + ); + + if(result.hasHit) { + sensor.sensorColor = new THREE.Color(1, 0, 0); + } else { + sensor.sensorColor = new THREE.Color(0, 0, 1); + } + } + + + + // draw sensors + { + this.debugArrows.sensors = this.debugArrows.sensors || []; + + for(var s = 0, l = this.sensors.length; s < l; ++s) { + + if(!this.debugArrows.sensors[s]) { + this.debugArrows.sensors[s] = {}; + } + + if(!this.debugArrows.sensors[s].mesh) { + + var geometry = new THREE.Geometry(); + var mesh = new THREE.Mesh( + geometry, + new THREE.MeshBasicMaterial( + { + color : 0x000000, + wireframe : true + } + ) + ); + + this.debugArrows.sensors[s].mesh = mesh; + sys.game.scenes["MainScene"].instance.add(this.debugArrows.sensors[s].mesh); + } + + // remove old arrow, if we have one + if(this.debugArrows.sensors[s].arrow) { + this.debugArrows.sensors[s].mesh.remove(this.debugArrows.sensors[s].arrow); + } + + + var sensor = this.sensors[s]; + var sensorLength = sensor.sensorLength; // should get this from the sensor itself + + this.debugArrows.sensors[s].arrow = new THREE.ArrowHelper( + new THREE.Vector3( + sensor.sensorDirection.x, + sensor.sensorDirection.y, + sensor.sensorDirection.z + ).applyQuaternion(new THREE.Quaternion( + this.parentEntity.quaternion.x, + this.parentEntity.quaternion.y, + this.parentEntity.quaternion.z, + this.parentEntity.quaternion.w + )).normalize(), + + new THREE.Vector3( + this.parentEntity.position.x, + this.parentEntity.position.y, + this.parentEntity.position.z + ).add(new THREE.Vector3( + sensor.sensorPositionOffset.x, + sensor.sensorPositionOffset.y, + sensor.sensorPositionOffset.z + ).applyQuaternion(new THREE.Quaternion( + this.parentEntity.quaternion.x, + this.parentEntity.quaternion.y, + this.parentEntity.quaternion.z, + this.parentEntity.quaternion.w + ))), + + sensorLength * vehicleVelocityLength, + + sensor.sensorColor + ); + + this.debugArrows.sensors[s].mesh.add(this.debugArrows.sensors[s].arrow); + } + } + } +}; \ No newline at end of file diff --git a/src/game-lib-component-vehicle-ai-path-boid.js b/src/game-lib-component-vehicle-ai-path-boid.js new file mode 100644 index 0000000..d432d36 --- /dev/null +++ b/src/game-lib-component-vehicle-ai-path-boid.js @@ -0,0 +1,52 @@ +/** + * + * @param componentId + * @param targetEntity GameLib.D3.Entity + * @param nodePath + * @constructor + */ +GameLib.D3.ComponentVehicleAIPathBoid = function( + componentId, + targetEntity, + nodePath +) { + this.componentId = componentId || GameLib.D3.Tools.RandomId(); + this.parentEntity = null; + GameLib.D3.Utils.Extend(GameLib.D3.ComponentVehicleAIPathBoid, GameLib.D3.ComponentInterface); + + this.targetEntity = targetEntity; + this.raycastVehicleComponent = null; + this.nodePath = nodePath; + this.debugArrows = {}; +}; + +///////////////////////////////////////////////////////////////////////// +///////////////////////// Methods to override /////////////////////////// +///////////////////////////////////////////////////////////////////////// +GameLib.D3.ComponentVehicleAIPathBoid.prototype.onSetParentEntity = function( + parentScene, + parentEntity +) { + this.parentEntity = parentEntity; + this.raycastVehicleComponent = parentEntity.getComponent(GameLib.D3.RaycastVehicle); + + if(!this.raycastVehicleComponent) { + console.warn("NO RAYCAST VEHICLE FOUND!"); + } +}; + +GameLib.D3.ComponentVehicleAIPathBoid.prototype.onUpdate = function( + deltaTime, + parentEntity +) { + if(this.targetEntity && this.raycastVehicleComponent && this.nodePath) { + + // boid code. + + var currentNodeIndex = this.nodePath.indexOf(this.targetEntity); + var distanceToCurrentNode = this.parentEntity.position.distanceTo(this.targetEntity.position); + + + + } +}; \ No newline at end of file diff --git a/src/game-lib-component-vehicle-ai-path-steering.js b/src/game-lib-component-vehicle-ai-path-steering.js new file mode 100644 index 0000000..1f95eb7 --- /dev/null +++ b/src/game-lib-component-vehicle-ai-path-steering.js @@ -0,0 +1,236 @@ +/** + * + * @param componentId + * @param targetEntity GameLib.D3.Entity + * @param steeringSpeed + * @param maxSteerAngle + * @constructor + */ +GameLib.D3.ComponentVehicleAIPathSteering = function( + componentId, + targetEntity, + steeringSpeed, + maxSteerAngle +) { + this.componentId = componentId || GameLib.D3.Tools.RandomId(); + this.parentEntity = null; + + // Todo: this should be executed somewhere in game-lib-z, so that we don't execute it on every construction of an object. + GameLib.D3.Utils.Extend(GameLib.D3.ComponentVehicleAIPathSteering, GameLib.D3.ComponentInterface); + + // + this.targetEntity = targetEntity; + this.steeringSpeed = steeringSpeed || 2.5; + this.maxSteerAngle = maxSteerAngle || 0.5; + + this.raycastVehicleComponent = null; + + this.debugArrows = {}; +}; + +///////////////////////// Methods to override ////////////////////////// + +GameLib.D3.ComponentVehicleAIPathSteering.prototype.onSetParentEntity = function( + parentScene, + parentEntity +) { + this.raycastVehicleComponent = parentEntity.getComponent(GameLib.D3.RaycastVehicle); + this.parentEntity = parentEntity; + + if(!this.raycastVehicleComponent) { + console.warn("NO RAYCAST VEHICLE FOUND!"); + } +}; + +GameLib.D3.ComponentVehicleAIPathSteering.prototype.onUpdate = function( + deltaTime, + parentEntity +) { + + if(this.targetEntity && this.raycastVehicleComponent) { + + var v1 = new THREE.Vector3( + this.parentEntity.position.x, + this.parentEntity.position.y, + this.parentEntity.position.z + ); + + var v2 = new THREE.Vector3( + this.targetEntity.position.x, + this.targetEntity.position.y, + this.targetEntity.position.z + ); + + + // get forward vector of the car. + var v3 = new THREE.Vector3( + 1, + 0, + 0 + ); + + var q1 = new THREE.Quaternion( + this.parentEntity.quaternion.x, + this.parentEntity.quaternion.y, + this.parentEntity.quaternion.z, + this.parentEntity.quaternion.w + ); + + var q2 = new THREE.Quaternion( + this.targetEntity.quaternion.x, + this.targetEntity.quaternion.y, + this.targetEntity.quaternion.z, + this.targetEntity.quaternion.w + ); + + var v1ToV2 = v2.sub(v1); + var forward = v3.applyQuaternion(q1).normalize(); + + var v1v2cpy = new THREE.Vector3( + v1ToV2.x, + v1ToV2.y, + v1ToV2.z + ).applyQuaternion(q2).normalize(); + + v1v2cpy.y = 0; + v1v2cpy = v1v2cpy.normalize(); + + var forwardcpy = new THREE.Vector3( + forward.x, + 0, + forward.z + ).normalize(); + + var cos = v1v2cpy.dot(forwardcpy); + var angleRadians = Math.acos(cos); + var steerAngleModifier = GameLib.D3.Vector3.AngleDirection( + forwardcpy, + v1v2cpy, + new GameLib.D3.Vector3( + 0, + 1, + 0 + ) + ); + var steerAngle = Math.min(angleRadians, this.maxSteerAngle) * steerAngleModifier; + + if(isNaN(steerAngle)) { + console.log("NOT A NUMBER", steerAngle); + } + + // check if forward & movedirection are pointing in two different directions + /* if(cos < 0) { + console.log("movedirection & forward are pointing in different directions"); + }*/ + + //if(steerAngle > 0.002 || steerAngle < -0.002) { + this.raycastVehicleComponent.instance.setSteeringValue(steerAngle, 0); + this.raycastVehicleComponent.instance.setSteeringValue(steerAngle, 1); + //} + + this.raycastVehicleComponent.instance.applyEngineForce(-2000, 2); + this.raycastVehicleComponent.instance.applyEngineForce(-2000, 3); + + + // - - - - - - - - - - - DEBUG ARROW 1 - - - - - - - - - + { + if(!this.debugArrows.v1) { + this.debugArrows.v1 = this.debugArrows.v1 || {}; + } + + if(!this.debugArrows.v1.mesh) { + + var geometryTHREE = new THREE.Geometry(); + var wireframeMesh = new THREE.Mesh( + geometryTHREE, + new THREE.MeshBasicMaterial( + { + color: 0xff0000, + wireframe: true, + opacity: 1 + } + ) + ); + + this.debugArrows.v1.mesh = wireframeMesh; + + sys.game.scenes["MainScene"].instance.add(this.debugArrows.v1.mesh); + } + + if(this.debugArrows.v1.arrow) { + this.debugArrows.v1.mesh.remove(this.debugArrows.v1.arrow); + } + + var len = v1ToV2.length(); + this.debugArrows.v1.arrow = new THREE.ArrowHelper( + v1ToV2.normalize(), + + new THREE.Vector3( + this.parentEntity.position.x, + this.parentEntity.position.y, + this.parentEntity.position.z + ), + + len || 100, + + new THREE.Color( + 0, + 1, + 0 + ) + ); + + this.debugArrows.v1.mesh.add( this.debugArrows.v1.arrow ); + } + + // - - - - - - - - - - - DEBUG ARROW 2 - - - - - - - - - + { + if(!this.debugArrows.v2) { + this.debugArrows.v2 = this.debugArrows.v2 || {}; + } + + if(!this.debugArrows.v2.mesh) { + + var geometryTHREE = new THREE.Geometry(); + var wireframeMesh = new THREE.Mesh( + geometryTHREE, + new THREE.MeshBasicMaterial( + { + color: 0xff0000, + wireframe: true, + opacity: 1 + } + ) + ); + + this.debugArrows.v2.mesh = wireframeMesh; + + sys.game.scenes["MainScene"].instance.add(this.debugArrows.v2.mesh); + } + + if(this.debugArrows.v2.arrow) { + this.debugArrows.v2.mesh.remove(this.debugArrows.v2.arrow); + } + + this.debugArrows.v2.arrow = new THREE.ArrowHelper( + forward, + + new THREE.Vector3( + this.parentEntity.position.x, + this.parentEntity.position.y, + this.parentEntity.position.z + ), + + 12, + + new THREE.Color( + 1.0, + 0.0, + 0.0 + ) + ); + + this.debugArrows.v2.mesh.add( this.debugArrows.v2.arrow ); + } + } +}; \ No newline at end of file diff --git a/src/game-lib-game.js b/src/game-lib-game.js index 8f70283..c6217f2 100644 --- a/src/game-lib-game.js +++ b/src/game-lib-game.js @@ -26,8 +26,7 @@ GameLib.D3.Game.prototype.processPhysics = function ( GameLib.D3.Game.prototype.render = function( dt, - renderer, - camera + renderer ) { for(var s in this.scenes) { var scene = this.scenes[s]; diff --git a/src/game-lib-vector-3.js b/src/game-lib-vector-3.js index 8ca7cfe..32ecee8 100644 --- a/src/game-lib-vector-3.js +++ b/src/game-lib-vector-3.js @@ -98,6 +98,28 @@ GameLib.D3.Vector3.prototype.lerp = function ( v, alpha ) { ); }; +GameLib.D3.Vector3.prototype.distanceTo = function(v) { + var dx = this.x - v.x, + dy = this.y - v.y, + dz = this.z - v.z; + + return Math.sqrt(dx * dx + dy * dy + dz * dz); +}; + +GameLib.D3.Vector3.AngleDirection = function(forward, directionToCheck, up) { + var perp = forward.cross(directionToCheck); + var dir = perp.dot(up); + + if (dir > 0.0) { + return 1.0; + } else if (dir < 0.0) { + return -1.0; + } else { + return 0.0; + } + +}; + GameLib.D3.Vector3.prototype.multiply = function (s) { if (s instanceof GameLib.D3.Vector3) { this.x *= s.x; diff --git a/src/game-lib-world.js b/src/game-lib-world.js index 1052503..44d0f65 100644 --- a/src/game-lib-world.js +++ b/src/game-lib-world.js @@ -837,7 +837,7 @@ GameLib.D3.World.prototype.fixupTriangleMeshShape = function( // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Decide if we want to create new rigid bodies, or create a compound mesh + // Decide if we want to create new rigiwyd bodies, or create a compound mesh // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - for(var e in bFaceIndexed) { @@ -850,6 +850,10 @@ GameLib.D3.World.prototype.fixupTriangleMeshShape = function( } else { var body = new GameLib.D3.RigidBody(this.engine, 0, 12); + + //TODO: this is just a hack. + body.instance.collisionFilterGroup = 1 | 2; // puts this body in two groups. + body.addShape(shape); this.addRigidBody(body); } From 51ba9a855d4eb45dbe6d3b2b9b4b1876002c578e Mon Sep 17 00:00:00 2001 From: polygonboutique Date: Thu, 17 Nov 2016 10:24:59 +0100 Subject: [PATCH 02/11] merge part 1 / 2 --- src/game-lib-a.js | 6 +++--- src/game-lib-component-colorlerp.js | 10 ++++++++-- ...ame-lib-component-vehicle-ai-object-avoidance.js | 13 ++++++++++--- src/game-lib-component-vehicle-ai-path-boid.js | 13 ++++++++++--- src/game-lib-component-vehicle-ai-path-steering.js | 13 ++++++++++--- 5 files changed, 41 insertions(+), 14 deletions(-) diff --git a/src/game-lib-a.js b/src/game-lib-a.js index cacc090..b133e51 100644 --- a/src/game-lib-a.js +++ b/src/game-lib-a.js @@ -17,9 +17,9 @@ if (typeof Q == 'undefined') { if (typeof _ == 'undefined') { if (typeof require == 'undefined') { - console.warn('You need the lowdash library for the GameLib.D3'); - throw new Error('You need the lowdash library for the GameLib.D3'); + console.warn('You need the lodash library for the GameLib.D3'); + throw new Error('You need the lodash library for the GameLib.D3'); } - var _ = require('_'); + var _ = require('lodash'); } \ No newline at end of file diff --git a/src/game-lib-component-colorlerp.js b/src/game-lib-component-colorlerp.js index 57eaad8..5a46a6c 100644 --- a/src/game-lib-component-colorlerp.js +++ b/src/game-lib-component-colorlerp.js @@ -1,10 +1,16 @@ GameLib.D3.ComponentColorLerp = function( - componentId, + id, + name, startColor, endColor, lerpSpeed ) { - this.componentId = componentId || GameLib.D3.Tools.RandomId(); + this.id = id|| GameLib.D3.Tools.RandomId(); + if (typeof name == 'undefined') { + name = this.constructor.name; + } + this.name = name; + this.parentEntity = null; // Todo: this should be executed somewhere in game-lib-z, so that we don't execute it on every construction of an object. diff --git a/src/game-lib-component-vehicle-ai-object-avoidance.js b/src/game-lib-component-vehicle-ai-object-avoidance.js index 64daedc..1d920b5 100644 --- a/src/game-lib-component-vehicle-ai-object-avoidance.js +++ b/src/game-lib-component-vehicle-ai-object-avoidance.js @@ -1,14 +1,21 @@ /** * - * @param componentId + * @param id + * @param name * @param physicsWorld * @constructor */ GameLib.D3.ComponentVehicleAIObjectAvoidance = function( - componentId, + id, + name, physicsWorld ) { - this.componentId = componentId || GameLib.D3.Tools.RandomId(); + this.id = id|| GameLib.D3.Tools.RandomId(); + if (typeof name == 'undefined') { + name = this.constructor.name; + } + this.name = name; + this.parentEntity = null; GameLib.D3.Utils.Extend(GameLib.D3.ComponentVehicleAIObjectAvoidance, GameLib.D3.ComponentInterface); diff --git a/src/game-lib-component-vehicle-ai-path-boid.js b/src/game-lib-component-vehicle-ai-path-boid.js index d432d36..0c213cb 100644 --- a/src/game-lib-component-vehicle-ai-path-boid.js +++ b/src/game-lib-component-vehicle-ai-path-boid.js @@ -1,16 +1,23 @@ /** * - * @param componentId + * @param id + * @param name * @param targetEntity GameLib.D3.Entity * @param nodePath * @constructor */ GameLib.D3.ComponentVehicleAIPathBoid = function( - componentId, + id, + name, targetEntity, nodePath ) { - this.componentId = componentId || GameLib.D3.Tools.RandomId(); + this.id = id|| GameLib.D3.Tools.RandomId(); + if (typeof name == 'undefined') { + name = this.constructor.name; + } + this.name = name; + this.parentEntity = null; GameLib.D3.Utils.Extend(GameLib.D3.ComponentVehicleAIPathBoid, GameLib.D3.ComponentInterface); diff --git a/src/game-lib-component-vehicle-ai-path-steering.js b/src/game-lib-component-vehicle-ai-path-steering.js index 1f95eb7..7e28974 100644 --- a/src/game-lib-component-vehicle-ai-path-steering.js +++ b/src/game-lib-component-vehicle-ai-path-steering.js @@ -1,18 +1,25 @@ /** * - * @param componentId + * @param id + * @param name * @param targetEntity GameLib.D3.Entity * @param steeringSpeed * @param maxSteerAngle * @constructor */ GameLib.D3.ComponentVehicleAIPathSteering = function( - componentId, + id, + name, targetEntity, steeringSpeed, maxSteerAngle ) { - this.componentId = componentId || GameLib.D3.Tools.RandomId(); + this.id = id|| GameLib.D3.Tools.RandomId(); + if (typeof name == 'undefined') { + name = this.constructor.name; + } + this.name = name; + this.parentEntity = null; // Todo: this should be executed somewhere in game-lib-z, so that we don't execute it on every construction of an object. From d5f51b0af8a3bd39e2ba9fe9192b57a40f088934 Mon Sep 17 00:00:00 2001 From: polygonboutique Date: Thu, 17 Nov 2016 16:04:03 +0100 Subject: [PATCH 03/11] ai stuff --- ...b-component-vehicle-ai-object-avoidance.js | 191 ++++++++++++++++-- ...-lib-component-vehicle-ai-path-steering.js | 7 +- src/game-lib-vector-2.js | 105 +++++++++- src/game-lib-vector-3.js | 171 +++++++++++----- 4 files changed, 386 insertions(+), 88 deletions(-) diff --git a/src/game-lib-component-vehicle-ai-object-avoidance.js b/src/game-lib-component-vehicle-ai-object-avoidance.js index 1d920b5..473f709 100644 --- a/src/game-lib-component-vehicle-ai-object-avoidance.js +++ b/src/game-lib-component-vehicle-ai-object-avoidance.js @@ -54,7 +54,7 @@ GameLib.D3.ComponentVehicleAIObjectAvoidance.prototype.onSetParentEntity = funct // this should be configurable inside the editor var carBoxScaleModifier = { x : 3 / 4, y : 1 / 2, z : 0.90 }; - var sensorLength = 0.65; + var sensorLength = 7.0; var sensorColor = new THREE.Color(0, 0, 1); // . . . . . . . . . . FRONT . . . . . . . . . . @@ -75,7 +75,7 @@ GameLib.D3.ComponentVehicleAIObjectAvoidance.prototype.onSetParentEntity = funct sensorPositionOffset : new THREE.Vector3( boundingBox.max.x * this.parentEntity.mesh.scale.x * carBoxScaleModifier.x, boundingBox.max.z * this.parentEntity.mesh.scale.z * carBoxScaleModifier.z, - boundingBox.max.y * this.parentEntity.mesh.scale.y * carBoxScaleModifier.y // this is still swapped with y, because cannon. + 0//boundingBox.max.y * this.parentEntity.mesh.scale.y * carBoxScaleModifier.y // this is still swapped with y, because cannon. ) } ); @@ -97,7 +97,7 @@ GameLib.D3.ComponentVehicleAIObjectAvoidance.prototype.onSetParentEntity = funct sensorPositionOffset : new THREE.Vector3( boundingBox.max.x * this.parentEntity.mesh.scale.x * carBoxScaleModifier.x, -boundingBox.max.z * this.parentEntity.mesh.scale.z * carBoxScaleModifier.z, - boundingBox.max.y * this.parentEntity.mesh.scale.y * carBoxScaleModifier.y // this is still swapped with y, because cannon. + 0//boundingBox.max.y * this.parentEntity.mesh.scale.y * carBoxScaleModifier.y // this is still swapped with y, because cannon. ) } ); @@ -142,7 +142,7 @@ GameLib.D3.ComponentVehicleAIObjectAvoidance.prototype.onSetParentEntity = funct sensorPositionOffset : new THREE.Vector3( boundingBox.max.x * this.parentEntity.mesh.scale.x * carBoxScaleModifier.x, boundingBox.max.z * this.parentEntity.mesh.scale.z * carBoxScaleModifier.z, - boundingBox.max.y * this.parentEntity.mesh.scale.y * carBoxScaleModifier.y // this is still swapped with y, because cannon. + 0//boundingBox.max.y * this.parentEntity.mesh.scale.y * carBoxScaleModifier.y // this is still swapped with y, because cannon. ) } ); @@ -164,7 +164,7 @@ GameLib.D3.ComponentVehicleAIObjectAvoidance.prototype.onSetParentEntity = funct sensorPositionOffset : new THREE.Vector3( boundingBox.max.x * this.parentEntity.mesh.scale.x * carBoxScaleModifier.x, -boundingBox.max.z * this.parentEntity.mesh.scale.z * carBoxScaleModifier.z, - boundingBox.max.y * this.parentEntity.mesh.scale.y * carBoxScaleModifier.y // this is still swapped with y, because cannon. + 0//boundingBox.max.y * this.parentEntity.mesh.scale.y * carBoxScaleModifier.y // this is still swapped with y, because cannon. ) } ); @@ -185,7 +185,7 @@ GameLib.D3.ComponentVehicleAIObjectAvoidance.prototype.onSetParentEntity = funct sensorPositionOffset : new THREE.Vector3( boundingBox.max.x * this.parentEntity.mesh.scale.x * carBoxScaleModifier.x, boundingBox.max.z * this.parentEntity.mesh.scale.z * carBoxScaleModifier.z, - boundingBox.max.y * this.parentEntity.mesh.scale.y * carBoxScaleModifier.y // this is still swapped with y, because cannon. + 0//boundingBox.max.y * this.parentEntity.mesh.scale.y * carBoxScaleModifier.y // this is still swapped with y, because cannon. ) } ); @@ -207,7 +207,7 @@ GameLib.D3.ComponentVehicleAIObjectAvoidance.prototype.onSetParentEntity = funct sensorPositionOffset : new THREE.Vector3( boundingBox.max.x * this.parentEntity.mesh.scale.x * carBoxScaleModifier.x, -boundingBox.max.z * this.parentEntity.mesh.scale.z * carBoxScaleModifier.z, - boundingBox.max.y * this.parentEntity.mesh.scale.y * carBoxScaleModifier.y // this is still swapped with y, because cannon. + 0//boundingBox.max.y * this.parentEntity.mesh.scale.y * carBoxScaleModifier.y // this is still swapped with y, because cannon. ) } ); @@ -228,7 +228,7 @@ GameLib.D3.ComponentVehicleAIObjectAvoidance.prototype.onSetParentEntity = funct sensorPositionOffset : new THREE.Vector3( boundingBox.max.x * this.parentEntity.mesh.scale.x * carBoxScaleModifier.x, boundingBox.max.z * this.parentEntity.mesh.scale.z * carBoxScaleModifier.z, - boundingBox.max.y * this.parentEntity.mesh.scale.y * carBoxScaleModifier.y // this is still swapped with y, because cannon. + 0//boundingBox.max.y * this.parentEntity.mesh.scale.y * carBoxScaleModifier.y // this is still swapped with y, because cannon. ) } ); @@ -250,7 +250,7 @@ GameLib.D3.ComponentVehicleAIObjectAvoidance.prototype.onSetParentEntity = funct sensorPositionOffset : new THREE.Vector3( boundingBox.max.x * this.parentEntity.mesh.scale.x * carBoxScaleModifier.x, -boundingBox.max.z * this.parentEntity.mesh.scale.z * carBoxScaleModifier.z, - boundingBox.max.y * this.parentEntity.mesh.scale.y * carBoxScaleModifier.y // this is still swapped with y, because cannon. + 0//boundingBox.max.y * this.parentEntity.mesh.scale.y * carBoxScaleModifier.y // this is still swapped with y, because cannon. ) } ); @@ -265,15 +265,27 @@ GameLib.D3.ComponentVehicleAIObjectAvoidance.prototype.onUpdate = function( parentEntity ) { if(this.raycastVehicleComponent && this.physicsWorld) { + // debug + this.debugArrows.avgDirection = this.debugArrows.avgDirection || {}; + this.debugArrows.sensors = this.debugArrows.sensors || []; + var vehicleVelocity = this.parentEntity.getComponent(GameLib.D3.RigidBody).instance.velocity; var vehicleVelocityLength = 12; - // shoot rays for each sensor & check collisions. var world = this.physicsWorld.instance; var result = new CANNON.RaycastResult(); + this.debugArrows.avgDirection.vector = new THREE.Vector3(); + for(var s = 0, l = this.sensors.length; s < l; ++s) { + + // debug + if(!this.debugArrows.sensors[s]) { + this.debugArrows.sensors[s] = {}; + } + + var sensor = this.sensors[s]; var from = new THREE.Vector3( @@ -306,7 +318,7 @@ GameLib.D3.ComponentVehicleAIObjectAvoidance.prototype.onUpdate = function( this.parentEntity.quaternion.y, this.parentEntity.quaternion.z, this.parentEntity.quaternion.w - )).normalize().multiplyScalar(sensor.sensorLength * vehicleVelocityLength); + )).normalize().multiplyScalar(sensor.sensorLength); var toC = new CANNON.Vec3( @@ -329,23 +341,124 @@ GameLib.D3.ComponentVehicleAIObjectAvoidance.prototype.onUpdate = function( if(result.hasHit) { sensor.sensorColor = new THREE.Color(1, 0, 0); + + var direction = new THREE.Vector3( + sensor.sensorDirection.x, + sensor.sensorDirection.y, + sensor.sensorDirection.z + ).applyQuaternion(new THREE.Quaternion( + this.parentEntity.quaternion.x, + this.parentEntity.quaternion.y, + this.parentEntity.quaternion.z, + this.parentEntity.quaternion.w + )).normalize(); + + /*var reflection = direction.reflect( + new THREE.Vector3( + result.hitNormalWorld.x, + result.hitNormalWorld.y, + result.hitNormalWorld.z + ) + ).normalize();*/ + + var reflection = direction.reflect( + new THREE.Vector3( + result.hitPointWorld.x, + result.hitPointWorld.y, + result.hitPointWorld.z + ).normalize().cross(direction) + ).normalize().negate(); + + var origin = new THREE.Vector3( + this.parentEntity.position.x, + this.parentEntity.position.y, + this.parentEntity.position.z + ).add(new THREE.Vector3( + sensor.sensorPositionOffset.x, + sensor.sensorPositionOffset.y, + sensor.sensorPositionOffset.z + ).applyQuaternion(new THREE.Quaternion( + this.parentEntity.quaternion.x, + this.parentEntity.quaternion.y, + this.parentEntity.quaternion.z, + this.parentEntity.quaternion.w + ))); + + var moveDirection = direction.add(reflection).setY(0).normalize(); + this.debugArrows.avgDirection.vector = this.debugArrows.avgDirection.vector.add(moveDirection); + + if(this.debugArrows.sensors[s].intersectionArrow && this.debugArrows.sensors[s].mesh) { + this.debugArrows.sensors[s].mesh.remove(this.debugArrows.sensors[s].intersectionArrow); + } + + if(this.debugArrows.sensors[s].mesh){ + + var arrow = new THREE.ArrowHelper( + + moveDirection, + + origin, + + 22, + + new THREE.Color(1, 1, 0) + ); + + this.debugArrows.sensors[s].intersectionArrow = arrow; + this.debugArrows.sensors[s].mesh.add(this.debugArrows.sensors[s].intersectionArrow); + } + } else { sensor.sensorColor = new THREE.Color(0, 0, 1); + + if(this.debugArrows.sensors[s].intersectionArrow && this.debugArrows.sensors[s].mesh) { + this.debugArrows.sensors[s].mesh.remove(this.debugArrows.sensors[s].intersectionArrow); + } } } + this.debugArrows.avgDirection.vector = this.debugArrows.avgDirection.vector.normalize(); + // draw the avg move direction + + if(!this.debugArrows.avgDirection.mesh) { + this.debugArrows.avgDirection.mesh = new THREE.Mesh( + new THREE.Geometry(), + new THREE.MeshBasicMaterial( + { + color : 0x00ffff, + wireframe : true + } + ) + ); + + sys.game.scenes["MainScene"].instance.add(this.debugArrows.avgDirection.mesh); + } + + if(this.debugArrows.avgDirection.arrow && this.debugArrows.avgDirection.mesh) { + this.debugArrows.avgDirection.mesh.remove(this.debugArrows.avgDirection.arrow); + } + + this.debugArrows.avgDirection.arrow = new THREE.ArrowHelper( + this.debugArrows.avgDirection.vector, + + new THREE.Vector3( + this.parentEntity.position.x, + this.parentEntity.position.y, + this.parentEntity.position.z + ), + + 12, + + this.debugArrows.avgDirection.mesh.material.color + ); + + this.debugArrows.avgDirection.mesh.add(this.debugArrows.avgDirection.arrow); // draw sensors { - this.debugArrows.sensors = this.debugArrows.sensors || []; - for(var s = 0, l = this.sensors.length; s < l; ++s) { - if(!this.debugArrows.sensors[s]) { - this.debugArrows.sensors[s] = {}; - } - if(!this.debugArrows.sensors[s].mesh) { var geometry = new THREE.Geometry(); @@ -399,7 +512,7 @@ GameLib.D3.ComponentVehicleAIObjectAvoidance.prototype.onUpdate = function( this.parentEntity.quaternion.w ))), - sensorLength * vehicleVelocityLength, + sensorLength, sensor.sensorColor ); @@ -407,5 +520,47 @@ GameLib.D3.ComponentVehicleAIObjectAvoidance.prototype.onUpdate = function( this.debugArrows.sensors[s].mesh.add(this.debugArrows.sensors[s].arrow); } } + + + // . . . . . . . . . . . . correct the path . . . . . . . . . . . . . . + if( this.debugArrows.avgDirection.vector.x != 0 + || this.debugArrows.avgDirection.vector.y != 0 + || this.debugArrows.avgDirection.vector.z != 0 + ) { + + // get forward direction OR better the velocity angle of the car + + var avgMoveVector = this.debugArrows.avgDirection.vector; + var forward = new THREE.Vector3( + 1, + 0, + 0 + ).applyQuaternion(new THREE.Quaternion( + this.parentEntity.quaternion.x, + this.parentEntity.quaternion.y, + this.parentEntity.quaternion.z, + this.parentEntity.quaternion.w + )).setY(0).normalize(); + + // get angle and steer. + var cos = avgMoveVector.dot(forward); + + var angleRadians = Math.acos(cos); + var steerAngleModifier = GameLib.D3.Vector3.AngleDirection( + forward, + avgMoveVector, + new GameLib.D3.Vector3( + 0, + 1, + 0 + ) + ); + + var steerAngle = Math.min(angleRadians, 0.5) * steerAngleModifier; + + this.raycastVehicleComponent.instance.setSteeringValue(steerAngle, 0); + this.raycastVehicleComponent.instance.setSteeringValue(steerAngle, 1); + } + } }; \ No newline at end of file diff --git a/src/game-lib-component-vehicle-ai-path-steering.js b/src/game-lib-component-vehicle-ai-path-steering.js index 7e28974..095b02b 100644 --- a/src/game-lib-component-vehicle-ai-path-steering.js +++ b/src/game-lib-component-vehicle-ai-path-steering.js @@ -135,10 +135,6 @@ GameLib.D3.ComponentVehicleAIPathSteering.prototype.onUpdate = function( this.raycastVehicleComponent.instance.setSteeringValue(steerAngle, 1); //} - this.raycastVehicleComponent.instance.applyEngineForce(-2000, 2); - this.raycastVehicleComponent.instance.applyEngineForce(-2000, 3); - - // - - - - - - - - - - - DEBUG ARROW 1 - - - - - - - - - { if(!this.debugArrows.v1) { @@ -240,4 +236,7 @@ GameLib.D3.ComponentVehicleAIPathSteering.prototype.onUpdate = function( this.debugArrows.v2.mesh.add( this.debugArrows.v2.arrow ); } } + + this.raycastVehicleComponent.instance.applyEngineForce(-3500, 2); + this.raycastVehicleComponent.instance.applyEngineForce(-3500, 3); }; \ No newline at end of file diff --git a/src/game-lib-vector-2.js b/src/game-lib-vector-2.js index 460e5a9..1d18583 100644 --- a/src/game-lib-vector-2.js +++ b/src/game-lib-vector-2.js @@ -1,15 +1,6 @@ GameLib.D3.Vector2 = function(x, y) { - - this.x = 0; - this.y = 0; - - if (x) { - this.x = x; - } - - if (y) { - this.y = y; - } + this.x = x || 0; + this.y = y || 0; }; GameLib.D3.Vector2.prototype.copy = function() { @@ -25,3 +16,95 @@ GameLib.D3.Vector2.prototype.equals = function(v) { ((this.y == v.x) && (this.x == v.y))); }; + +GameLib.D3.Vector2.prototype.add = function(v) { + return new GameLib.D3.Vector2( + this.x + v.x, + this.y + v.y + ); +}; + +GameLib.D3.Vector2.prototype.subtract = function(v) { + return new GameLib.D3.Vector2( + this.x - v.x, + this.y - v.y + ); +}; + +GameLib.D3.Vector2.prototype.multiply = function(v) { + if (v instanceof GameLib.D3.Vector2) { + return new GameLib.D3.Vector2( + this.x * v.x, + this.y * v.y + ); + } else if (isNumber(v)) { + return new GameLib.D3.Vector2( + this.x * v, + this.y * v + ); + } +}; + +GameLib.D3.Vector2.prototype.divide = function(v) { + if (v instanceof GameLib.D3.Vector2) { + return new GameLib.D3.Vector2( + this.x * (1.0 / v.x), + this.y * (1.0 / v.y) + ); + } else if (isNumber(v)) { + var invS = 1.0 / v; + return new GameLib.D3.Vector2( + this.x * invS, + this.y * invS + ); + } +}; + +GameLib.D3.Vector2.prototype.clone = function() { + return new GameLib.D3.Vector2( + this.x, + this.y + ); +}; + +GameLib.D3.Vector2.prototype.copy = function(v) { + this.x = v.x; + this.y = v.y; +}; + +GameLib.D3.Vector2.prototype.set = function(x, y) { + this.x = x; + this.y = y; +}; + +GameLib.D3.Vector2.prototype.clamp = function(min, max) { + return new GameLib.D3.Vector2( + Math.max(min.x, Math.min(max.x, this.x)), + Math.max(min.y, Math.min(max.y, this.y)) + ); +}; + +GameLib.D3.Vector2.prototype.length = function() { + return Math.sqrt(this.x * this.x + this.y * this.y); +}; + +GameLib.D3.Vector2.prototype.dot = function(v) { + return this.x * v.x + this.y * v.y; +}; + +GameLib.D3.Vector2.prototype.normalize = function() { + return this.multiply(1.0 / this.length()); +}; + +GameLib.D3.Vector2.prototype.angle = function() { + var angle = Math.atan2(this.y, this.x); + if ( angle < 0 ) angle += 2 * Math.PI; + return angle; +}; + +GameLib.D3.Vector2.prototype.lerp = function ( v, alpha ) { + return new GameLib.D3.Vector2( + this.x + ( v.x - this.x ) * alpha, + this.y + ( v.y - this.y ) * alpha + ); +}; \ No newline at end of file diff --git a/src/game-lib-vector-3.js b/src/game-lib-vector-3.js index 32ecee8..fc7ebf5 100644 --- a/src/game-lib-vector-3.js +++ b/src/game-lib-vector-3.js @@ -1,35 +1,15 @@ GameLib.D3.Vector3 = function(x, y, z) { - - this.x = 0; - this.y = 0; - this.z = 0; - - if (x) { - this.x = x; - } - - if (y) { - this.y = y; - } - - if (z) { - this.z = z; - } + this.x = x || 0; + this.y = y || 0; + this.z = z || 0; }; GameLib.D3.Vector3.prototype.subtract = function (v) { - - if (v instanceof GameLib.D3.Vector3) { - this.x -= v.x; - this.y -= v.y; - this.z -= v.z; - } - - if (v instanceof GameLib.D3.Vector4) { - console.warn("trying to subtract vector of bigger length (4 vs 3))"); - } - - return this; + return new GameLib.D3.Vector3( + this.x - v.x, + this.y - v.y, + this.z - v.z + ); }; GameLib.D3.Vector3.prototype.cross = function (v) { @@ -40,21 +20,11 @@ GameLib.D3.Vector3.prototype.cross = function (v) { ); }; -GameLib.D3.Vector3.prototype.negative = function () { - this.x *= -1; - this.y *= -1; - this.z *= -1; - return this; -}; GameLib.D3.Vector3.clockwise = function (u, v, w, viewPoint) { - var normal = GameLib.D3.Vector3.normal(u, v, w); - var uv = u.copy(); - var winding = normal.dot(uv.subtract(viewPoint)); - return (winding > 0); }; @@ -65,10 +35,8 @@ GameLib.D3.Vector3.normal = function (u, v, w) { }; GameLib.D3.Vector3.prototype.lookAt = function (at, up) { - var lookAtMatrix = GameLib.D3.Matrix4.lookAt(this, at, up); - - this.multiply(lookAtMatrix); + return this.multiply(lookAtMatrix); }; GameLib.D3.Vector3.prototype.translate = function (v) { @@ -78,6 +46,14 @@ GameLib.D3.Vector3.prototype.translate = function (v) { return this; }; +GameLib.D3.Vector3.prototype.add = function (v) { + return new GameLib.D3.Vector3( + this.x + v.x, + this.y + v.y, + this.z + v.z + ); +}; + GameLib.D3.Vector3.prototype.squared = function () { return this.x * this.x + this.y * this.y + this.z * this.z; }; @@ -102,10 +78,12 @@ GameLib.D3.Vector3.prototype.distanceTo = function(v) { var dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z; - return Math.sqrt(dx * dx + dy * dy + dz * dz); }; +/** + * @return {number} + */ GameLib.D3.Vector3.AngleDirection = function(forward, directionToCheck, up) { var perp = forward.cross(directionToCheck); var dir = perp.dot(up); @@ -122,21 +100,51 @@ GameLib.D3.Vector3.AngleDirection = function(forward, directionToCheck, up) { GameLib.D3.Vector3.prototype.multiply = function (s) { if (s instanceof GameLib.D3.Vector3) { - this.x *= s.x; - this.y *= s.y; - this.z *= s.z; + + return new GameLib.D3.Vector3( + this.x * s.x, + this.y * s.y, + this.z * s.z + ) + } else if (s instanceof GameLib.D3.Matrix4) { + + var x = s.rows[0].x * this.x + s.rows[0].y * this.y + s.rows[0].z * this.z + s.rows[0].w; + var y = s.rows[1].x * this.x + s.rows[1].y * this.y + s.rows[1].z * this.z + s.rows[1].w; + var z = s.rows[2].x * this.x + s.rows[2].y * this.y + s.rows[2].z * this.z + s.rows[2].w; + + return new GameLib.D3.Vector3( + x, + y, + z + ); + + } else if (s instanceof GameLib.D3.Matrix3) { + var x = s.rows[0].x * this.x + s.rows[0].y * this.y + s.rows[0].z * this.z; var y = s.rows[1].x * this.x + s.rows[1].y * this.y + s.rows[1].z * this.z; var z = s.rows[2].x * this.x + s.rows[2].y * this.y + s.rows[2].z * this.z; - this.x = x; - this.y = y; - this.z = z; + + return new GameLib.D3.Vector3( + x, + y, + z + ); + + } else if(isNumber(s)) { + + return new GameLib.D3.Vector3( + this.x * s, + this.y * s, + this.z * s + ); + } else { + console.log("functionality not implemented - please do this"); throw new Error("not implemented"); + return this; } - return this; }; @@ -145,20 +153,73 @@ GameLib.D3.Vector3.prototype.dot = function (v) { }; GameLib.D3.Vector3.prototype.normalize = function () { - var EPSILON = 0.000001; - var v2 = this.squared(); if (v2 < EPSILON) { return this; //do nothing for zero vector } - var invLength = 1 / Math.sqrt(v2); + var invLength = 1.0 / Math.sqrt(v2); + return new GameLib.D3.Vector3( + this.x * invLength, + this.y * invLength, + this.z * invLength + ); +}; - this.x *= invLength; - this.y *= invLength; - this.z *= invLength; +GameLib.D3.Vector3.prototype.clone = function () { + return new GameLib.D3.Vector3( + this.x, + this.y, + this.z + ); +}; + +GameLib.D3.Vector3.prototype.applyQuaternion = function(q) { + var x = this.x, y = this.y, z = this.z; + var qx = q.x, qy = q.y, qz = q.z, qw = q.w; + + // calculate quat * vector + + var ix = qw * x + qy * z - qz * y; + var iy = qw * y + qz * x - qx * z; + var iz = qw * z + qx * y - qy * x; + var iw = - qx * x - qy * y - qz * z; + + // calculate result * inverse quat + + return new GameLib.D3.Vector3( + ix * qw + iw * - qx + iy * - qz - iz * - qy, + iy * qw + iw * - qy + iz * - qx - ix * - qz, + iz * qw + iw * - qz + ix * - qy - iy * - qx + ); +}; + +GameLib.D3.Vector3.prototype.clamp = function(min, max) { + this.x = Math.max( min.x, Math.min( max.x, this.x ) ); + this.y = Math.max( min.y, Math.min( max.y, this.y ) ); + this.z = Math.max( min.z, Math.min( max.z, this.z ) ); return this; }; + +GameLib.D3.Vector3.prototype.negate = function() { + this.x = -this.x; + this.y = -this.y; + this.z = -this.z; + return this; +}; + +GameLib.D3.Vector3.prototype.length = function() { + return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z ); +}; + +GameLib.D3.Vector3.prototype.reflect = function(normal) { + return this.sub( v1.copy( normal ).multiply( 2 * this.dot( normal ) ) ); +}; + +GameLib.D3.Vector3.prototype.angleTo = function (v) { + var theta = this.dot( v ) / ( Math.sqrt( this.lengthSq() * v.lengthSq() ) ); + return Math.acos( exports.Math.clamp( theta, - 1, 1 ) ); +}; \ No newline at end of file From 144d62a8fe0450703120585f3195ef20c1cf0a0f Mon Sep 17 00:00:00 2001 From: polygonboutique Date: Fri, 18 Nov 2016 10:50:19 +0100 Subject: [PATCH 04/11] some changes --- ...me-lib-component-vehicle-ai-object-avoidance.js | 14 +++++++------- src/game-lib-component-vehicle-ai-path-steering.js | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/game-lib-component-vehicle-ai-object-avoidance.js b/src/game-lib-component-vehicle-ai-object-avoidance.js index 473f709..112965f 100644 --- a/src/game-lib-component-vehicle-ai-object-avoidance.js +++ b/src/game-lib-component-vehicle-ai-object-avoidance.js @@ -421,7 +421,7 @@ GameLib.D3.ComponentVehicleAIObjectAvoidance.prototype.onUpdate = function( this.debugArrows.avgDirection.vector = this.debugArrows.avgDirection.vector.normalize(); // draw the avg move direction - if(!this.debugArrows.avgDirection.mesh) { + /*if(!this.debugArrows.avgDirection.mesh) { this.debugArrows.avgDirection.mesh = new THREE.Mesh( new THREE.Geometry(), new THREE.MeshBasicMaterial( @@ -437,9 +437,9 @@ GameLib.D3.ComponentVehicleAIObjectAvoidance.prototype.onUpdate = function( if(this.debugArrows.avgDirection.arrow && this.debugArrows.avgDirection.mesh) { this.debugArrows.avgDirection.mesh.remove(this.debugArrows.avgDirection.arrow); - } + }*/ - this.debugArrows.avgDirection.arrow = new THREE.ArrowHelper( + /*this.debugArrows.avgDirection.arrow = new THREE.ArrowHelper( this.debugArrows.avgDirection.vector, new THREE.Vector3( @@ -451,12 +451,12 @@ GameLib.D3.ComponentVehicleAIObjectAvoidance.prototype.onUpdate = function( 12, this.debugArrows.avgDirection.mesh.material.color - ); + );*/ - this.debugArrows.avgDirection.mesh.add(this.debugArrows.avgDirection.arrow); + //this.debugArrows.avgDirection.mesh.add(this.debugArrows.avgDirection.arrow); // draw sensors - { + /*{ for(var s = 0, l = this.sensors.length; s < l; ++s) { if(!this.debugArrows.sensors[s].mesh) { @@ -519,7 +519,7 @@ GameLib.D3.ComponentVehicleAIObjectAvoidance.prototype.onUpdate = function( this.debugArrows.sensors[s].mesh.add(this.debugArrows.sensors[s].arrow); } - } + }*/ // . . . . . . . . . . . . correct the path . . . . . . . . . . . . . . diff --git a/src/game-lib-component-vehicle-ai-path-steering.js b/src/game-lib-component-vehicle-ai-path-steering.js index 095b02b..5e3e341 100644 --- a/src/game-lib-component-vehicle-ai-path-steering.js +++ b/src/game-lib-component-vehicle-ai-path-steering.js @@ -135,7 +135,7 @@ GameLib.D3.ComponentVehicleAIPathSteering.prototype.onUpdate = function( this.raycastVehicleComponent.instance.setSteeringValue(steerAngle, 1); //} - // - - - - - - - - - - - DEBUG ARROW 1 - - - - - - - - - + /*// - - - - - - - - - - - DEBUG ARROW 1 - - - - - - - - - { if(!this.debugArrows.v1) { this.debugArrows.v1 = this.debugArrows.v1 || {}; @@ -234,7 +234,7 @@ GameLib.D3.ComponentVehicleAIPathSteering.prototype.onUpdate = function( ); this.debugArrows.v2.mesh.add( this.debugArrows.v2.arrow ); - } + }*/ } this.raycastVehicleComponent.instance.applyEngineForce(-3500, 2); From eafd6fc01ee0ca9394fd1934856f9a0ec0714938 Mon Sep 17 00:00:00 2001 From: polygonboutique Date: Mon, 21 Nov 2016 08:20:47 +0100 Subject: [PATCH 05/11] height maps --- src/game-lib-game.js | 2 +- src/game-lib-vector-3.js | 6 ++++++ src/game-lib-world.js | 7 ++++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/game-lib-game.js b/src/game-lib-game.js index c6217f2..592b74f 100644 --- a/src/game-lib-game.js +++ b/src/game-lib-game.js @@ -44,7 +44,7 @@ GameLib.D3.Game.prototype.update = function( for(var w in scene.worlds) { var world = scene.worlds[w]; // NOTE: We are calling the step function with a variable timestep! - world.step(dt); + world.step(fixedDt, dt); } scene.update(dt); diff --git a/src/game-lib-vector-3.js b/src/game-lib-vector-3.js index fc7ebf5..d6396e7 100644 --- a/src/game-lib-vector-3.js +++ b/src/game-lib-vector-3.js @@ -66,6 +66,12 @@ GameLib.D3.Vector3.prototype.copy = function () { ); }; +GameLib.D3.Vector3.prototype.set = function (x, y, z) { + this.x = x; + this.y = y; + this.z = z; +}; + GameLib.D3.Vector3.prototype.lerp = function ( v, alpha ) { return new GameLib.D3.Vector3( this.x + ( v.x - this.x ) * alpha, diff --git a/src/game-lib-world.js b/src/game-lib-world.js index 44d0f65..76eb306 100644 --- a/src/game-lib-world.js +++ b/src/game-lib-world.js @@ -103,8 +103,13 @@ GameLib.D3.World.prototype.addVehicle = function( }; GameLib.D3.World.prototype.step = function( - timeStep + fixedStep, + dtStep ) { + this.instance.step(fixedStep, dtStep, 3); + return; + + // todo: figure out, why this call to internal step is more stable for trimesh collisions..... //this.instance.internalStep(timeStep); //return; From 420dfc0edccf2019ea5d37b9f86d867b794d4fd6 Mon Sep 17 00:00:00 2001 From: polygonboutique Date: Mon, 21 Nov 2016 08:40:43 +0100 Subject: [PATCH 06/11] height maps --- src/game-lib-world.js | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/game-lib-world.js b/src/game-lib-world.js index 76eb306..07896d8 100644 --- a/src/game-lib-world.js +++ b/src/game-lib-world.js @@ -109,24 +109,18 @@ GameLib.D3.World.prototype.step = function( this.instance.step(fixedStep, dtStep, 3); return; - - // todo: figure out, why this call to internal step is more stable for trimesh collisions..... - //this.instance.internalStep(timeStep); - //return; - //console.log("this should not be called."); - - //var now = Date.now() / 1000; - var now = null; + var now = Date.now() / 1000.0; + //var now = null; if(!this.lastCallTime){ // last call time not saved, cant guess elapsed time. Take a simple step. - this.instance.step(timeStep); + this.instance.step(fixedStep); this.lastCallTime = now; return; } - var timeSinceLastCall = now - this.lastCallTime; + var timeSinceLastCall = (now - this.lastCallTime); - this.instance.step(timeStep, timeSinceLastCall); + this.instance.step(fixedStep, timeSinceLastCall, 4); this.lastCallTime = now; }; From 87bd9178bf5cd99d8b87cf8ddd489fb39b8cfdc8 Mon Sep 17 00:00:00 2001 From: polygonboutique Date: Mon, 21 Nov 2016 10:27:53 +0100 Subject: [PATCH 07/11] added swipe contorls to fly controls component --- src/game-lib-component-fly-controls.js | 41 ++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/game-lib-component-fly-controls.js b/src/game-lib-component-fly-controls.js index 37103b7..42434b2 100644 --- a/src/game-lib-component-fly-controls.js +++ b/src/game-lib-component-fly-controls.js @@ -134,6 +134,47 @@ GameLib.D3.ComponentFlyControls.prototype.onSetParentEntity = function( document.exitPointerLock = document.exitPointerLock || document.mozExitPointerLock || document.webkitExitPointerLock; } + // Swipe + + document.addEventListener('touchstart', function(evt) { + + component.xDown = evt.touches[0].clientX; + component.yDown = evt.touches[0].clientY; + + }, false); + + document.addEventListener('touchmove', function(evt) { + + if ( ! component.xDown || ! component.yDown ) { + return; + } + + var xUp = evt.touches[0].clientX; + var yUp = evt.touches[0].clientY; + + var xDiff = component.xDown - xUp; + var yDiff = component.yDown - yUp; + + if ( Math.abs( xDiff ) > Math.abs( yDiff ) ) {/*most significant*/ + if ( xDiff > 0 ) { + /* left swipe */ + } else { + /* right swipe */ + } + } else { + if ( yDiff > 0 ) { + /* up swipe */ + } else { + /* down swipe */ + } + } + + component.yaw -= xDiff * 0.002; + component.pitch -= yDiff * 0.002; + + }, false); + + // Mouse move document.addEventListener('mousemove', function (event) { From 2382e2a1d5560d6a0b3f3651a8151843eb6082f9 Mon Sep 17 00:00:00 2001 From: polygonboutique Date: Mon, 21 Nov 2016 14:36:38 +0100 Subject: [PATCH 08/11] track made out of cubes. --- gulpfile.js | 89 ++++++++++++++++++- src/game-lib-a.js | 11 ++- src/game-lib-component-mesh-permutation.js | 4 +- src/game-lib-component-trigger-box-box.js | 6 +- src/game-lib-component-trigger-box-sphere.js | 5 +- ...ame-lib-component-trigger-sphere-sphere.js | 5 +- ...b-component-vehicle-ai-object-avoidance.js | 6 +- ...-lib-component-vehicle-ai-path-steering.js | 4 +- 8 files changed, 121 insertions(+), 9 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index 3e4b80c..cb8c9f7 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -6,6 +6,7 @@ var plumber = require('gulp-plumber'); var istanbul = require('gulp-istanbul'); var mocha = require('gulp-mocha'); var watch = require('gulp-watch'); +var preprocessor = require('gulp-c-preprocessor'); gulp.task( 'build', @@ -58,10 +59,92 @@ gulp.task( } ); + +gulp.task('compileRuntime', ['build'], + function() { + gulp.src(['./build/defines/runtime.js', './build/game-lib.js']) + .pipe(concat('game-lib-runtime.js')) + .pipe(preprocessor( + { + // End of line character + endLine: '\n', + + // Escape '//#' & '/*#' comments (see extra/comments) + commentEscape: true, + + // Empty lines to add between code and included files + includeSpaces: 0, + + // Limit of empty following lines (0 = no limit) + emptyLinesLimit: 0, + + // Base path for including files + basePath: './', + + // Stop the compiler when an error ocurred ? + stopOnError: true, + + // Constants in #enum command must be in hexadecimal ? + enumInHex: true + + }) + ) + .pipe(minify({ + ext:{ + src:'.js', + min:'-min.js' + } + })) + .pipe(gulp.dest('./build/')); + } +); + +gulp.task('compileEditor', ['build'], + function() { + gulp.src(['./build/defines/editor.js', './build/game-lib.js']) + .pipe(concat('game-lib-editor.js')) + .pipe(preprocessor( + { + // End of line character + endLine: '\n', + + // Escape '//#' & '/*#' comments (see extra/comments) + commentEscape: true, + + // Empty lines to add between code and included files + includeSpaces: 0, + + // Limit of empty following lines (0 = no limit) + emptyLinesLimit: 0, + + // Base path for including files + basePath: './', + + // Stop the compiler when an error ocurred ? + stopOnError: true, + + // Constants in #enum command must be in hexadecimal ? + enumInHex: true + + }) + ) + .pipe(minify({ + ext:{ + src:'.js', + min:'-min.js' + } + })) + .pipe(gulp.dest('./build/')); + } +); + + gulp.task( 'default', [ - 'build' + 'build', + 'compileRuntime', + 'compileEditor' ], function() { return watch([ @@ -69,7 +152,9 @@ gulp.task( ], function() { gulp.start([ - 'build' + 'build', + 'compileRuntime', + 'compileEditor' ]); }) } diff --git a/src/game-lib-a.js b/src/game-lib-a.js index b133e51..a48500a 100644 --- a/src/game-lib-a.js +++ b/src/game-lib-a.js @@ -22,4 +22,13 @@ if (typeof _ == 'undefined') { } var _ = require('lodash'); -} \ No newline at end of file +} + + +//#ifdef RUNTIME__ +console.log("Loading runtime library..."); +//#endif + +//#ifdef EDITOR__ +console.log("Loading editor library..."); +//#endif \ No newline at end of file diff --git a/src/game-lib-component-mesh-permutation.js b/src/game-lib-component-mesh-permutation.js index 6ca117d..bc1740d 100644 --- a/src/game-lib-component-mesh-permutation.js +++ b/src/game-lib-component-mesh-permutation.js @@ -31,6 +31,7 @@ GameLib.D3.ComponentMeshPermutation = function ComponentMeshPermutation( GameLib.D3.Utils.Extend(GameLib.D3.ComponentMeshPermutation, GameLib.D3.ComponentInterface); }; +//#ifdef RUNTIME__ if(typeof THREE != "undefined") { ComponentMeshPermutation_quaternion = new THREE.Quaternion(); ComponentMeshPermutation_quaternionCopy = new THREE.Quaternion(); @@ -67,4 +68,5 @@ GameLib.D3.ComponentMeshPermutation.prototype.onLateUpdate = function( parentEntity.mesh.quaternion.copy(ComponentMeshPermutation_quaternion); parentEntity.mesh.scale.copy(ComponentMeshPermutation_scale); } -}; \ No newline at end of file +}; +//#endif \ No newline at end of file diff --git a/src/game-lib-component-trigger-box-box.js b/src/game-lib-component-trigger-box-box.js index 5aaa2cd..ec44abc 100644 --- a/src/game-lib-component-trigger-box-box.js +++ b/src/game-lib-component-trigger-box-box.js @@ -31,10 +31,12 @@ GameLib.D3.ComponentTriggerBoxBox = function ComponentTriggerBoxBox( this.onLeave = onLeave || null; this.onSetParent = onSetParent || null; - // runtime code + // defines code this.entitiesInside = []; }; + +//#ifdef RUNTIME__ if(typeof THREE != "undefined") { ComponentTriggerBoxBox_BB = new THREE.Box3(); ComponentTriggerBoxBox_BBEntity = new THREE.Box3(); @@ -89,6 +91,8 @@ GameLib.D3.ComponentTriggerBoxBox.prototype.onUpdate = function( } } }; +//#endif + GameLib.D3.ComponentTriggerBoxBox.prototype.onSetParentEntity = function( parentScene, diff --git a/src/game-lib-component-trigger-box-sphere.js b/src/game-lib-component-trigger-box-sphere.js index ad76876..9a45a94 100644 --- a/src/game-lib-component-trigger-box-sphere.js +++ b/src/game-lib-component-trigger-box-sphere.js @@ -29,10 +29,11 @@ GameLib.D3.ComponentTriggerBoxSphere = function ComponentTriggerBoxSphere( this.onLeave = onLeave || null; this.onSetParent = onSetParent || null; - // runtime code + // defines code this.entitiesInside = []; }; +//#ifdef RUNTIME__ if(typeof THREE != "undefined") { ComponentTriggerBoxSphere_TargetPosition_Vec3 = new THREE.Vector3(); ComponentTriggerBoxSphere_TargetRadius = 0.0; @@ -115,6 +116,8 @@ GameLib.D3.ComponentTriggerBoxSphere.prototype.onUpdate = function( } }; +//#endif + GameLib.D3.ComponentTriggerBoxSphere.prototype.onSetParentEntity = function( parentScene, parentEntity diff --git a/src/game-lib-component-trigger-sphere-sphere.js b/src/game-lib-component-trigger-sphere-sphere.js index 0f68a81..960515c 100644 --- a/src/game-lib-component-trigger-sphere-sphere.js +++ b/src/game-lib-component-trigger-sphere-sphere.js @@ -41,10 +41,11 @@ GameLib.D3.ComponentTriggerSphereSphere = function ComponentTriggerSphereSphere( this.onLeave = onLeave || null; this.onSetParent = onSetParent || null; - // runtime code + // defines code this.entitiesInside = []; }; +//#ifdef RUNTIME__ if(typeof THREE != "undefined") { ComponentTriggerSphereSphere_spherePosition_Vector3 = new THREE.Vector3(); ComponentTriggerSphereSphere_targetBoundingSpherePosition_Vector3 = new THREE.Vector3(); @@ -126,6 +127,8 @@ GameLib.D3.ComponentTriggerSphereSphere.prototype.onUpdate = function( } }; +//#endif + GameLib.D3.ComponentTriggerSphereSphere.prototype.onSetParentEntity = function( parentScene, parentEntity diff --git a/src/game-lib-component-vehicle-ai-object-avoidance.js b/src/game-lib-component-vehicle-ai-object-avoidance.js index 112965f..b768544 100644 --- a/src/game-lib-component-vehicle-ai-object-avoidance.js +++ b/src/game-lib-component-vehicle-ai-object-avoidance.js @@ -30,6 +30,8 @@ GameLib.D3.ComponentVehicleAIObjectAvoidance = function( console.log("constructor for : ComponentVehicleAIObjectAvoidance"); }; +//#ifdef RUNTIME__ + ///////////////////////////////////////////////////////////////////////// ///////////////////////// Methods to override /////////////////////////// ///////////////////////////////////////////////////////////////////////// @@ -563,4 +565,6 @@ GameLib.D3.ComponentVehicleAIObjectAvoidance.prototype.onUpdate = function( } } -}; \ No newline at end of file +}; + +//#endif \ No newline at end of file diff --git a/src/game-lib-component-vehicle-ai-path-steering.js b/src/game-lib-component-vehicle-ai-path-steering.js index 5e3e341..981c3a4 100644 --- a/src/game-lib-component-vehicle-ai-path-steering.js +++ b/src/game-lib-component-vehicle-ai-path-steering.js @@ -49,6 +49,7 @@ GameLib.D3.ComponentVehicleAIPathSteering.prototype.onSetParentEntity = function } }; +//#ifdef RUNTIME__ GameLib.D3.ComponentVehicleAIPathSteering.prototype.onUpdate = function( deltaTime, parentEntity @@ -239,4 +240,5 @@ GameLib.D3.ComponentVehicleAIPathSteering.prototype.onUpdate = function( this.raycastVehicleComponent.instance.applyEngineForce(-3500, 2); this.raycastVehicleComponent.instance.applyEngineForce(-3500, 3); -}; \ No newline at end of file +}; +//#endif \ No newline at end of file From 87471b1b12d81cb69be62fed3dc345165d39a15a Mon Sep 17 00:00:00 2001 From: polygonboutique Date: Tue, 22 Nov 2016 16:10:03 +0100 Subject: [PATCH 09/11] ABORT ABORT ABORT --- src/game-lib-vector-3.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/game-lib-vector-3.js b/src/game-lib-vector-3.js index d6396e7..6b5d802 100644 --- a/src/game-lib-vector-3.js +++ b/src/game-lib-vector-3.js @@ -12,6 +12,14 @@ GameLib.D3.Vector3.prototype.subtract = function (v) { ); }; +GameLib.D3.Vector3.prototype.sub = function (v) { + return new GameLib.D3.Vector3( + this.x - v.x, + this.y - v.y, + this.z - v.z + ); +}; + GameLib.D3.Vector3.prototype.cross = function (v) { return new GameLib.D3.Vector3( this.y * v.z - this.z * v.y, @@ -137,7 +145,7 @@ GameLib.D3.Vector3.prototype.multiply = function (s) { z ); - } else if(isNumber(s)) { + } else if(!isNaN(parseFloat(s)) && isFinite(s)) { return new GameLib.D3.Vector3( this.x * s, From 105e931035aa462e219e1be02cad1a44d3054e1a Mon Sep 17 00:00:00 2001 From: polygonboutique Date: Tue, 22 Nov 2016 17:07:02 +0100 Subject: [PATCH 10/11] follow path component --- src/game-lib-component-path-following.js | 88 +++++++++++++++++++ ...game-lib-component-vehicle-ai-path-boid.js | 59 ------------- 2 files changed, 88 insertions(+), 59 deletions(-) create mode 100644 src/game-lib-component-path-following.js delete mode 100644 src/game-lib-component-vehicle-ai-path-boid.js diff --git a/src/game-lib-component-path-following.js b/src/game-lib-component-path-following.js new file mode 100644 index 0000000..f8b577a --- /dev/null +++ b/src/game-lib-component-path-following.js @@ -0,0 +1,88 @@ +/** + * + * @param id + * @param name + * @param splineCurve3 + * @constructor + */ +GameLib.D3.ComponentPathFollowing = function ComponentPathFollowing( + id, + name, + splineCurve3 +) { + this.id = id || GameLib.D3.Tools.RandomId(); + + if (typeof name == 'undefined') { + name = this.constructor.name; + } + + this.name = name; + this.parentEntity = null; + this.splineCurve3 = splineCurve3; + + this.currentPathValue = 0.0; + + GameLib.D3.Utils.Extend(GameLib.D3.ComponentPathFollowing, GameLib.D3.ComponentInterface); +}; + +///////////////////////// Methods to override ////////////////////////// +GameLib.D3.ComponentPathFollowing.prototype.onUpdate = function( + deltaTime, + parentEntity +) { + + if(this.splineCurve3) { + + if(this.currentPathValue >= 1) { + this.currentPathValue = 0; + } + + //To maintain a constant speed, you use .getPointAt( t ) instead of .getPoint( t ). + //http://stackoverflow.com/questions/18400667/three-js-object-following-a-spline-path-rotation-tanget-issues-constant-sp + + var position = this.splineCurve3.getPointAt(this.currentPathValue); //getPointAt????? + var rotation = this.splineCurve3.getTangentAt(this.currentPathValue).normalize(); + + var up = new THREE.Vector3( 0, 1, 0 ); + + var axis = new THREE.Vector3(); + axis.crossVectors(up, rotation).normalize(); + var radians = Math.acos(up.dot(rotation)); + var quaternion = new THREE.Quaternion().setFromAxisAngle( axis, radians ); + + /* var quaternion = new THREE.Quaternion().setFromEuler( + new THREE.Euler( + rotation.x, + rotation.y, + rotation.z + ) + );*/ + + var offset = new THREE.Vector3(1, 0, 0); + offset = offset.applyQuaternion(quaternion).multiplyScalar(10.0); + + console.log("offset x", offset); + + // apply to parent rigidbody instead of direclty to the mesh. + parentEntity.position.x = position.x + offset.x; + parentEntity.position.y = position.y + offset.y; + parentEntity.position.z = position.z + offset.z; + + parentEntity.quaternion.x = quaternion.x; + parentEntity.quaternion.y = quaternion.y; + parentEntity.quaternion.z = quaternion.z; + parentEntity.quaternion.w = quaternion.w; + + this.currentPathValue += (0.5 * deltaTime); + + } +}; + +GameLib.D3.ComponentPathFollowing.prototype.onSetParentEntity = function( + parentScene, + parentEntity +) { + if(!this.splineCurve3) { + console.error("NO PATH GIVEN"); + } +}; \ No newline at end of file diff --git a/src/game-lib-component-vehicle-ai-path-boid.js b/src/game-lib-component-vehicle-ai-path-boid.js deleted file mode 100644 index 0c213cb..0000000 --- a/src/game-lib-component-vehicle-ai-path-boid.js +++ /dev/null @@ -1,59 +0,0 @@ -/** - * - * @param id - * @param name - * @param targetEntity GameLib.D3.Entity - * @param nodePath - * @constructor - */ -GameLib.D3.ComponentVehicleAIPathBoid = function( - id, - name, - targetEntity, - nodePath -) { - this.id = id|| GameLib.D3.Tools.RandomId(); - if (typeof name == 'undefined') { - name = this.constructor.name; - } - this.name = name; - - this.parentEntity = null; - GameLib.D3.Utils.Extend(GameLib.D3.ComponentVehicleAIPathBoid, GameLib.D3.ComponentInterface); - - this.targetEntity = targetEntity; - this.raycastVehicleComponent = null; - this.nodePath = nodePath; - this.debugArrows = {}; -}; - -///////////////////////////////////////////////////////////////////////// -///////////////////////// Methods to override /////////////////////////// -///////////////////////////////////////////////////////////////////////// -GameLib.D3.ComponentVehicleAIPathBoid.prototype.onSetParentEntity = function( - parentScene, - parentEntity -) { - this.parentEntity = parentEntity; - this.raycastVehicleComponent = parentEntity.getComponent(GameLib.D3.RaycastVehicle); - - if(!this.raycastVehicleComponent) { - console.warn("NO RAYCAST VEHICLE FOUND!"); - } -}; - -GameLib.D3.ComponentVehicleAIPathBoid.prototype.onUpdate = function( - deltaTime, - parentEntity -) { - if(this.targetEntity && this.raycastVehicleComponent && this.nodePath) { - - // boid code. - - var currentNodeIndex = this.nodePath.indexOf(this.targetEntity); - var distanceToCurrentNode = this.parentEntity.position.distanceTo(this.targetEntity.position); - - - - } -}; \ No newline at end of file From 6baed2483fbf72fd6e62305dd492c404b28fb0e5 Mon Sep 17 00:00:00 2001 From: polygonboutique Date: Wed, 23 Nov 2016 10:23:24 +0100 Subject: [PATCH 11/11] path controls component. main.js cleanup --- src/game-lib-component-path-controls.js | 130 +++++++++++++++++++++++ src/game-lib-component-path-following.js | 59 ++++++---- 2 files changed, 170 insertions(+), 19 deletions(-) create mode 100644 src/game-lib-component-path-controls.js diff --git a/src/game-lib-component-path-controls.js b/src/game-lib-component-path-controls.js new file mode 100644 index 0000000..5f67ed7 --- /dev/null +++ b/src/game-lib-component-path-controls.js @@ -0,0 +1,130 @@ +/** + * + * @param id + * @param name + * @constructor + */ +GameLib.D3.ComponentPathControls = function ComponentPathFollowing( + id, + name +) { + this.id = id || GameLib.D3.Tools.RandomId(); + + if (typeof name == 'undefined') { + name = this.constructor.name; + } + + this.name = name; + this.parentEntity = null; + + // runtime + this.pathFollowingComponent = null; + this.keyLeftPressed = false; + this.keyRightPressed = false; + this.keyForwardPressed = false; + this.keyBackPressed = false; + this.keyBreakPressed = false; + + GameLib.D3.Utils.Extend(GameLib.D3.ComponentPathControls, GameLib.D3.ComponentInterface); +}; + +///////////////////////// Methods to override ////////////////////////// +GameLib.D3.ComponentPathControls.prototype.onUpdate = function( + deltaTime, + parentEntity +) { + + if (this.keyForwardPressed) { // Forward [i] + this.pathFollowingComponent.direction = 1; + } else if (this.keyBackPressed){ + this.pathFollowingComponent.direction = -1; + } else { + this.pathFollowingComponent.direction = 0; + } + + // left right + if (this.keyLeftPressed) { // Left [j] + this.pathFollowingComponent.offset.x = 0; + this.pathFollowingComponent.offset.y = 0; + this.pathFollowingComponent.offset.z = 1; + // also: set offset scale + } else if (this.keyRightPressed) { // Right [l] + this.pathFollowingComponent.offset.x = 0; + this.pathFollowingComponent.offset.y = 0; + this.pathFollowingComponent.offset.z = -1; + // also: set offset scale + } +}; + +GameLib.D3.ComponentPathControls.prototype.onSetParentEntity = function( + parentScene, + parentEntity +) { + + this.pathFollowingComponent = parentEntity.getComponent(GameLib.D3.ComponentPathFollowing); + if(!this.pathFollowingComponent) { + console.error("ComponentPathControls. NO PATH FOLLOWING COMPONENT"); + } + + var component = this; + + document.addEventListener('keydown', function(event) { + + if (event.keyCode == 73) { // Forward [i] + + component.keyForwardPressed = true; + + } else if (event.keyCode == 75) { // Back [k] + + component.keyBackPressed = true; + + } + + if (event.keyCode == 74) { // Left [j] + + component.keyLeftPressed = true; + + } else if (event.keyCode == 76) { // Right [l] + + component.keyRightPressed = true; + + } + + if (event.keyCode == 66) { + + component.keyBreakPressed = true; + + } + + }, false); + + document.addEventListener('keyup', function(event) { + + if (event.keyCode == 73) { // Forward [i] + + component.keyForwardPressed = false; + + } else if (event.keyCode == 75) { // Back [k] + + component.keyBackPressed = false; + + } + + if (event.keyCode == 74) { // Left [j] + + component.keyLeftPressed = false; + + } else if (event.keyCode == 76) { // Right [l] + + component.keyRightPressed = false; + + } + + if (event.keyCode == 66) { + + component.keyBreakPressed = false; + + } + + }, false); +}; \ No newline at end of file diff --git a/src/game-lib-component-path-following.js b/src/game-lib-component-path-following.js index f8b577a..63d94ed 100644 --- a/src/game-lib-component-path-following.js +++ b/src/game-lib-component-path-following.js @@ -3,12 +3,18 @@ * @param id * @param name * @param splineCurve3 + * @param accel + * @param maxSpeed + * @param baseOffset * @constructor */ GameLib.D3.ComponentPathFollowing = function ComponentPathFollowing( id, name, - splineCurve3 + splineCurve3, + accel, + maxSpeed, + baseOffset ) { this.id = id || GameLib.D3.Tools.RandomId(); @@ -19,8 +25,17 @@ GameLib.D3.ComponentPathFollowing = function ComponentPathFollowing( this.name = name; this.parentEntity = null; this.splineCurve3 = splineCurve3; + this.maxSpeed = maxSpeed || 10.0; + this.accel = accel || 2.0; + this.baseOffset = baseOffset || new GameLib.D3.Vector3(); + + // runtime code this.currentPathValue = 0.0; + this.offset = new GameLib.D3.Vector3(); + this.currentSpeed = 0.0; + this.direction = 0; + GameLib.D3.Utils.Extend(GameLib.D3.ComponentPathFollowing, GameLib.D3.ComponentInterface); }; @@ -33,47 +48,53 @@ GameLib.D3.ComponentPathFollowing.prototype.onUpdate = function( if(this.splineCurve3) { - if(this.currentPathValue >= 1) { + if(this.currentPathValue >= 1 || this.currentPathValue < 0) { this.currentPathValue = 0; } //To maintain a constant speed, you use .getPointAt( t ) instead of .getPoint( t ). //http://stackoverflow.com/questions/18400667/three-js-object-following-a-spline-path-rotation-tanget-issues-constant-sp - var position = this.splineCurve3.getPointAt(this.currentPathValue); //getPointAt????? + var position = this.splineCurve3.getPointAt(this.currentPathValue); var rotation = this.splineCurve3.getTangentAt(this.currentPathValue).normalize(); - var up = new THREE.Vector3( 0, 1, 0 ); + var up = new THREE.Vector3(-1, 0, 0); var axis = new THREE.Vector3(); axis.crossVectors(up, rotation).normalize(); var radians = Math.acos(up.dot(rotation)); var quaternion = new THREE.Quaternion().setFromAxisAngle( axis, radians ); - /* var quaternion = new THREE.Quaternion().setFromEuler( - new THREE.Euler( - rotation.x, - rotation.y, - rotation.z - ) - );*/ + // move the entity + var t = deltaTime * this.accel; + t = t * t * t * (t * (6.0 * t - 15.0) + 10.0); + this.currentSpeed = this.currentSpeed + (this.maxSpeed * this.direction - this.currentSpeed) * t; - var offset = new THREE.Vector3(1, 0, 0); - offset = offset.applyQuaternion(quaternion).multiplyScalar(10.0); - - console.log("offset x", offset); + var transformedOffset = new THREE.Vector3( + this.baseOffset.x + this.offset.x, + this.baseOffset.y + this.offset.y, + this.baseOffset.z + this.offset.z + ).applyQuaternion(quaternion); // apply to parent rigidbody instead of direclty to the mesh. - parentEntity.position.x = position.x + offset.x; - parentEntity.position.y = position.y + offset.y; - parentEntity.position.z = position.z + offset.z; + parentEntity.position.x = position.x + transformedOffset.x; + parentEntity.position.y = position.y + transformedOffset.y; + parentEntity.position.z = position.z + transformedOffset.z; parentEntity.quaternion.x = quaternion.x; parentEntity.quaternion.y = quaternion.y; parentEntity.quaternion.z = quaternion.z; parentEntity.quaternion.w = quaternion.w; - this.currentPathValue += (0.5 * deltaTime); + console.log("this.currentSpeed", this.currentSpeed); + + this.currentPathValue += (this.currentSpeed); + + if(this.currentSpeed >= this.maxSpeed) { + this.currentSpeed = this.maxSpeed; + } else if (this.currentSpeed <= 0) { + this.currentSpeed = 0.0; + } } };