From 12ca785b427e17a9fb8f3826350bcfb503208fee Mon Sep 17 00:00:00 2001 From: polygonboutique Date: Fri, 4 Nov 2016 14:57:48 +0100 Subject: [PATCH] changes: - entities have position, quaternion & scale - components operate on those properties - entities apply those back to the three mesh - scene: renamed threeScene to instance - added camera component - added fly controls component - added scaleOffset to mesh permutation component --- src/game-lib-component-camera-follow.js | 18 ++ src/game-lib-component-camera.js | 31 ++++ src/game-lib-component-fly-controls.js | 201 +++++++++++++++++++++ src/game-lib-component-mesh-permutation.js | 12 +- src/game-lib-entity.js | 34 +++- src/game-lib-rigid-body.js | 12 +- src/game-lib-scene.js | 18 +- 7 files changed, 306 insertions(+), 20 deletions(-) create mode 100644 src/game-lib-component-camera-follow.js create mode 100644 src/game-lib-component-camera.js create mode 100644 src/game-lib-component-fly-controls.js diff --git a/src/game-lib-component-camera-follow.js b/src/game-lib-component-camera-follow.js new file mode 100644 index 0000000..15cd2d2 --- /dev/null +++ b/src/game-lib-component-camera-follow.js @@ -0,0 +1,18 @@ +GameLib.D3.ComponentCameraFollow = function( + componentId, + targetEntity +) { + 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.ComponentCameraFollow, GameLib.D3.ComponentInterface); +}; + +///////////////////////// Methods to override ////////////////////////// +GameLib.D3.ComponentCameraFollow.prototype.onUpdate = function( + deltaTime, + parentEntity +) { + // +}; \ No newline at end of file diff --git a/src/game-lib-component-camera.js b/src/game-lib-component-camera.js new file mode 100644 index 0000000..6d52332 --- /dev/null +++ b/src/game-lib-component-camera.js @@ -0,0 +1,31 @@ +GameLib.D3.ComponentCamera = function( + componentId, + threeCamera +) { + 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.ComponentCamera, GameLib.D3.ComponentInterface); + + // Component fields + this.threeCamera = threeCamera; +}; + +///////////////////////// Methods to override ////////////////////////// +GameLib.D3.ComponentCamera.prototype.onLateUpdate = function( + deltaTime, + parentEntity +) { + + var quat = new THREE.Quaternion( + parentEntity.quaternion.x, + parentEntity.quaternion.y, + parentEntity.quaternion.z, + parentEntity.quaternion.w + ); + + this.threeCamera.quaternion.copy(quat); + this.threeCamera.position.copy(parentEntity.position); + +}; \ No newline at end of file diff --git a/src/game-lib-component-fly-controls.js b/src/game-lib-component-fly-controls.js new file mode 100644 index 0000000..7c919c0 --- /dev/null +++ b/src/game-lib-component-fly-controls.js @@ -0,0 +1,201 @@ +GameLib.D3.ComponentFlyControls = function( + componentId +) { + 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.ComponentFlyControls, GameLib.D3.ComponentInterface); + + // Component fields + this.pitch = 0; + this.yaw = 0; + this.canRotate = false; + this.moveSpeed = 22.2; + this.moveForward = false; + this.moveBackward = false; + this.moveLeft = false; + this.moveRight = false; + this.moveUp = false; + this.moveDown = false; + +}; + +///////////////////////// Methods to override ////////////////////////// +GameLib.D3.ComponentFlyControls.prototype.onUpdate = function( + deltaTime, + parentEntity +) { + // Apply rotation + var rotation = new THREE.Euler( + this.pitch, + this.yaw, + 0, + "YXZ" + ); + + var quat = new THREE.Quaternion().setFromEuler( + rotation + ); + + parentEntity.quaternion.x = quat.x; + parentEntity.quaternion.y = quat.y; + parentEntity.quaternion.z = quat.z; + parentEntity.quaternion.w = quat.w; + + // Apply translation + var direction = new THREE.Vector3(0, 0, -1); + direction = direction.applyEuler(rotation).normalize(); + + if(this.moveForward) { + + parentEntity.position.x += direction.x * (deltaTime * this.moveSpeed); + parentEntity.position.y += direction.y * (deltaTime * this.moveSpeed); + parentEntity.position.z += direction.z * (deltaTime * this.moveSpeed); + + } else if(this.moveBackward) { + + parentEntity.position.x -= direction.x * (deltaTime * this.moveSpeed); + parentEntity.position.y -= direction.y * (deltaTime * this.moveSpeed); + parentEntity.position.z -= direction.z * (deltaTime * this.moveSpeed); + + } + + if(this.moveLeft) { + + var right = direction.cross(new THREE.Vector3(0, 1, 0)); + parentEntity.position.x -= right.x * (deltaTime * this.moveSpeed); + parentEntity.position.y -= right.y * (deltaTime * this.moveSpeed); + parentEntity.position.z -= right.z * (deltaTime * this.moveSpeed); + + } else if(this.moveRight) { + + var right = direction.cross(new THREE.Vector3(0, 1, 0)); + parentEntity.position.x += right.x * (deltaTime * this.moveSpeed); + parentEntity.position.y += right.y * (deltaTime * this.moveSpeed); + parentEntity.position.z += right.z * (deltaTime * this.moveSpeed); + + } + + // Absolute Y-Axis + if(this.moveUp) { + + parentEntity.position.y += (deltaTime * this.moveSpeed); + + } else if(this.moveDown) { + + parentEntity.position.y -= (deltaTime * this.moveSpeed); + + } +}; + +GameLib.D3.ComponentFlyControls.prototype.onSetParentEntity = function( + parentScene, + parentEntity +) { + var component = this; + + // Lock cursor + var havePointerLock = 'pointerLockElement' in document || 'mozPointerLockElement' in document || 'webkitPointerLockElement' in document; + var element = document.body; + + document.addEventListener('click', function(event) { + if(havePointerLock) { + if(event.button == 0) { + component.canRotate = true; + element.requestPointerLock(); + } else if(event.button == 2) { + component.canRotate = false; + document.exitPointerLock(); + } + } + }); + + if(havePointerLock) { + element.requestPointerLock = element.requestPointerLock || element.mozRequestPointerLock || element.webkitRequestPointerLock; + document.exitPointerLock = document.exitPointerLock || document.mozExitPointerLock || document.webkitExitPointerLock; + } + + + // Mouse move + document.addEventListener('mousemove', function (event) { + if(component.canRotate) { + var movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0; + var movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0; + + component.yaw -= movementX * 0.002; + component.pitch -= movementY * 0.002; + } + + // Save mouseCoords + sys.mouseCoords.set( + (event.clientX / window.innerWidth) * 2 - 1, + -(event.clientY / window.innerHeight) * 2 + 1 + ); + + }, false); + + + // Hook up keyboard controls + document.addEventListener('keydown', function (event) { + + switch (event.keyCode) { + case 87: // w + component.moveForward = true; + break; + + case 65: // a + component.moveLeft = true; + break; + + case 83: // s + component.moveBackward = true; + break; + + case 68: // d + component.moveRight = true; + break; + + case 32: // space + component.moveUp = true; + break; + + case 16: + component.moveDown = true; + break; + } + }, false); + + document.addEventListener('keyup', function (event) { + switch (event.keyCode) { + case 38: // up + case 87: // w + component.moveForward = false; + break; + + case 37: // left + case 65: // a + component.moveLeft = false; + break; + + case 40: // down + case 83: // s + component.moveBackward = false; + break; + + case 39: // right + case 68: // d + component.moveRight = false; + break; + + case 32: // space + component.moveUp = false; + break; + + case 16: + component.moveDown = false; + break; + } + }, false); + +}; \ 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 a90c2af..0ad3c36 100644 --- a/src/game-lib-component-mesh-permutation.js +++ b/src/game-lib-component-mesh-permutation.js @@ -1,13 +1,15 @@ GameLib.D3.ComponentMeshPermutation = function( componentId, positionOffset, - quaternionOffset + quaternionOffset, + scaleOffset ) { this.componentId = componentId || GameLib.D3.Tools.RandomId(); this.parentEntity = null; this.positionOffset = positionOffset || new GameLib.D3.Vector3(0, 0, 0); this.quaternionOffset = quaternionOffset || new GameLib.D3.Quaternion(0, 0, 0, 1); + this.scaleOffset = scaleOffset || new GameLib.D3.Vector3(0, 0, 0); // 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.ComponentMeshPermutation, GameLib.D3.ComponentInterface); @@ -36,7 +38,15 @@ GameLib.D3.ComponentMeshPermutation.prototype.onLateUpdate = function( offsetPosition.copy(this.positionOffset); position = position.add(offsetPosition.applyQuaternion(quaternionCopy)); + var scale = new THREE.Vector3(); + scale.copy(parentEntity.mesh.scale); + + var scaleOffset = new THREE.Vector3(); + scaleOffset.copy(this.scaleOffset); + scale = scale.add(scaleOffset); + parentEntity.mesh.position.copy(position); parentEntity.mesh.quaternion.copy(quaternion); + parentEntity.mesh.scale.copy(scale); } }; \ No newline at end of file diff --git a/src/game-lib-entity.js b/src/game-lib-entity.js index 60f745a..dc3c4b2 100644 --- a/src/game-lib-entity.js +++ b/src/game-lib-entity.js @@ -1,6 +1,9 @@ GameLib.D3.Entity = function( meshId, - componentIds + componentIds, + position, + quaternion, + scale ) { this.meshId = meshId; @@ -14,15 +17,20 @@ GameLib.D3.Entity = function( this.parentScene = null; this.mesh = null; - // todo: - // add position, rotation & scale properties to entity itself! + if(GameLib.D3.Utils.UndefinedOrNull(position)) { + position = new GameLib.D3.Vector3(0, 0, 0); + } + this.position = position; - this.permutate = { - offset : { - position : null, - quaternion : null - } - }; + if(GameLib.D3.Utils.UndefinedOrNull(quaternion)) { + quaternion = new GameLib.D3.Vector4(0, 0, 0, 1); + } + this.quaternion = quaternion; + + if(GameLib.D3.Utils.UndefinedOrNull(scale)) { + scale = new GameLib.D3.Vector3(1, 1, 1); + } + this.scale = scale; }; /** @@ -40,6 +48,12 @@ GameLib.D3.Entity.prototype.update = function( } } + if(this.mesh) { + this.mesh.position.set(this.position.x, this.position.y, this.position.z); + this.mesh.quaternion.set(this.quaternion.x, this.quaternion.y, this.quaternion.z, this.quaternion.w); + this.mesh.scale.set(this.scale.x, this.scale.y, this.scale.z); + } + this.onUpdate(deltaTime); }; @@ -71,7 +85,7 @@ GameLib.D3.Entity.prototype.register = function( this.parentScene = parentScene; if(this.meshId != null && parentScene.meshIdToMesh[this.meshId]) { - parentScene.threeScene.add(parentScene.meshIdToMesh[this.meshId]); + parentScene.instance.add(parentScene.meshIdToMesh[this.meshId]); this.mesh = parentScene.meshIdToMesh[this.meshId]; } diff --git a/src/game-lib-rigid-body.js b/src/game-lib-rigid-body.js index 7e750b9..4c94abf 100644 --- a/src/game-lib-rigid-body.js +++ b/src/game-lib-rigid-body.js @@ -149,14 +149,20 @@ GameLib.D3.RigidBody.prototype.onUpdate = function( deltaTime, parentEntity ) { - if(parentEntity.mesh) { + if(parentEntity) { var quaternion = new THREE.Quaternion(); quaternion.copy(this.instance.quaternion); var position = new THREE.Vector3(); position.copy(this.instance.position); - parentEntity.mesh.position.copy(position); - parentEntity.mesh.quaternion.copy(quaternion); + parentEntity.position.x = position.x; + parentEntity.position.y = position.y; + parentEntity.position.z = position.z; + + parentEntity.quaternion.x = quaternion.x; + parentEntity.quaternion.y = quaternion.y; + parentEntity.quaternion.z = quaternion.z; + parentEntity.quaternion.w = quaternion.w; } }; \ No newline at end of file diff --git a/src/game-lib-scene.js b/src/game-lib-scene.js index 25d4f4d..b8457e1 100644 --- a/src/game-lib-scene.js +++ b/src/game-lib-scene.js @@ -81,10 +81,7 @@ GameLib.D3.Scene = function( } this.entities = entities; - // todo: remove this from the scene class - // changes - this.threeScene = new THREE.Scene(); - this.threeScene.render = true; + this.instance = this.createInstance(); // assoc array this.meshIdToMesh = {}; @@ -93,6 +90,15 @@ GameLib.D3.Scene = function( this.componentIdToComponent = {}; }; + +GameLib.D3.Scene.prototype.createInstance = function ( + +) { + var scene = new THREE.Scene(); + scene.render = true; + return scene; +}; + /** * Loads a scene directly from the API * @param gameLibScene GameLib.D3.Scene @@ -599,7 +605,7 @@ GameLib.D3.Scene.prototype.render = function( renderer, camera ) { - renderer.render(this.threeScene, camera); + renderer.render(this.instance, camera); }; /** @@ -647,5 +653,5 @@ GameLib.D3.Scene.prototype.registerComponent = function( GameLib.D3.Scene.prototype.registerLight = function( light ) { - this.threeScene.add(light); + this.instance.add(light); }; \ No newline at end of file