-- Move speed (m/s) MOVE_SPEED_NORMAL = 1 MOVE_SPEED_FAST = 5 -- Move flags MOVE_FORWARD = 1 MOVE_BACKWARD = 2 MOVE_RIGHT = 3 MOVE_LEFT = 4 _useScriptCamera = false _forwardSpeed = 0 _sideSpeed = 0 _touch = Vector2.new() _delta = Vector2.new() _move = Vector2.new() _moveFlags = { false, false, false, false } _yaw = 0 _pitch = 0 _moveFast = false function camera_setActive(flag) _useScriptCamera = flag if _useScriptCamera then Game.getInstance():setMultiTouch(true) _scene = Scene.getScene() _cameraNode = _scene:getActiveCamera():getNode() -- Set initial camera angles local eulers = camera_quatToEuler(_cameraNode:getRotation()) _yaw = eulers:y() _pitch = eulers:x() else -- Release scene and camera _scene = nil _cameraNode = nil end end function camera_setSpeed(normal, fast) MOVE_SPEED_NORMAL = normal MOVE_SPEED_FAST = fast end function camera_update(elapsedTime) if not _useScriptCamera then return end if USE_PHYSICS_CHARACTER then local char = _scene:findNode("camera"):getCollisionObject():asCharacter() local speed = MOVE_SPEED_NORMAL if _moveFast then speed = MOVE_SPEED_FAST end -- Forward motion if _moveFlags[MOVE_FORWARD] then char:setForwardVelocity(speed) elseif _moveFlags[MOVE_BACKWARD] then char:setForwardVelocity(-speed) else char:setForwardVelocity(0) end -- Strafing if _moveFlags[MOVE_LEFT] then char:setRightVelocity(-speed) elseif _moveFlags[MOVE_RIGHT] then char:setRightVelocity(speed) else char:setRightVelocity(0) end else -- Manual camera movement local secs = elapsedTime / 1000.0 _move:set(0,0) -- Forward motion if _moveFlags[MOVE_FORWARD] then _move:y(1) elseif _moveFlags[MOVE_BACKWARD] then _move:y(-1) end -- Strafing if _moveFlags[MOVE_LEFT] then _move:x(-1) elseif _moveFlags[MOVE_RIGHT] then _move:x(1) end if not _move:isZero() then local speed = MOVE_SPEED_NORMAL if _moveFast then speed = MOVE_SPEED_FAST end _move:normalize():scale(secs * speed) camera_moveForward(_move:y()); camera_moveRight(_move:x()); end end end function camera_keyEvent(evt, key) if not _useScriptCamera then return end if evt == Keyboard.KEY_PRESS then if key == Keyboard.KEY_W or key == Keyboard.KEY_CAPITAL_W then _moveFlags[MOVE_FORWARD] = true elseif key == Keyboard.KEY_S or key == Keyboard.KEY_CAPITAL_S then _moveFlags[MOVE_BACKWARD] = true elseif key == Keyboard.KEY_A or key == Keyboard.KEY_CAPITAL_A then _moveFlags[MOVE_LEFT] = true elseif key == Keyboard.KEY_D or key == Keyboard.KEY_CAPITAL_D then _moveFlags[MOVE_RIGHT] = true elseif key == Keyboard.KEY_SHIFT then _moveFast = true end elseif evt == Keyboard.KEY_RELEASE then if key == Keyboard.KEY_W or key == Keyboard.KEY_CAPITAL_W then _moveFlags[MOVE_FORWARD] = false elseif key == Keyboard.KEY_S or key == Keyboard.KEY_CAPITAL_S then _moveFlags[MOVE_BACKWARD] = false elseif key == Keyboard.KEY_A or key == Keyboard.KEY_CAPITAL_A then _moveFlags[MOVE_LEFT] = false elseif key == Keyboard.KEY_D or key == Keyboard.KEY_CAPITAL_D then _moveFlags[MOVE_RIGHT] = false elseif key == Keyboard.KEY_SHIFT then _moveFast = false end end end function camera_touchEvent(evt, x, y, contactIndex) if not _useScriptCamera then return end if evt == Touch.TOUCH_PRESS then if contactIndex == 0 then _touch:set(x, y) elseif contactIndex == 1 then _moveFlags[MOVE_FORWARD] = true elseif contactIndex == 2 then _moveFast = true end elseif evt == Touch.TOUCH_RELEASE then if contactIndex == 1 then _moveFlags[MOVE_FORWARD] = false elseif contactIndex == 2 then _moveFast = false end elseif evt == Touch.TOUCH_MOVE then if contactIndex == 0 then _delta:set(x - _touch:x(), y - _touch:y()) _touch:set(x, y) _pitch = _pitch - math.rad(_delta:y() * 0.5) _yaw = _yaw - math.rad(_delta:x() * 0.5) _cameraNode:setRotation(Quaternion.identity()) _cameraNode:rotateY(_yaw) _cameraNode:rotateX(_pitch) end end end function camera_moveForward(by) local v = _cameraNode:getForwardVector() v:normalize():scale(by) _cameraNode:translate(v) end function camera_moveRight(by) local v = _cameraNode:getRightVector() v:normalize():scale(by) _cameraNode:translate(v) end function camera_quatToEuler(quat) local qx = quat:x() local qy = quat:y() local qz = quat:z() local qw = quat:w() local qx2 = qx * qx local qy2 = qy * qy local qz2 = qz * qz local qw2 = qw * qw local rotx = 0 local roty = 0 local rotz = 0 if (qx*qy + qz*qw) == 0.5 then rotx = 0 roty = 2 * math.atan2(qx, qw) elseif (qx*qy + qz*qw) == -0.5 then rotx = 0 roty = -2 * math.atan2(qx, qw) else rotx = math.atan2(2*qx*qw-2*qy*qz , 1 - 2*qx2 - 2*qz2) roty = math.atan2(2*qy*qw-2*qx*qz , 1 - 2*qy2 - 2*qz2) end rotz = math.asin(2*qx*qy + 2*qz*qw) return Vector3.new(rotx, roty, rotz) end