Game Development Community

Rotation

by Trond Wespestad · in Torque Game Builder · 08/15/2006 (10:06 am) · 11 replies

Hey.
I just downloaded the demo of TGB a few hours ago and I need some help.

I want to make it so thet when you press A the player controlled object rotates counterclockwise and when you press D it rotates clockwise.
And then when you press W it goes the way the front is.

If you understand what I mean.
I guess the rotation part is not wary hard, I just dont know the script function for it.
Please help.
Thanks.

About the author

Recent Threads


#1
08/17/2006 (6:10 pm)
You could use [object].setRotation([angle]) or [object].rotateTo([angle]).

Check out the TorqueScript Reference in your Reference folder. =)
#2
08/17/2006 (7:12 pm)
If I understand, correctly, your wanting to rotate the player object with A and D, and then move the object in that direction with W and S ...

Thomas is correct with the setRotation() or rotateTo() methods for rotating the object, to get the object to move in that direction however requires you to know what the current rotation of the object is, then move them in that direction ... you could use the setLinearVelocityPolar() method and pass the objects Rotation in as the direction, and the speed set to whatever you deem necessary as a decent movement speed while the W or S is pressed.

function myObj::onLevelLoaded(%this, %scenegraph)
{
  $myObj = %this;
  $myObj.moveForward = false;
  $myObj.moveBackward = false;
  $myObj.rotateLeft = false;
  $myObj.rotateRight = false;

  $myObj.rotationSpeed = 10;
  $myObj.velocitySpeed = 15;

  moveMap.bindCmd(keyboard, "a", "rotateLeft();" ,"rotateLeftStop();");
  moveMap.bindCmd(keyboard, "d", "rotateRight();", "rotateRightStop();");
  // ... additional bindCmd's removed for readability ... 
}

function rotateLeft()
{
  $myObj.rotateLeft = true;
  updateMovement();
}

function rotateLeftStop()
{
  $myObj.rotateLeft = false;
  updateMovement();
}

function rotateRight()
{
  $myObj.rotateRight = true;
  updateMovement();
}

function rotateRightStop()
{
  $myObj.rotateRight = false;
  updateMovement();
}

function updateMovement()
{
  if($myObj.rotateLeft)
  {
    $myObj.setAngularVelocity(-$myObj.rotationSpeed);
  } else if($myObj.rotateRight)
  {
    $myObj.setAngularVelocity(-$myObj.rotationSpeed);
  } else { $myObj.setAngularVelocity(0); }

  if($myObj.moveForward)
  {
    $myObj.setLinearVelocityPolar($myObj.getRotation(), -$myObj.velocitySpeed);
  } else if ($myObj.moveBackward)
  {
    $myObj.setLinearVelocityPolar($myObj.getRotation(), $myObj.velocitySpeed);
  } else { $myObj.setLinearVelocity(0, 0); }
}


Keep in mind, this code is un-tested, but should either 'work as is', or 'lead you in the right direction' ... not 100% sure if my negative/position switches are correct for Left/Right and Forward/Backward ... but they should be ...

hope this helps.
#3
08/18/2006 (3:20 am)
Wow thank you so much.
I lerned a lot from that.

You had a typo (a "-") in the rotateRight code so I had to do some troubleshooting to find out why it onley rotated left.
Always lern a lot from doing that.
That was your plan right lol :)

Here is the code I use now:
(I have not added code for moveBackward)

function myObj::onLevelLoaded(%this, %scenegraph)
{
  $myObj = %this;
  $myObj.moveForward = false;
  $myObj.moveBackward = false;
  $myObj.rotateLeft = false;
  $myObj.rotateRight = false;
  $myObj.rotationSpeed = 50;
  $myObj.velocitySpeed = 35;
  moveMap.bindCmd(keyboard, "a", "rotateLeft();" ,"rotateLeftStop();");
  moveMap.bindCmd(keyboard, "d", "rotateRight();", "rotateRightStop();");
  moveMap.bindCmd(keyboard, "w", "moveForward();", "moveForwardStop();");
}
function rotateLeft()
{
  $myObj.rotateLeft = true;
  updateMovement();
}
function rotateLeftStop()
{
  $myObj.rotateLeft = false;
  updateMovement();
}
function rotateRight()
{
  $myObj.rotateRight = true;
  updateMovement();
}
function rotateRightStop()
{
  $myObj.rotateRight = false;
  updateMovement();
}
function moveForward()
{
  $myObj.moveForward = true;
  updateMovement();
}
function moveForwardStop()
{
  $myObj.moveForward = false;
  updateMovement();
}
function updateMovement()
{
  if($myObj.rotateLeft)
  {
    $myObj.setAngularVelocity(-$myObj.rotationSpeed);
  } else if($myObj.rotateRight)
  {
    $myObj.setAngularVelocity($myObj.rotationSpeed);
  } else { $myObj.setAngularVelocity(0); }
  if($myObj.moveForward)
  {
    $myObj.setLinearVelocityPolar($myObj.getRotation(), $myObj.velocitySpeed);
  } else if ($myObj.moveBackward)
  {
    $myObj.setLinearVelocityPolar($myObj.getRotation(), -$myObj.velocitySpeed);
  } else { $myObj.setLinearVelocity(0, 0);
 }
}

