Game Development Community

Tank Physics Mini tutorial

by Aaron Soules · in Torque Game Builder · 02/02/2007 (2:37 pm) · 3 replies

I've been looking over the tank physics mini tutorial, and I wanted to adapt the tank to move in 8 directions using WASD. Basically the same type on movement in the shooter tutorial. Being new to torque, (but not to scripting), I tried to combine elements on the playership from the shooter tutorial and the tank from the tank physics tutorial. I've been able to get the movement working by commenting out this line:
%this.setTimerOn(25);
However, this obviously disables the turret, since that function relies on the timer. So I attempted to re-write the shooter movement script to work inside the onTimer function, but have not succeeded in a successful integration.

#1
02/02/2007 (2:39 pm)
My Current Version:
// Tank Datablock definition
// play with these variables to change the handling of your Tank!
datablock t2dSceneObjectDatablock(PhysTankDatablock)
{
   class = "PhysTank"; // associate this datablock with the PhysTank namespace
   maxSteerAngle = "100"; // the maximum angular force used for steering the tank (not an angle)
   cTrac = "15"; // coefficient of traction (max speed)
   walkSpeed = "30"; //Shooter Walking Speed
   size = "8.120 8.120"; // default size
};

// Turret Datablock definition
datablock t2dSceneObjectDatablock(PhysTankTurretDatablock)
{
   turnSpeed = "800"; // speed at which turret turns
   size = "2.755 11.132"; // default size
};

// PhysTank onLevelLoaded callback
function PhysTank::onLevelLoaded(%this, %scenegraph)
{   
   // set this tank's name so SceneWindow2D can find it
   %this.setName("MyTank");
   
   // init tank toggle vars
   %this.gasPedal = false;
   %this.brake = false;
   %this.left = false;
   %this.right = false;
   %this.turretLeft = false;
   %this.turretRight = false;
   
   // init shooter toggle vars
   %this.moveUp = false;
   %this.moveDown = false;
   %this.moveLeft = false;
   %this.moveRight = false;
   
   // init tank input vars
   %this.throttle = 0; // ranges from -1 to 1 (full reverse to full forward)
   %this.steering = 0; // ranges from -1 to 1 (full left to full right)
   %this.lastMousePos = "0 0";
      
   // init tank physics vars
   %this.latSpeed = 0;
   
   // set up turret
   %this.initializeTurret();
   
   // Tank map keys
   moveMap.bindCmd(keyboard, "up", %this @ ".throttleOn();", %this @ ".throttleOff();");
   moveMap.bindCmd(keyboard, "down", %this @ ".brakeOn();", %this @ ".brakeOff();");
   moveMap.bindCmd(keyboard, "left", %this @ ".leftOn();", %this @ ".leftOff();");
   moveMap.bindCmd(keyboard, "right", %this @ ".rightOn();", %this @ ".rightOff();");
   
   //Shooter Commands Below
   moveMap.bindCmd(keyboard, "w", %this @ ".walkUp();", %this @ ".walkUpStop();"); 
   moveMap.bindCmd(keyboard, "s", %this @ ".walkDown();", %this @ ".walkDownStop();"); 
   moveMap.bindCmd(keyboard, "a", %this @ ".walkLeft();", %this @ ".walkLeftStop();"); 
   moveMap.bindCmd(keyboard, "d", %this @ ".walkRight();", %this @ ".walkRightStop();"); 
   
   // enable the timer callback for this object for every 25 milliseconds
   %this.setTimerOn(25);
}

// create and attach a turret to this tank
function PhysTank::initializeTurret(%this)
{
   // create the new turret and store it on this object
   %this.turret = new t2dStaticSprite()
   {
      sceneGraph = %this.scenegraph; // make sure to set the scenegraph
      ImageMap = "tankTurretImageMap"; // set the image to use
      config = "PhysTankTurretDatablock"; // set the config datablock
   };

   // mount the turret to the tank and set 'trackRotation' (fourth argument)
   // to false so we can rotate our turret independently
   %this.turret.mount(%this, "0 -0.1", 0, false, true, true, true);
}

// this is called every time the mouse cursor is moved
function sceneWindow2D::onMouseMove(%this, %modifier, %worldPos, %clicks)
{
   // update MyTank's lastMousePos variable with fresh coordinates
   MyTank.lastMousePos = %worldPos;
}

// this is our update turret function to rotate the turret 
// towards the mouse pointer
function PhysTank::updateTurret(%this, %mousePos)
{
   // get a vector from the tank to the mouse pointer
   %vec = t2dVectorSub(%this.getPosition(), %mousePos);
   
   // get the desired angle required to point at the mouse pointer   
   %angle = -mRadToDeg(mATan(getWord(%vec,0),getWord(%vec,1)));
   
   // tell the tank turret to rotate towards that angle at a rate of 
   // 'turret.turnSpeed' which was set in our turret's datablock
   %this.turret.rotateTo(%angle, %this.turret.turnSpeed);
}

