Jump to content
  • Advertisement
Sign in to follow this  
blue_mushroom

2D car driving game with SDL

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

If you intended to correct an error in the post then please contact us.

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 this post


Link to post
Share on other sites
Advertisement
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 surface
SDL_Surface *gScreen;
SDL_Surface *car = NULL;

// Pointer to the joystick interface
SDL_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 dimensions
const int CAR_WIDTH = 100;
const int CAR_HEIGHT = 208;

// Last iteration's tick value
int gLastTick;

// Player's position
float gXPos;
float gYPos;

// Player's motion vector
float gXMov;
float gYMov;

// Player's key status
int gKeyLeft;
int gKeyRight;
int gKeyUp;
int gKeyDown;

//Function that draws the car
void 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 wall
void 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 point
int 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 this post


Link to post
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

Share this post


Link to post
Share on other sites
it's just a matter of applying the above, you could end up with something like this, for the movement code


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;




Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!