But one problem.
myObj go straight ahead and rotates when I hold down A and W at the same time.
I need it to do a left turn when I hold down A and W.
Is that easy to do?

I guess the problem is that it onley updates when i let go of A.
#4
08/18/2006 (5:11 pm)
I believe I see the problem you are referrring too.

If you are currently holding down W to move forward, and then press A to turn, the object continues moving along it's original rotation and does not take into account the new rotation.

I will look into this and have an update shortly (I hope)
#5
08/18/2006 (5:29 pm)
Ok, I believe I found the problem -- not quite sure what the 'best practice' solution is though.

The updateMovement() function is being called by the moveForward(), rotateLeft() and rotateRight() functions which are only being called when the key is initially pressed the first time.

You can test this by adding echo() statements into the updateMovement() function either before or after the set*Velocity*() functions are called.

The object makes it look as though the 'game' is responding to the key being held down, when in fact the game is merely responding to the press and release of the key.

If you tapped the A or S keys, the object's linear velocity would be updated to reflect the new rotation at the time of the key press.

This can most likely be resolved, 'assumeably the best way' through a t2dSceneObject::updateScene() function that calls updateMovement() for you.
#6
08/18/2006 (5:31 pm)
The code below performs the functionality I believe you were initially asking for;

Changes are indicated in bold, I also added Backward movement (for others who may have been curious, feel free to remove it if your 'game' does not require it)
function myObj::onLevelLoaded(%this, %scenegraph)
{
  $myObj = %this;
  $myObj.moveForward = false;
  $myObj.moveBackward = false;
  $myObj.rotateLeft = false;
  $myObj.rotateRight = false;
  $myObj.rotationSpeed = 50;
  $myObj.velocitySpeed = 35;
  moveMap.bindCmd(keyboard, "a", "rotateLeft();" ,"rotateLeftStop();");
  moveMap.bindCmd(keyboard, "d", "rotateRight();", "rotateRightStop();");
  moveMap.bindCmd(keyboard, "w", "moveForward();", "moveForwardStop();");
  moveMap.bindCmd(keyboard, "s", "moveBackward();", "moveBackwardStop();");
}
function rotateLeft()
{
  $myObj.rotateLeft = true;
  [b]//updateMovement();[/b]
}
function rotateLeftStop()
{
  $myObj.rotateLeft = false;
  [b]//updateMovement();[/b]
}
function rotateRight()
{
  $myObj.rotateRight = true;
  [b]//updateMovement();[/b]
}
function rotateRightStop()
{
  $myObj.rotateRight = false;
  [b]//updateMovement();[/b]
}
function moveForward()
{
  $myObj.moveForward = true;
  [b]//updateMovement();[/b]
}
function moveForwardStop()
{
  $myObj.moveForward = false;
  [b]//updateMovement();[/b]
}
[b]function moveBackward()
{
   $myObj.moveBackward = true;
}
function moveBackwardStop()
{
   $myObj.moveBackward = false;
}[/b]
function updateMovement()
{
  if($myObj.rotateLeft)
  {
   $myObj.setAngularVelocity(-$myObj.rotationSpeed);
  } else if($myObj.rotateRight)
  {
    $myObj.setAngularVelocity($myObj.rotationSpeed);
  } else { $myObj.setAngularVelocity(0); }
  
  if($myObj.moveForward)
  {
    $myObj.setLinearVelocityPolar($myObj.getRotation(), $myObj.velocitySpeed);
  } else if ($myObj.moveBackward)
  {
    $myObj.setLinearVelocityPolar($myObj.getRotation(), -$myObj.velocitySpeed);
  } else { $myObj.setLinearVelocity(0, 0);
 }
}
[b]
function t2dSceneGraph::onUpdateScene(%this)
{
   updateMovement();
}
[/b]
#7
08/19/2006 (2:20 am)
Nice.
Thats exactly what I wanted.
This code can be used for a lot of different games so I'm shure others will want it to.
Thank you so much for takeing the time to help me out.

One last thing.
No real objekt stop that fast :)
I need it so when you let go of W (or S if your going backward) it starts to slow down and then stop after like 1 second or something like that.