// PhysTank onTimer callback
function PhysTank::onTimer(%this)
{
   // 1. interpret input flags
   // Throttle:
   // if only the gas pedal is pressed and we aren't reversing
   if((%this.gasPedal && !%this.brake) && %this.throttle >=0)
   {
      // increment trottle (forward)
      %this.throttle += 0.025;
      
      // clamp throttle at 1 for full forward
      if(%this.throttle > 1)
      {
         %this.throttle = 1;
      }
   }
   // if only the 'brake' is pressed and we aren't going forward
   else if((%this.brake && !%this.gasPedal) && %this.throttle <= 0)
   {
      // decrement throttle (reverse)
      %this.throttle -= 0.005;
      
      // clamp throttle at -1 for full reverse
      if(%this.throttle < -1)
      {
         %this.throttle = -1;
      }
   }
   // either *neither* or *both* gas petal and throttle are activated
   // -or- we are trying to throttle in the opposite direction we are moving
   else
   {
      // lower the throttle from either direction by 0.02
      // if magnitude of throttle is less than 0.02 then set to 0
      // Note: without checking for this, our throttle could skip between
      // negative and positive as it tries to hit zero. 
      // for example, immagine the throttle is 0.1
      if(%this.throttle < -0.02)
      {
         %this.throttle += 0.02;
      }
      else if(%this.throttle > 0.02)
      {
         %this.throttle -= 0.02;
      }
      else
      {
         %this.throttle = 0;
      }
   }
   
   // Steering:
   // if only pressing left and steering isnt to the right
   if((%this.left && !%this.right) && %this.steering <= 0)
   {
      // decrement steering (left)
      %this.steering -= 0.025;
      
      // clamp steering at -1 (full left)
      if(%this.steering < -1)
      {
         %this.steering = -1;
      }
   }
   // if only pressing right and steering isnt to the left
   else if((%this.right && !%this.left) && %this.steering >= 0)
   {
      // increment steering (right)
      %this.steering += 0.025;
      
      // clamp stering at 1 (full right)
      if(%this.steering > 1)
      {
         %this.steering = 1;
      }
   }
   else
   {
      // lower the steering from either direction by 0.02
      // if magnitude of steering is less than 0.02 then set to 0
      if(%this.steering < -0.05)
      {
         %this.steering += 0.05;
      }
      else if(%this.steering > 0.05)
      {
         %this.steering -= 0.05;
      }
      else
      {
         %this.steering = 0;
      }
   }
   
   // 2. calculate longitudinal force
   // get current forward traction force (speed)
   %traction = %this.cTrac * %this.throttle;
   
   // get longitudinal force vector
   // remember that neg Y is up, so we need -cos(rotation) for Y
   %longVelX = mSin(mDegToRad(%this.getRotation())) * %traction;
   %longVelY = -mCos(mDegToRad(%this.getRotation())) * %traction;
   
   // 3. steering / angular vel   
   // adjust steering force:
   // get a base steering force based on speed of movement
   %steerVel = %this.steering * %this.maxSteerAngle;
   
   // 4. apply forces
   // apply linear velocity
   %this.setLinearVelocity(%longVelX SPC %longVelY);
   
   // apply angular velocity
   %this.setAngularVelocity(%steerVel);
   
   // 5. set turret's rotation!
   %this.updateTurret(%this.lastMousePos);
}
#2
02/02/2007 (2:39 pm)
Continued...

// ____ tank input functions ____
// gas
function PhysTank::throttleOn(%this)
{
   %this.gasPedal = true;
}
function PhysTank::throttleOff(%this)
{
   %this.gasPedal = false;
}

// brake / reverse
function PhysTank::brakeOn(%this)
{
   %this.brake = true;
}
function PhysTank::brakeOff(%this)
{
   %this.brake = false;
}

// steer left
function PhysTank::leftOn(%this)
{
   %this.left = true;
}
function PhysTank::leftOff(%this)
{
   %this.left = false;
}

// steer right
function PhysTank::rightOn(%this)
{
   %this.right = true;
}
function PhysTank::rightOff(%this)
{
   %this.right = false;
}

// rotate turret left
function PhysTank::turretLeftOn(%this)
{
   %this.turretLeft = true;
}
function PhysTank::turretLeftOff(%this)
{
   %this.turretLeft = false;
}

// rotate turret right
function PhysTank::turretRightOn(%this)
{
   %this.turretRight = true;
}
function PhysTank::turretRightOff(%this)
{
   %this.turretRight = false;
}

function PhysTank::updateMovement(%this)
{
   if(%this.moveLeft)
   {
      %this.setLinearVelocityX( -%this.walkSpeed );
   }

   if(%this.moveRight)
   {
      %this.setLinearVelocityX( %this.walkSpeed );
   }   
   
   if(%this.moveUp)
   {
      %this.setLinearVelocityY( -%this.walkSpeed );
   }

   if(%this.moveDown)
   {
      %this.setLinearVelocityY( %this.walkSpeed );
   }

   if(!%this.moveLeft && !%this.moveRight)
   {
      %this.setLinearVelocityX( 0 );
   } 

   if(!%this.moveUp && !%this.moveDown)
   {
      %this.setLinearVelocityY( 0 );
   }
}

// Shooter Input Functions
// Move Up
function PhysTank::walkUp(%this)
{
   %this.moveUp = true;
   %this.updateMovement();
}
function PhysTank::walkUpStop(%this)
{
   %this.moveUp = false;
   %this.updateMovement();
}

// Move Down
function PhysTank::walkDown(%this)
{
   %this.moveDown = true;
   %this.updateMovement();
}
function PhysTank::walkDownStop(%this)
{
   %this.moveDown = false;
   %this.updateMovement();
}

// Move Left
function PhysTank::walkLeft(%this)
{
   %this.moveLeft = true;
   %this.updateMovement();
}
function PhysTank::walkLeftStop(%this)
{
   %this.moveLeft = false;
   %this.updateMovement();
}

// Move Right
function PhysTank::walkRight(%this)
{
   %this.moveRight = true;
   %this.updateMovement();
}
function PhysTank::walkRightStop(%this)
{
   %this.moveRight = false;
   %this.updateMovement();
}
#3
02/03/2007 (6:21 pm)
Problem solved.