Game Development Community

Creating a Throttle-type bindCmd/Action Map

by Brian Wilson · in Torque Game Builder · 04/04/2005 (10:19 pm) · 4 replies

I understand the philosophy of the tutorial for creating key bindings as a switch:

new ActionMap(playerMap);

playerMap.bindCmd(keyboard, "right", "playerRight();", "playerRightStop();");

playMap.push();

function playerRight()
{  $player.setLinearVelocityX(30); }

function playerRightStop()
{ $player.setLinearVelocityX(0); }
In the above, pressing the "->" (right arrow key) will cause "$player" to move to the right at a velocity of 30, and releasing the key will return it to 0.

Fine, but what I want to do is when the "->" key is pressed, for the velocity to increase over time until released, much like a Lander or Space Taxi type game.

My current code require tapping the key to achieve this effect:

// acceleration rate constant
$acceleration = 5;
// maximum velocity constant
$maxVelocity = 30;

function playerRight()
{
// temp var for new velocity
%tempVelocityX = $player.getLinearVelocityX()+$acceleration;

// test for maximum velocity and cap
if(%tempVelocityX > $maxVelocity)
  %tempVelocityX = $maxVelocity;

$player.setLinearVelocityX(%tempVelocityX);
}

I'm looking for a way to do the above without having to tap the key repeatedly for accelleration.

Any pointers here? I've trying puting a hack together with schedule(), but it's not working or even worthy of posting, nor am I convinced this is the best way to do it anyway.

Thanks in advance for everyone's help.

#1
04/04/2005 (10:29 pm)
Yes, schedule would be the way to go. I don't have any of the references out, but here's what I would do:

1. Bind the key to two functions, we'll call them startRight and stopRight.
2. Function startRight sets a variable to true (unless there's a way to check if a key is depressed, I'm unsure), sets an initial velocity if needed, and starts the schedule for increase.
3. Function stopRight, changes that variable to false.
4. The scheduled function will check if variable is true, if so it will increase the velocity. If it's not, it will kill the velocity, and unschedule the function.

I wish I could provide some psuedo- or even real-code for you, but I am working on something else at the moment and don't want to interrupt it by opening other things. This should give you enough to work through it though.
#2
04/04/2005 (10:47 pm)
Ok, thanks Michael, that worked great! I guess my brain locked up...

Here's what worked:

$acceleration = 5;              // Constant of acceleration
// Right Arrow is Pressed
function playerRight()
{
  $playerRightSwitch = 1;
  $playerRightEvent();
}
// Right Arrow is Released
function playerRightStop()
{
  $playerRightSwitch = 0;
}
// Event to alter velocity
function playerRightEvent()
{
  if($playerRightSwitch != 1)
    return;
  $player.setLinearVelocityX($player.getLinearVelocityX()+$acceleration);
  schedule(100, 0, "playerRightEvent");
}
#3
04/04/2005 (10:48 pm)
This should get you started:

// acceleration rate constant
$acceleration = 5;
// maximum velocity constant
$maxVelocity = 30;

function playerRight()
{
   // flags the keypress
   $right = true;
   // calls the actual acceleration function
   playerRightSched();
}

function playerRightSched()
{
   if ($right)
   {
      // temp var for new velocity
      %tempVelocityX = $player.getLinearVelocityX()+$acceleration;
      // test for maximum velocity and cap
      if(%tempVelocityX > $maxVelocity)
         %tempVelocityX = $maxVelocity;
      $player.setLinearVelocityX(%tempVelocityX);
      // calls acceleration function again, at intervals of 1/4 second
      schedule(250, 0, "playerRightSched");
   }
}

function playerRightStop()
{
   // unflags keypress
   $right = false;
}

edit: forgot to close the code tag... o_O
edit2: whoops, looks like you've already got it. :-p
#4
04/07/2005 (11:42 pm)
I recently implemented some code very similar to this in one of my own scripts for a spaceship game. But mine was for the ship's firing mechanism. I wanted to allow the player to press and hold the space bar for auto-fire (at a modest rate), or to press the space bar repeatedly and get a faster rate of fire.

I implemented the firing exactly like shown above, using a $firing flag and a fire() method with a schedule("fire") at the bottom. It worked just great, except for one quirky thing that I found ... you could 'trick' the autofire into firing multiple shots by double or triple tapping the space bar and holding it down. Pressing it three times runs the fire() function three times and schedules three more fire() executions in 200 millisecs (my chosen rate of fire). So long as you continue to hold the space bar down, those three fire() calls will fire three more, and three more, and so on.

So after much hair pulling, addition of more flags and if statements, and even a second scheduling routine, someone told me about a helpful command that fixed everything quite nicely. Using a variable, you can capture a scheduled command as follows:

$myEvent = schedule(200, 0, "fire");

Then later on, if for some reason you need to unschedule the command, just use:

cancel($myEvent);

So here's a modified version of my code:

function spawnPlayerMissile()
{
	if (!$player.fireOn)	return;

	// Code for generating the projectile here ...

	if ($player.fireOn)
		$fireEvent = schedule($playerFireRate, 0, "spawnPlayerMissile");
} // end spawnPlayerMissile

// Called on space bar down
function playerFire()
{
	$player.fireOn = true;
	spawnPlayerMissile();
} // end playerFire

// Called on space bar up
function playerFireStop()
{
	$player.fireOn = false;
	cancel($fireEvent);
}

It's a slightly different issue, but close enough that I thought it was worth mentioning here.