I guess we need to do something with this:
else { $myObj.setLinearVelocity(0, 0);

But I dont know what.
I cant find much info on what script functions can be used.
Are there a lots of info about that in the Torque Developer Network?
Thanks.
#8
08/19/2006 (9:51 am)
Trond,

you could accomplish the 'slow down and stop' by taking advantage of the built-in physics and applying density, friction and other such things to your object and basically then just remove the (0,0) velocity line all together and let the physics engine bring your object to a halt ... perfecting this would be something of a hassle though ... though combined with a timer set on the object to guarantee it does 'setAtRest()' you should be ok ...
#9
08/19/2006 (10:48 am)
function myObj::onLevelLoaded(%this, %scenegraph)
{
   $myObj = %this;
   $myObj.moveForward = 0;
   $myObj.moveBackward = 0;
   $myObj.rotateLeft = false;
   $myObj.rotateRight = false;
   $myObj.rotationSpeed = 50;
   $myObj.velocitySpeed = 35;
   moveMap.bindCmd(keyboard, "a", "rotateLeft();" ,"rotateLeftStop();");
   moveMap.bindCmd(keyboard, "d", "rotateRight();", "rotateRightStop();");
   moveMap.bindCmd(keyboard, "w", "moveForward();", "moveForwardStop();");
   moveMap.bindCmd(keyboard, "s", "moveBackward();", "moveBackwardStop();");
}

function rotateLeft() { $myObj.rotateLeft = true; }
function rotateLeftStop() { $myObj.rotateLeft = false; }
function rotateRight() { $myObj.rotateRight = true; }
function rotateRightStop() { $myObj.rotateRight = false; }
// set the opposite direction to 'stopped' so as not to process incorrectly
function moveForward() { $myObj.moveBackward = 0; $myObj.moveForward = 1; }
function moveForwardStop() { $myObj.moveForward = 2; }
function moveBackward() { $myObj.moveForward = 0; $myObj.moveBackward = 1; }
function moveBackwardStop() { $myObj.moveBackward = 2; }

function updateMovement() 
{
   // if it's not a valid object, then leave it alone (prevents errors during initial startup);
   if(!isObject($myObj)) return;
   
   // handle angular velocity
   if($myObj.rotateLeft) { $myObj.setAngularVelocity(-$myObj.rotationSpeed);
   } else if($myObj.rotateRight) { $myObj.setAngularVelocity($myObj.rotationSpeed);
   } else { $myObj.setAngularVelocity(0); }

   // set in forward/backward motion
   if($myObj.moveForward == 1) { $myObj.setLinearVelocityPolar($myObj.getRotation(), $myObj.velocitySpeed);
   } else if ($myObj.moveBackward == 1) { $myObj.setLinearVelocityPolar($myObj.getRotation(), -$myObj.velocitySpeed);
   } else
   // handle 'come to rest'
   if ($myObj.moveForward == 2)
   {
      %ret = $myObj.getLinearVelocityPolar();
      %speed = getWord(%ret, 1);
      if(%speed > 0.0) 
      { $myObj.setLinearVelocityPolar($myObj.getRotation(), %speed - (%speed*0.001)); } 
      else { $myObj.moveForward = 0; }
   } else if ($myObj.moveBackward == 2)
   {
      %ret = $myObj.getLinearVelocityPolar();
      %speed = getWord(%ret, 1);
      if(%speed > 0.0)
      { $myObj.setLinearVelocityPolar($myObj.getRotation(), -(%speed - (%speed*0.001))); } 
      else { $myObj.moveBackward = 0; }
   }
}

function t2dSceneGraph::onUpdateScene(%this)
{
   updateMovement();
}

EDIT: removed echo()'d debug statements
#10
08/19/2006 (10:52 am)
Or you could try taking a look at this code ... it slows the object down 1% per frame draw ... which on a 30fps screen would be 30% per second causing a 3.3333333 second 'slow motion stop'.

Took a bit to get this tweaked 'just right' so that forward and backward motions were handled properly, but here you go -- it does not handle angular velocity slow down, just linear velocity ... so when your pressing A and D and then release, your object just stops rotating instantly, but when you release either W or S the object comes to an eventual stop very slowly ...
#11
08/19/2006 (12:22 pm)
Trond,

you may also want to give this a whirl, it's a project I created with the trial version, it involves a tile-map with collisions and a player object (car) that can travel around the path laid out in the tile-map (road). It uses the same code that we've worked on in this thread, but has some added things;

when the car collides with the tilemap, it 'crashes' and the image changes -- press 'R' to reset the car


I attempted to add a speed-up functionality, but so far have not accomplished this -- I intend to have the car, from a full-stop 'speed-up' to it's maxSpeed value .. as if accelerating.

www.zoulcreations.com/tgb/ZCdemoCar.zip


EDIT: Added link, oops