Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm trying to implement a boost pad in my XNA game using the Farseer Physics Engine. (This question applies to Box2D too, I would be happy to port working Box2D code to C#.)

By "boost pad", I mean an object that can apply a force to the player that makes him go faster than he usually can under normal circumstances. These are most often seen in non-realistic racing games (e.g., Mario Kart, F-Zero). (For the record, my particular game is a 2D side-scroller.)

I use a very simple Farseer physics Body for my player: it's just a square shape with basic linear velocity.

Normally, I move my player like this:

body.ApplyForce(ConvertUnits.ToSimUnits(force));

Then, in my Update loop method, I cap the player velocity like this (to make sure the player speed never goes above maxSpeed):

float speed = body.LinearVelocity.Length();
if (speed > maxSpeed)
    body.LinearVelocity = (maxSpeed / speed) * velocity;

I'm struggling to think of a good way to implement a boost pad. The issues:

  • What would be a good way to enforce two separate max speeds? There's one maximum speed for forces that are applied by normal player input, and another maximum speed for forces applied by boost pads.
  • If the character is going faster than the normal max speed (e.g., they just hit a boost pad), how can I still allow the player to influence his direction without increasing his overall speed?
share|improve this question
    
Should your boost be directional (think spring from Sonic or boost pad from Mario-Kart), or more like a general speed increase (speed power-up)?. In the first case, the player wouldn't keep the higher speed when he changes direction, in the second case the speed bonus will apply in all directions of movement. –  bummzack Jan 7 '12 at 10:47
add comment

2 Answers

up vote 1 down vote accepted

I wouldn't cap the player velocity like that. Instead, cap the velocity vector that comes out of your steering behaviour(s), and then apply any extra forces (ie. from explosions, boost pads, etc.). You can then cap those extra forces before combining them with the forces coming from your steering behaviours.

edit

For example, something like:

var desiredVelocity = Vector2.Zero;
if (/* player can control */)
{
    desiredVelocity = 
        Vector2.Normalize(target - this.CurrentPosition) * this.MaxSpeed;
}

var additionalVelocity = Vector2.Zero;
if (/* criteria for "boosting" */)
    additionalVelocity = /* whatever you want */

var resultantVelocity = desiredVelocity + additionalVelocity;

An example of a time when a player might not be able to apply a force might be if they are airborne for eg.

I took this code from my game, which has an overhead perspective, but your target could just be a unit vector to the left or right of the CurrentPosition, or anywhere if there was a jetpack or something.

share|improve this answer
    
Interesting. Could you provide an example to illustrate? –  Michael Jan 7 '12 at 0:27
add comment

I gave this a try and the results I got look fine to me. Here's a video of what It looks like (although YouTube messed up the framerate).

The only thing I did was multiply both the maximum speed and the forces by some arbitrary boost multiplier.

  1. Multiplying the maximum speed addresses your first question - The two separate maximum speeds become maxSpeedand maxSpeed * boostMultiplier respectively.

  2. But I noticed that the body lost responsiveness due to the increased speed. Multiplying the forces by the same ratio seemed to solve the problem. The body is still as responsive as before.

If the video seems to be what you're looking for, here's the code:

bool hasBoost = Keyboard.GetState().IsKeyDown(Keys.Space);
float boostMultiplier = hasBoost ? 4f : 1f;

if (Keyboard.GetState().IsKeyDown(Keys.Left)) 
    body.ApplyForce(new Vector2(-1, 0) * boostMultiplier); // Notice the multiplier
if (Keyboard.GetState().IsKeyDown(Keys.Right)) 
     body.ApplyForce(new Vector2(1, 0) * boostMultiplier);
if (Keyboard.GetState().IsKeyDown(Keys.Up)) 
     body.ApplyForce(new Vector2(0, -1) * boostMultiplier);
if (Keyboard.GetState().IsKeyDown(Keys.Down)) 
    body.ApplyForce(new Vector2(0, 1) * boostMultiplier);

float speed = body.LinearVelocity.Length();
if (speed > maxSpeed * boostMultiplier) // Here too and on the next line
    body.LinearVelocity = body.LinearVelocity / speed * maxSpeed * boostMultiplier;

world.Step(Math.Min((float)gameTime.ElapsedGameTime.TotalSeconds, (1f / 30f)));
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.