tags:

views:

170

answers:

5

Hi. I'm trying to develop a simple racing 2d game (view top-down) in C#, sdl.net. Now, I'm trying to manage speed, acceleration and brakes of my car. My problem is the algorithm. I have the loop (Events_Tick) executed 50 times per seconds, where the position of my car is processed like the following:

private void Events_Tick(object sender, TickEventArgs e)
{
    car.ProcessPosition();
}

and ProcessPosition is something like:

if (throttle)
{
    speed += 1;
    x += 1;                        
}

and finally, I draw my sprite on the new X.

The problem is that it is too fast!

So I'm asking you how to maintain 50 FPS (frames per second) and move my sprite (the car) only N pixels per second (based on its speed).

Thank you in advance! Regards!

+2  A: 

Use a double value for speed and x, then you can use Math.Round(x) for drawing.

  if (throttle == true) {
        speed+=0.05;                    
  }
  x+=speed; //move car even without acceleration

Follow Henk's advice to make your program more flexible and to be able to show the user something like 50mph instead of 0.05px per 0.02s:

double speedInMph = 50;
double screenSizeInMiles = .1;
double screenSizeInPx = 500;

if(throttle)
{
    speedInMph += 1;
}
double speedInMpms = 50/(60*60*1000);//Miles per millisecond
double xInMiles = speedInMpms * 50;
double pxPerMile = screenSizeInPx/screenSizeInMiles;
x+= xInMiles * pxPerMile;
A: 

Henk is right. You will want to create a

Thread

and call its

Sleep(Int32)

method each time in your loop to slow the animation down, where the int parameter is the pause time in milliseconds.

In your case, you will want to move the car N/50 pixels each time looping, and sleep the thread for 20 milliseconds each time.

I assume that he currently uses the Timer WinForms control (or maybe System.Timers.Timer), so this probably won't be a problem.
+1  A: 

Acceleration will be constant, depending on user input (on a simple level the car is either accelerating, deccelerating or maintaining speed).

Speed will change each frame depending on that acceleration. Each frame, update the car's speed based on both the acceleration and the proportion of a second the frame covers (i.e. 1/50th of a second in your case).

So, if your car is accelerating at 10 units distance per second, in your example the speed will increase by 1/5th of a unit distance per frame.

Just thought it was worth elaborating a little on the other answers, instead of just posting more code :-)

Andy
+1  A: 

You should add velocity according to current acceleration and handle just acceleration with your controls, limiting speed with a cap and increasing it according to time elapsed between two game loop iterations.

float accel = 10.0f; // units per squared second
float maxSpeed = 50.0f // units per second
float curSpeed = 0.0f;

//game init

while (1) {
  long timeBefore = time();
  // game loop
  long timeElapsed = time() - timeBefore;

  if (throttle) {
    curSpeed += accel*(timeElapsed / 1000.0);
    if (curSpeed > maxSpeed)
      curSpeed = maxSpeed;
  }
}

In this way you take into account the fact that a longer frame will increase your car speed more than a quicker ore, keeping it consistent with time.

This model implies a constant acceleration while you could hypotetically want a dynamic one, in that case you just move the update to the acceleration (taking into account the frame duration as for speed) and cap it to not go over a fixed threshold.

Jack
+1  A: 

First of all, because you have 2d not 1d game, you'll need your speed to be

class Vector
{
     double x;
     double y;
}

with this class, you should maintain position and speed.

Since you are 2d top-down, you'll have to implement some .RotateLeft() and .RotateRight() on the speed vector.

Rotation will be implemented like:

x' = cos(a) * x - sin(a) * y
y' = sin(a) * x + cos(a) * y

And you'll have to implement your .Move() method as follows:

void Move(Vector v)
{
    x+=v.x;
    y+=v.y;
}

EDIT: please ask away if clarification is needed, or some more in-depth discussion.

Also, you can use timer here, but try to calculate time spent from last timer event, and then multiply speed with that value when adding to the current position, you will get more accurate position that way.

a in sin() and cos() will be an angle in radians, and you will probably want degrees here.

Here is something to get you going regarding degrees and radians.

Daniel Mošmondor
Hi Daniel, thank you. I would like to ask you about rotation: can you give me little extra info ? I'm not good in math, so i ask you: about sin(a) .. what is a ? the angle ?
stighy
yes, a is the angle, and it is in radians. you'll probably want it in degrees, so you can rotate your car for 15 degrees at a time. anyway, show me the game when something will be showable :)
Daniel Mošmondor