"atomic component"; var glmatrix = require("gl-matrix"); var quat = glmatrix.quat; var vec3 = glmatrix.vec3; var MATH_RAD_TO_DEG = 360 / Math.PI exports.component = function(self) { var BRAKE_FORCE = 0.028; var MOVE_FORCE = 0.3; var camNode var charNode var charBody var charAnimCtrl var cameraToCharVector var camera var screenWidth var screenHeight self.start = function() { charNode = self.node camera = charNode.scene.getMainCamera() camNode = camera.node cameraToCharVector = [0, 0, 0] var charPos = [0, 0, 0] // We define the cameraToCharVector as the vector with origin in the character // and that ends up on the camera position. // Initial vector value is computed from the initial state of the scene. vec3.add(cameraToCharVector, camNode.getWorldPosition(), vec3.negate(charPos, charNode.getWorldPosition())) charBody = charNode.getComponent("RigidBody") charBody.angularFactor = [0, 0, 0] charAnimCtrl = charNode.getComponent("AnimationController"); // Set the rigidbody to signal collision also when in rest, so that we get ground collisions properly charBody.collisionEventMode = Atomic.COLLISION_ALWAYS; screenWidth = Atomic.graphics.width screenHeight = Atomic.graphics.height } self.update = function(timeStep) { var mousePos = Atomic.input.getMousePosition() var inputData = updateInputData() // Update movement & animation var velocity = charBody.getLinearVelocity(); var moveDir = [0, 0, 0]; if (inputData.moveUp) { vec3.add(moveDir, moveDir, [0, 0, -1]); } if (inputData.moveDown) { vec3.add(moveDir, moveDir, [0, 0, 1]); } if (inputData.moveLeft) { vec3.add(moveDir, moveDir, [1, 0, 0]); } if (inputData.moveRight) { vec3.add(moveDir, moveDir, [-1, 0, 0]); } // Scale the vector to match the acceleration of the character vec3.normalize(moveDir, moveDir) vec3.scale(moveDir, moveDir, MOVE_FORCE); charBody.applyImpulse(moveDir) // Velocity on the XZ plane var planeVelocity = [velocity[0], 0.0, velocity[2]] vec3.negate(planeVelocity, planeVelocity) vec3.scale(planeVelocity, planeVelocity, BRAKE_FORCE) charBody.applyImpulse(planeVelocity) var newCamPos = [0, 0, 0] vec3.add(newCamPos, charNode.getWorldPosition(), cameraToCharVector) camNode.setWorldPosition(newCamPos) var scene = self.node.scene var octree = scene.getComponent("Octree") var origin = camNode.getWorldPosition() var mouseX = inputData.mousePos[0] var mouseY = inputData.mousePos[1] // Create a ray from the origin (users POV) that passes through the (mouseX, mouseY) point // in the near plane of the camera. var ray = camera.getScreenRay(mouseX / screenWidth, mouseY / screenHeight) // Perform raycasting var rayCastHits = octree.rayCastSingle(ray, Atomic.RAY_TRIANGLE, 250, Atomic.DRAWABLE_GEOMETRY) // If we hit something we take into account the XZ coordinates of the // hit object and get the vector describing the direction to which the // character is heading if (rayCastHits) { var charHeadingPlaneXZ = [0, 0,- 1] var rayHitPosPlaneXZ = rayCastHits.position rayHitPosPlaneXZ[1] = 0 var charPosPlaneXZ = charNode.getWorldPosition() charPosPlaneXZ[1] = 0 var charHeading = vec3.add([0, 0, 0], rayHitPosPlaneXZ, vec3.negate([0, 0, 0], charPosPlaneXZ)) charHeadingPlaneXZ = charHeading charHeadingPlaneXZ[1] = 0 var initHeading = [0, 0, -1] vec3.normalize(initHeading, initHeading) vec3.normalize(charHeadingPlaneXZ, charHeadingPlaneXZ) // Create a rotation quaternion to describe rotation from characters initial // heading to the computed char heading direction var rotationQ = quat.rotationTo([0, 0, 0, 0], [0, 0, -1], charHeadingPlaneXZ) // Here there is a little gotcha with quaternion math and JS // The engine expects the quaternion components to be ordered // differently than gl-matrix order so we just switch the order to match // the engines before appling rotation. quat.set(rotationQ, rotationQ[3], rotationQ[0], rotationQ[1], rotationQ[2]) charNode.rotation = rotationQ } var idle = !(Math.abs(velocity[0]) >= 0.01 || Math.abs(velocity[2]) > 0.01) if (idle) charAnimCtrl.playExclusive("Idle", 0, true, 0.0) else charAnimCtrl.playExclusive("Run", 0, true, 0.0) } } function updateInputData() { var input = Atomic.input; moveUp = false; moveDown = false; moveLeft = false; moveRight = false; button0 = false; button1 = false; //check input if (input.getKeyDown(Atomic.KEY_W) || input.getKeyDown(Atomic.KEY_UP)) moveUp = true; if (input.getKeyDown(Atomic.KEY_S) || input.getKeyDown(Atomic.KEY_DOWN)) moveDown = true; if (input.getKeyDown(Atomic.KEY_A) || input.getKeyDown(Atomic.KEY_LEFT)) moveLeft = true; if (input.getKeyDown(Atomic.KEY_D) || input.getKeyDown(Atomic.KEY_RIGHT)) moveRight = true; if (input.getKeyPress(Atomic.KEY_F)) button0 = true; if (input.getKeyPress(Atomic.KEY_SPACE)) button1 = true; return { moveUp: moveUp, moveDown: moveDown, moveLeft: moveLeft, moveRight: moveRight, mousePos: input.getMousePosition() } }