Path: blob/main/projects/missiles/src/missile.js
1835 views
MG.missile = (function () {12var ACCELERATION_TIME_CONSTANT = 1.0;3var DRIFT_DAMPING = 0.25;45var MAX_RADIUS = 0.8*MG.TUNNEL_RADIUS;67var MissileState = {8CRASHED: 'crashed',9AUTOPILOT: 'autopilot',10MANUAL: 'manual'11}1213var mState;1415var mOffset;16var mVelocity;17var mTargetVelocity;1819var mX;20var mY;2122var mTargetX;23var mTargetY;2425var mDriftVelX;26var mDriftVelY;27var mDriftCounter;282930return {31init: function () {32this.reset();33},343536reset: function (){37mState = MissileState.AUTOPILOT;3839mOffset = 200.0;40mVelocity = 0.0;41mTargetVelocity = 400.0;4243mX = 0.0;44mY = 0.0;4546mTargetX = 0.0;47mTargetY = 0.0;4849mDriftVelX = 0.0;50mDriftVelY = 0.0;51mDriftCounter = 1.0;5253},545556update: function (dt) {5758switch (mState) {59case MissileState.AUTOPILOT:60/* When under autopilot control, the missile will randomly61drift around the center of the tunnel, changing direction at62discrete intervals. */63/* The drift counter contains the time until the next direction change. */64mDriftCounter -= dt;65if (mDriftCounter < 0) {66mDriftCounter = 1.1 + 0.9*Math.random();6768mDriftVelX = (MG.TUNNEL_RADIUS*(Math.random()-0.5) - mTargetX)/1.5;69mDriftVelY = (MG.TUNNEL_RADIUS*(Math.random()-0.5) - mTargetY)/1.5;70}7172/* TODO Smooth */73mX += mDriftVelX * dt ;74mY += mDriftVelY * dt ;7576break;7778case MissileState.MANUAL:79mX += (mTargetX - mX) * dt / DRIFT_DAMPING;80mY += (mTargetY - mY) * dt / DRIFT_DAMPING;81break;8283default:84/* leave the missile pointing in the same direction */85}8687/* Clamp the missile's position to inside the tunnel wall */88var radius = Math.sqrt(mX*mX + mY*mY);89var newRadius = Math.min(MAX_RADIUS, radius);9091mX = (radius === 0) ? 0 : mX*newRadius/radius;92mY = (radius === 0) ? 0 : mY*newRadius/radius;93949596if (mState === MissileState.CRASHED) {97/* If the missile has crashed, it will bounce backwards coming98to rest near the location of the previous barrier. */99mVelocity += dt*MG.BARRIER_SPACING*mVelocity/(mOffset - MG.BARRIER_SPACING);100} else {101mVelocity += dt*(mTargetVelocity - mVelocity)/ACCELERATION_TIME_CONSTANT;102}103104mOffset -= mVelocity * dt;105},106107getPosition: function () {108return {x: mX, y:mY};109},110111getTarget: function () {112return {x: mTargetX, y:mTargetY};113},114115getOffset: function () {116return mOffset;117},118119getVelocity: function () {120return mVelocity;121},122123isCrashed: function () {124return mState == MissileState.CRASHED;125},126127setTarget: function (targetX, targetY) {128if (mState === MissileState.MANUAL) {129mTargetX = targetX;130mTargetY = targetY;131}132},133134setVelocity: function (velocity) {135mTargetVelocity = velocity;136},137138139setManual: function () {140mState = MissileState.MANUAL;141},142143setAutopilot: function () {144mState = MissileState.AUTOPILOT;145},146147148onBarrierPassed: function () {149mOffset += MG.BARRIER_SPACING;150},151152onCrash: function () {153mVelocity = -Math.abs(mVelocity);154155mState = MissileState.CRASHED;156}157};158}());159160161