• 9
• 10
• 11
• 13
• 9

2D car driving game with SDL

This topic is 3930 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

Hi everybody, i have a problem, i really don't get how to make my car turn right or left or even rotate... i read tutorials about moving a dot on the screen but when i replace the dot with my car (which is rectangular image) i'm sure you imagine what happens when i press the right and left arrow keys -> the whole image moves right or left .. and i don't want that... what i want is to turn the image (car) to the right or left.... i really hope you get what i mean.... i'm desperate ... if somebody could write me example code for turning rectangular image ... i don't now if this is the way of doing that (turning a car) actually but right now this is the only thing that comes in my mind... Thanx in advance and excuse me if my question is really stupid.....

Share on other sites
I could be very wrong, but if I remember correctly, SDL doesn't have the ability to rotate images.. I saw a tutorial on LazyFoo's about manipulating images though, I would see and go from there.

Share on other sites
thanx for the quick reply, unfortunately i already read these tutorials... but i couldn't find the answer there... and i was thinking maybe this turning (rotating) is made by some c++ code (not by sdl)... i really don't know if i'm thinking right....

Share on other sites
For the car to turn instead of moving you will have to take angles into consideration.

Map each angle with an image, and display the respective image when the car turns by a certain angle.
This is what i had done in ma game that never took off. A good article is here, although its in flash. Its a good read.
http://www.gamesheep.com/free/flash-tutorials/1-flash-racing-game-1/flash-tutorial-1-1.php

Let me know how it goes.

Share on other sites
hi again... well i have now different image for each angle ... but the car only turns now... doesn't move to the right direction... and i know why is so.. and the flash tutorial is nice .. i understood the things .. the direction dependence from the cos sin functions.... but i can't integrate it to my code :( i tried ... i get the things .. but i can't use them myself :( ... i read some maths and physics for game programming .. really nice explanations ... but still... i can't .. if only there was some kind of tutorial about moving and turning rectangular image ...

Share on other sites
am not sure how to turn a rectangle around.

but your image should be turned within the rectangle... and that way the rectangle feels turned in the game.

You could post your images and your code for us to see.

Share on other sites
First off, you can look into the separate library SDL_rotozoom for rotating pictures. It's not exactly the fastest thing in the world (it's mainly intended for pre-processing), but if you are *only* rotating one small picture once a frame, it should work fine. Just remember to keep the original image and rotate based off of that, not off of other rotations, since the rotations are destructive (that is, information is lost when you rotate, so the more times you rotate, the more blurred the image gets).

For your moving problem, you will need to implement a vector of some sort. You can take the real quick way out, which I'll describe. The long way is to make a vector class that handles this for you, but if you're only going to use it once, heck, take the ad hoc method. So, a vector is simply a direction and a length. This can be represented two ways, an angle and a length, or the distance along the x axis and distance along the y axis. You need a velocity vector, which will define both where you are headed and how fast you are headed there. Either representation will work, but I think it will be easier in your case to use the angle and length representation, since you already need the length.

Now that we've decided to store the angle that you're headed and the speed at which you're traveling, we're going to have to do that. Add, if you don't already have, a 'direction' and a 'speed' variable to your car class. Now, I'm presuming that you've got 'x' and 'y' variables that defines the car's position. So, every frame you will want to move your position in the direction of the vector by the length of the vector.

x += cos(direction) * speed
y += sin(direction) * speed

This is using the cos and sin to extract it like the link your read earlier described, but only using cos() and sin() would have you move at one unit each frame. That's not very flexible, so we multiply it by the speed that you're going at, and now you're gong speed units each frame. Viola! Now all you have to do to turn the car is increment or decrement direction, and to accelerate just change the speed!

Some quick mistakes that you could make while doing this:
-Most cos() and sin() functions take radians, not degrees. As long as you're consistent, this shouldn't be a problem. Just don't expect to be able to rotate 90 degrees
-Use floating point numbers, not integers with this. If you need to have integers for drawing, you can cast them at that time.

