// Handles moving pod around during steer mode // Based on move.js // These parameters control the motor's speed and strength. var MAX_MOTOR_TIMESCALE = 0.5; var PUSHING_MOTOR_TIMESCALE = 0.25; var BRAKING_MOTOR_TIMESCALE = 0.125; var VERY_LONG_TIME = 1000000.0; var AVATAR_SPEED = 4.0; var MIN_BRAKING_SPEED = 0.2; var motorAccumulator = {x:0.0, y:0.0, z:0.0}; var isBraking = false; var MAX_AUTO_REPEAT_DELAY = 3; var KEY_RELEASE_EXPIRY_MSEC = 100; PodMover = function() { print("================ PodMover Constructor"); // NOTE: the avatar's default orientation is such that "forward" is along the -zAxis, and "left" is along -xAxis. this.controlKeys = { "UP" : new KeyInfo({x: 0.0, y: 0.0, z:-1.0}), "DOWN" : new KeyInfo({x: 0.0, y: 0.0, z: 1.0}), "SHIFT+LEFT" : new KeyInfo({x:-1.0, y: 0.0, z: 0.0}), "SHIFT+RIGHT": new KeyInfo({x: 1.0, y: 0.0, z: 0.0}), "w" : new KeyInfo({x: 0.0, y: 0.0, z:-1.0}), "s" : new KeyInfo({x: 0.0, y: 0.0, z: 1.0}), "a" : new KeyInfo({x: 0.0, y: 1.0, z: 0.0}), "d" : new KeyInfo({x: 0.0, y:-1.0, z: 0.0}) }; this.pressTimestamps = {}; } // KeyInfo class contructor: function KeyInfo(contribution) { this.motorContribution = contribution; // Vec3 contribution of this key toward motorVelocity this.releaseTime = new Date(); // time when this button was released this.pressTime = new Date(); // time when this button was pressed this.isPressed = false; } // list of last timestamps when various buttons were last pressed PodMover.prototype.keyPressEvent = function(event) { var keyName = event.text; if (event.isShifted) { keyName = "SHIFT+" + keyName; } var key = this.controlKeys[keyName]; if (key != undefined) { key.pressTime = new Date(); // set the last pressTimestap element to undefined (MUCH faster than removing from the list) this.pressTimestamps[keyName] = undefined; var msec = key.pressTime.valueOf() - key.releaseTime.valueOf(); if (!key.isPressed) { // add this key's effect to the motorAccumulator motorAccumulator = Vec3.sum(motorAccumulator, key.motorContribution); key.isPressed = true; } } } PodMover.prototype.keyReleaseEvent = function(event) { //printDebug("POD MOVER KEY RELEASE"); var keyName = event.text; if (event.isShifted) { keyName = "SHIFT+" + keyName; } var key = this.controlKeys[keyName]; if (key != undefined) { this.pressTimestamps[keyName] = new Date(); key.releaseTime = new Date(); var msec = key.releaseTime.valueOf() - key.pressTime.valueOf(); } } PodMover.prototype.updateMotor = function(deltaTime) { var now = new Date(); for (var keyName in this.pressTimestamps) { var t = this.pressTimestamps[keyName]; if (t != undefined) { var msec = now.valueOf() - t.valueOf(); if (msec > KEY_RELEASE_EXPIRY_MSEC) { motorAccumulator = Vec3.subtract(motorAccumulator, this.controlKeys[keyName].motorContribution); this.controlKeys[keyName].isPressed = false; this.pressTimestamps[keyName] = undefined; } } } var motorVelocity = {x:0.0, y:0.0, z:0.0}; // figure out if we're pushing or braking var accumulatorLength = Vec3.length(motorAccumulator); var isPushing = false; if (accumulatorLength == 0.0) { if (!isBraking) { isBraking = true; } isPushing = false; } else { isPushing = true; motorVelocity = Vec3.multiply(AVATAR_SPEED / accumulatorLength, motorAccumulator); } // compute the timescale var motorTimescale = MAX_MOTOR_TIMESCALE; if (isBraking) { var speed = Vec3.length(MyAvatar.getVelocity()); if (speed < MIN_BRAKING_SPEED) { // we're going slow enough to turn off braking // --> we'll drift to a halt, but not so stiffly that we can't be bumped isBraking = false; motorTimescale = MAX_MOTOR_TIMESCALE; } else { // we're still braking motorTimescale = BRAKING_MOTOR_TIMESCALE; } } else if (isPushing) { motorTimescale = PUSHING_MOTOR_TIMESCALE; } // apply the motor parameters MyAvatar.motorVelocity = motorVelocity; MyAvatar.motorTimescale = motorTimescale; } PodMover.scriptEnding = function() { // disable the motor MyAvatar.motorVelocity = {x:0.0, y:0.0, z:0.0} MyAvatar.motorTimescale = VERY_LONG_TIME; } // init stuff MyAvatar.motorReferenceFrame = "camera"; // "camera" is default, other options are "avatar" and "world" MyAvatar.motorTimescale = VERY_LONG_TIME; // connect callbacks // Controller.keyPressEvent.connect(keyPressEvent); // Controller.keyReleaseEvent.connect(keyReleaseEvent); // Script.update.connect(updateMotor); // Script.scriptEnding.connect(scriptEnding)