Game Development Community

Top-down player steering

by Morten Hougs · in Torque Game Builder · 05/23/2006 (11:54 am) · 5 replies

Newbie alert.

This is my first non-tutorial game attempt, so please bear with my. I'm not even sure this is the right forum - if not, please direct me to the right place. Thanks.

I'm trying to achieve a top-down car steering effect for my player. I can make it move along the X and Y axis, like the contols described in the TGB Basic Tutorial (space shooter).

However, this control is no good for a top-down car player that needs to be able to steer left / right, go forwards and backwards, all depending on the position and direction of the car (e.g. left turn should always turn left from the player objects point of view).

Could anyone point me in the right direction? Examples?

Thanks!

#1
05/23/2006 (12:11 pm)
Personally, I would draw the car facing 'up' the screen. Then I would use .setForwardMovementOnly so that applying either positive or negative Y forces will make the car go forward and backward. For turning, you just have the left and right keys alter the rotation of the car.

Should be pretty straightforward.
#2
05/24/2006 (1:51 pm)
Thanks for the tip!
Ok, I managed to get it working, all except for being able to "reverse" the player. Forward movement works nicely combined with turning.
Moving forward is done by %this.setLinearVelocityPolar(%this.getRotation(),$pRacer.maxForwardSpeed);

My player object is .setForwardMovementOnly - which somewhat explains why I can't go backwards. Or am I missing something?

If I ommit the setForwardMovementOnly, my player can go forwards and backwards and turn, however turning the player could only be achieved by "tapping" left og right. Holding down left/right while moving forwards just rotated the player on it's own axis, and moved him in the initial forward pointing direction.

What am I missing?
#3
05/28/2006 (11:07 am)
@Morten

What your missing for the turning is the fact that the bindCMD() function only run's an updateMovement() when a key is pressed or released. What you need is a constant loop to check for keypresses. Kinda like your standard game loop. Here's an example of what im using:



function whateverobject::onLevelLoaded(%this,%scenegraph)
{
$player = %this; //set the global player

moveMap.bindCMD(keyboard,"A","keypress(\"w\")","keypress(\"wUP\")");
//repeat for every key you wanna use

//start your keyboard loop
whateverobject.updateMovement();
}


function whateverobject::keypress(%key)
{

switch$(%key)

{
case "w":
$player.moveForward = true;

case "wUP":
$player.moveForward = false;

//etc...what ever key presses you want

}

}

function whateverobject::updateMovement()
{


if(player.moveFoward)
$player.setLinearVelocityPolar($player.getRotation(), 30);

if(player.moveReverse)
$player.setLinearVelocityPolar($player.getRotation(),-30);

if(player.turnLeft)
$player.setRotation($player.getRotation() + 5);

if(player.turnRight)
$player.setRotation($player.getRotation() - 5);

//there is more code that would be needed to insure smooth movement..but this is just a basic example.



$player.schedule(100,updateMovement); //runs updateMovement every 100 milliseconds to check input.

}



Some of my syntax may be off, since im not at home right now. All this does is setup a function that checks for keys that have been pressed instead of acting only when the key is pressed or released.

Im sure there is an even easier way to implement this, but ive only been using tgb for about a week myself...heh! Hope that helps!
#4
05/29/2006 (10:21 pm)
@Eric

Thanks for the example. Turns out I was missing the scheduling in updateMovement, which made all the difference! My top-down vehicle control now works pretty well - steering wise, although there are still some issues with going from forward moving state to reverse state, and having some kind of braking mechanism in between.

Also, I haven't got my head around implementing proper physics - friction, mass etc. which I assume is the key to getting proper forward and backward movement going, i.e. letting go of the forward key should not stop the car emmediately, but mass/friction/inertia should keep it moving. I've used the setDamping function in an attempt to achieve this, and it somewhat gives the desired effect, but not exaclty what I'm after.


Thanks for all the help so far!
#5
05/31/2006 (12:29 pm)
Quote:Also, I haven't got my head around implementing proper physics - friction, mass etc. which I assume is the key to getting proper forward and backward movement going, i.e. letting go of the forward key should not stop the car emmediately, but mass/friction/inertia should keep it moving. I've used the setDamping function in an attempt to achieve this, and it somewhat gives the desired effect, but not exaclty what I'm after.

This design issue comes up from time to time, so hopefully we can help clear it up!

The first main misunderstanding is realizing/remembering that TGB is a 2 dimensional simulation, and that's important when you think about the physics of a top-down style shooter. If you think about the layout of a TD shooter, your 2 dimensions are already used in your forward/back/left/right, and therefore their isn't a dimension to actually apply physics against to implement a friction component against the "background"--picture it in your mind and you'll realize that you would need a gravity force that goes in to the screen to have a friction component to slow down movement. Being 2 dimensional, the TGB physics aren't going to allow for this.

You have two options to get the effect you are looking for:

--Write a CUSTOM collision/physics response for your vehicle in C++. Most flexible, probably most difficult.

--Use either an ::onUpdateScene() or related time based callback to have your forward velocity fall off when a user input isn't given, or simply schedule a falloff of velocity over time when they let go of the "forward" or "back" key. You could use a series of schedules in a semi-recursive concept to incrementally decrease the velocity to a rest state rather easily with this technique.