Share on other sites
hi, i'll take the risk to piss you off ... with my car ... but i'm so confused with this.. and these are my first steps in graphics programming ... this is where i started from ... it's from a tutorial for moving a dot on the screen... and i replaced the dot with my car image ... and of course when i press the right and left arrows a get translation of the image ... but i don't want that .. i want to turn the image .. and to move it .. like a real car...
#include <stdlib.h>#include <math.h>#include "SDL/SDL.h"#include "SDL/SDL_image.h"#include <string>// Screen surface and car surfaceSDL_Surface *gScreen;SDL_Surface *car = NULL;// Pointer to the joystick interfaceSDL_Joystick *gJoystick = NULL;// Screen pitch#define PITCH (gScreen->pitch / 4)// Screen width#define WIDTH 800// Screen height#define HEIGHT 600// Background color#define BGCOLOR 0x5f0000// Wall color#define WALLCOLOR 0x9f1f1f// Definition of PI#define PI 3.1415926535897932384626433832795f// Player's thrust value#define THRUST 0.1f// Slowdown due to friction, etc.#define SLOWDOWN 0.99f// Physics iterations per second#define PHYSICSFPS 100//The car dimensionsconst int CAR_WIDTH = 100;const int CAR_HEIGHT = 208;// Last iteration's tick valueint gLastTick;// Player's positionfloat gXPos;float gYPos;// Player's motion vectorfloat gXMov;float gYMov;// Player's key statusint gKeyLeft;int gKeyRight;int gKeyUp;int gKeyDown;//Function that draws the carvoid drawcar(int x, int y, SDL_Surface* source, SDL_Surface* destination, SDL_Rect* clip = NULL ){    //Holds offsets    SDL_Rect offset;        //Get offsets    offset.x = x;    offset.y = y;        //Blit    SDL_BlitSurface( source, clip, destination, &offset );}//Function that draws the wallvoid drawrect(int x, int y, int width, int height, int c){  int i, j;  for (i = 0; i < height; i++)  {    // vertical clipping: (top and bottom)    if ((y + i) >= 0 && (y + i) < HEIGHT)    {      int len = width;      int xofs = x;      // left border      if (xofs < 0)      {        len += xofs;        xofs = 0;      }      // right border      if (xofs + len >= WIDTH)      {        len -= (xofs + len) - WIDTH;      }      int ofs = (i + y) * PITCH + xofs;      // note that len may be 0 at this point,       // and no pixels get drawn!      for (j = 0; j < len; j++)        ((unsigned int*)gScreen->pixels)[ofs + j] = c;    }  }}void init(){  //Load the car image into temporary surface  SDL_Surface *temp = IMG_Load("car.png");  //Convert the surface into the screen format   car = SDL_ConvertSurface(temp, gScreen->format, SDL_SWSURFACE);  //Free the old surface  SDL_FreeSurface(temp);  //Color key car surface  SDL_SetColorKey( car, SDL_SRCCOLORKEY, SDL_MapRGB( car->format, 0, 0xFF, 0xFF ) );  gXPos = (WIDTH / 2) - (CAR_WIDTH / 2);  gYPos = (HEIGHT / 2) - (CAR_HEIGHT / 2);  gXMov = 0;  gYMov = 0;  gKeyLeft = 0;  gKeyRight = 0;  gKeyUp = 0;  gKeyDown = 0;  if (SDL_NumJoysticks() > 0)  {    gJoystick = SDL_JoystickOpen(0);		    if (SDL_JoystickNumAxes(gJoystick) < 2)    {      // Not enough axes for our use; don't use the joystick.      SDL_JoystickClose(gJoystick);      gJoystick = NULL;    }  }  gLastTick = SDL_GetTicks();}void deinit(){  if (gJoystick)    SDL_JoystickClose(gJoystick);}void clean_up(){    //Free the surfaces    SDL_FreeSurface( car );        }void render(){     // Ask SDL for the time in milliseconds  int tick = SDL_GetTicks();  if (tick <= gLastTick)   {    SDL_Delay(1);    return;  }  while (gLastTick < tick)  {    if (gKeyLeft) gXMov -= THRUST;    if (gKeyRight) gXMov += THRUST;    if (gKeyUp) gYMov -= THRUST;    if (gKeyDown) gYMov += THRUST;	if (gJoystick)    {      gXMov += (SDL_JoystickGetAxis(gJoystick, 0) / 32768.0f) * THRUST;      gYMov += (SDL_JoystickGetAxis(gJoystick, 1) / 32768.0f) * THRUST;    }    	gXMov *= SLOWDOWN;    gYMov *= SLOWDOWN;    gXPos += gXMov;    gYPos += gYMov;    gLastTick += 1000 / PHYSICSFPS;  }  // Lock surface if needed  if (SDL_MUSTLOCK(gScreen))    if (SDL_LockSurface(gScreen) < 0)       return;  // fill background  drawrect(0, 0, WIDTH, HEIGHT, BGCOLOR);      // draw borders  drawrect(0, 0, 100, HEIGHT, WALLCOLOR);           drawrect(WIDTH - 100, 0, 100, HEIGHT, WALLCOLOR);   // draw the player object  drawcar((int)gXPos,             (int)gYPos,             car,             gScreen);          // Unlock if needed    if (SDL_MUSTLOCK(gScreen))         SDL_UnlockSurface(gScreen);  // Tell SDL to update the whole gScreen    SDL_UpdateRect(gScreen, 0, 0, WIDTH, HEIGHT);    }// Entry pointint main(int argc, char *argv[]){  // Initialize SDL's subsystems  if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0)   {    fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());    exit(1);  }  // Register SDL_Quit to be called at exit; makes sure things are  // cleaned up when we quit.  atexit(SDL_Quit);  // make sure our clean_up gets called at shutdown.  atexit(clean_up);  // make sure our deinit gets called at shutdown.  atexit(deinit);      // Attempt to create a WIDTHxHEIGHT window with 32bit pixels.  gScreen = SDL_SetVideoMode(WIDTH, HEIGHT, 32, SDL_SWSURFACE);    init();  // If we fail, return error.  if (gScreen == NULL)   {    fprintf(stderr, "Unable to set up video: %s\n", SDL_GetError());    exit(1);  }  // Main loop: loop forever.  while (1)  {    // Render stuff    render();    // Poll for events, and handle the ones we care about.    SDL_Event event;    while (SDL_PollEvent(&event))     {      switch (event.type)       {      case SDL_KEYDOWN:        switch (event.key.keysym.sym)        {        case SDLK_LEFT:          gKeyLeft = 1;          break;        case SDLK_RIGHT:          gKeyRight = 1;          break;        case SDLK_UP:          gKeyUp = 1;          break;        case SDLK_DOWN:          gKeyDown = 1;          break;        }        break;      case SDL_KEYUP:                  switch (event.key.keysym.sym)        {        case SDLK_ESCAPE:          // If escape is pressed, return (and thus, quit)          return 0;        case SDLK_LEFT:          gKeyLeft = 0;          break;        case SDLK_RIGHT:          gKeyRight = 0;          break;        case SDLK_UP:          gKeyUp = 0;          break;        case SDLK_DOWN:          gKeyDown = 0;          break;        }        break;      case SDL_QUIT:        return(0);      }    }  }}

... and this is my car

Share on other sites
a solution that might be easier than rotating the image would be to have alternating images of the car banking if you're only allowing turning in one dimension

if (gKeyLeft) Angle-=AngleStep;if (gKeyRight) Angle+=AngleStep;if (gKeyUp) Thrust+=Accel;if (gKeyDown) Thrust-=Accel;gXMov=Accel*cos(Angle);gYMov=Accel*sin(Angle);Accel*=SLOWDOWN;gXPos += gXMov;gYPos += gYMov;