Moving smoothly in discrete units
by Theo Brinkman · in Torque Game Builder · 06/05/2006 (9:32 pm) · 3 replies
I'm working on a puzzle game that requires movement in half-tile increments, but I don't want the player to simply jump from place to place. I'm thinking the solution is going to involve moveTo(), but I'm having trouble figuring out how to make it work properly. Basically, I want to make it so that when the player releases the 'up' key, the player will continue moving up until they hit that next half-tile mark.
My current code allows the player to 'ride' multiple keys for fast reactions (no worries about not releasing 'up' before you press 'left'), but I can't figure out how to make the player finish moving to the half-tile mark. This is my first project, and the planned game is relatively straight-forward, but the half-tile movement is critical to the design (the enemies have to move by half-tile increments as well).
My current code allows the player to 'ride' multiple keys for fast reactions (no worries about not releasing 'up' before you press 'left'), but I can't figure out how to make the player finish moving to the half-tile mark. This is my first project, and the planned game is relatively straight-forward, but the half-tile movement is critical to the design (the enemies have to move by half-tile increments as well).
function cPlayer::onLevelLoaded(%this, %scenegraph)
{
$player = %this;
moveMap.bindCmd(keyboard, "w", "playerUp();", "playerUpStop();");
moveMap.bindCmd(keyboard, "s", "playerDown();", "playerDownStop();");
moveMap.bindCmd(keyboard, "a", "playerLeft();", "playerLeftStop();");
moveMap.bindCmd(keyboard, "d", "playerRight();", "playerRightStop();");
%this.direction = "stop";
}
function cPlayer::updateMovement(%this)
{
switch$ (%this.key1)
{
case "up":
%this.setLinearVelocityX( 0 );
%this.setLinearVelocityY( -$player.speed );
case "down":
%this.setLinearVelocityX( 0 );
%this.setLinearVelocityY( $player.speed );
case "left":
%this.setLinearVelocityX( -$player.speed );
%this.setLinearVelocityY( 0 );
case "right":
%this.setLinearVelocityX( $player.speed );
%this.setLinearVelocityY( 0 );
default:
%this.setLinearVelocityX( 0 );
%this.setLinearVelocityY( 0 );
}
}
function playerUp()
{
$player.addKey("up");
$player.updateMovement();
}
function playerDown()
{
$player.addKey("down");
$player.updateMovement();
}
function playerLeft()
{
$player.addKey("left");
$player.updateMovement();
}
function playerRight()
{
$player.addKey("right");
$player.updateMovement();
}
function playerUpStop()
{
$player.removeKey("up");
$player.updateMovement();
}
function playerDownStop()
{
$player.removeKey("down");
$player.updateMovement();
}
function playerLeftStop()
{
$player.removeKey("left");
$player.updateMovement();
}
function playerRightStop()
{
$player.removeKey("right");
$player.updateMovement();
}
function cPlayer::addKey(%this, %newKey)
{
%this.removeKey(%newKey);
%this.key4 = %this.key3;
%this.key3 = %this.key2;
%this.key2 = %this.key1;
%this.key1 = %newKey;
}
function cPlayer::removeKey(%this, %dropKey)
{
switch$ (%dropKey)
{
case %this.key1:
%this.key1 = %this.key2;
%this.key2 = %this.key3;
%this.key3 = %this.key4;
%this.key4 = "";
case %this.key2:
%this.key2 = %this.key3;
%this.key3 = %this.key4;
%this.key4 = "";
case %this.key3:
%this.key3 = %this.key4;
%this.key4 = "";
case %this.key4:
%this.key4 = "";
}
}About the author
#2
06/06/2006 (6:03 pm)
Figured it out. Pretty simple code once I worked around a couple wierd bits (%this.key1 = "up"; %this.key1 != "" returns false). Ended up *always* using moveTo() instead of special casing the key-up event.function cPlayer::onLevelLoaded(%this, %scenegraph)
{
// echo("cPlayer::onLevelLoaded(%this, %scenegraph);");
$player = %this;
moveMap.bindCmd(keyboard, "w", "playerUp();", "playerUpStop();");
moveMap.bindCmd(keyboard, "s", "playerDown();", "playerDownStop();");
moveMap.bindCmd(keyboard, "a", "playerLeft();", "playerLeftStop();");
moveMap.bindCmd(keyboard, "d", "playerRight();", "playerRightStop();");
%this.gridSize = 2;
%this.ready = true;
}
function cPlayer::onWorldLimit(%this)
{
%this.ready = true;
%this.updateMovement();
}
function cPlayer::onPositionTarget(%this)
{
// Called when target reaches moveTo destination
// echo("cPlayer::onPositionTarget(%this);");
// echo("Position:" SPC %this.getPosition());
%this.ready = true;
%this.updateMovement();
}
function cPlayer::updateMovement(%this)
{
// echo("cPlayer::updateMovement();");
// echo("Ready:" SPC %this.ready);
if(%this.ready && %this.key1 !$= "")
{
%this.ready = false;
$pos = %this.getPosition();
$X = mFloor(getWord($pos, 0) / %this.gridSize) * %this.gridSize;
$Y = mFloor(getWord($pos, 1) / %this.gridSize) * %this.gridSize;
// echo("Position:" SPC $pos SPC "-" SPC $X SPC $Y);
// echo("Direction:" SPC %this.key);
switch$ (%this.key1)
{
case "up":
$Y -= %this.gridSize;
case "down":
$Y += %this.gridSize;
case "left":
$X -= %this.gridSize;
case "right":
$X += %this.gridSize;
default:
// Note, moveTo's callback does not fire if you are already AT the target location
%this.ready = true;
}
// echo("moveTo:" SPC $X SPC $Y);
%this.moveTo($X, $Y, %this.speed, true, true);
}
}
function cPlayer::addKey(%this, %key)
{
// Adds key to beginning of buffer
%this.removeKey(%key);
// echo("cPlayer::addKey(%this, " @ %key @ ");");
%this.key4 = %this.key3;
%this.key3 = %this.key2;
%this.key2 = %this.key1;
%this.key1 = %key;
}
function cPlayer::removeKey(%this, %key)
{
// echo("cPlayer::removeKey(%this, " @ %key @ ");");
// removes key from buffer, and shifts later keys to the beginning
switch$ (%key)
{
case %this.key1:
%this.key1 = %this.key2;
%this.key2 = %this.key3;
%this.key3 = %this.key4;
%this.key4 = "stop";
case %this.key2:
%this.key2 = %this.key3;
%this.key3 = %this.key4;
%this.key4 = "stop";
case %this.key3:
%this.key3 = %this.key4;
%this.key4 = "stop";
case %this.key4:
%this.key4 = "stop";
}
}
function playerUp()
{
// echo("playerUp();");
$player.addKey("up");
$player.updateMovement();
}
function playerDown()
{
// echo("playerDown();");
$player.addKey("down");
$player.updateMovement();
}
function playerLeft()
{
// echo("playerLeft();");
$player.addKey("left");
$player.updateMovement();
}
function playerRight()
{
// echo("playerRight();");
$player.addKey("right");
$player.updateMovement();
}
function playerUpStop()
{
// echo("playerUpStop();");
$player.removeKey("up");
$player.updateMovement();
}
function playerDownStop()
{
// echo("playerDownStop();");
$player.removeKey("down");
$player.updateMovement();
}
function playerLeftStop()
{
// echo("playerLeftStop();");
$player.removeKey("left");
$player.updateMovement();
}
function playerRightStop()
{
// echo("playerRightStop();");
$player.removeKey("right");
$player.updateMovement();
}
#3
1. object moves to new location
2. object arrives and stops
3. callback function called, **checks if key is still pressed**
4. if so go back to top!
Oh, I see you are already doing that... hehe, goodjob.
06/09/2006 (6:44 am)
Hey theo, take another look at the code I posted on the cardinal direction thread. What I did was use moveto, then when the moveto is completed a callback function is called (if you set its flag), and the object will automatically stop (if you set the flag). So,1. object moves to new location
2. object arrives and stops
3. callback function called, **checks if key is still pressed**
4. if so go back to top!
Oh, I see you are already doing that... hehe, goodjob.
Torque Owner Pavel Tovarys
Default Studio Name
in updateMovemen for move up add
schedule(500, 0, "stop_moving_up");
function stop_moving_up()
{
if( !key_up_still_pressed() )
stop_moving_up();
}