Sign in to follow this  

SDL: Why does this not work?

This topic is 4708 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

Hello, I'm creating a simple tile engine in SDL, and right now, I just want to create a map, put a sprite on it and be able to move it. I got this code, and it compiles fine, but it just shows the map and not the sprite. Can someone help me figure this out?
#include <iostream>
#include <SDL/SDL.h>
using namespace std; //yes, I know this is evil.
SDL_Surface *screen;
SDL_Surface *grass;
SDL_Surface *water;
SDL_Surface *wall;
SDL_Surface *tree;
SDL_Surface *mySprite;
int sxpos = 0;
int sypos = 0;
int map[10][10] = {{4, 4, 4, 4, 4, 4, 4, 4, 4, 4},
                   {4, 1, 1, 1, 1, 1, 1, 1, 1, 4},
                   {4, 1, 2, 2, 1, 1, 2, 2, 1, 4},
                   {4, 1, 3, 3, 3, 3, 3, 3, 1, 4},
                   {4, 1, 2, 2, 1, 1, 2, 2, 1, 4},
                   {4, 1, 1, 1, 1, 1, 1, 1, 1, 4},
                   {4, 1, 3, 3, 3, 3, 3, 3, 1, 4},
                   {4, 1, 1, 1, 4, 4, 1, 1, 1, 4},
                   {4, 1, 1, 1, 1, 1, 1, 1, 1, 4},
                   {4, 4, 4, 4, 4, 4, 4, 4, 4, 4}};
int xpos = 0;
int ypos = 0;
int InitImages() {
  grass = SDL_LoadBMP("grass.bmp");
  water = SDL_LoadBMP("water.bmp");
  wall = SDL_LoadBMP("wall.bmp");
  tree = SDL_LoadBMP("tree.bmp");
  mySprite = SDL_LoadBMP("mysprite.bmp");
  return 0;
}
int SDL_BlitSurface(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *destrect);
void drawIMG(SDL_Surface *img, int x, int y) {
  SDL_Rect dest;
  dest.x = x;
  dest.y = y;
  SDL_BlitSurface(img, NULL, screen, &dest);
}
int drawMap() {
  xpos = 0;
  ypos = 0;
  for(int y=0; y<=9; ++y) {
    xpos = 0;
    for(int x=0; x<=9; ++x) {
      if(map[y][x] == 1) {
        drawIMG(grass, xpos, ypos);
        SDL_Flip(screen);
      }
      if(map[y][x] == 2) {
        drawIMG(water, xpos, ypos);
        SDL_Flip(screen);
      }
      if(map[y][x] == 3) {
        drawIMG(wall, xpos, ypos);
        SDL_Flip(screen);
      }
      if(map[y][x] == 4) {
        drawIMG(tree, xpos, ypos);
        SDL_Flip(screen);
      }
      xpos += 32;
      if(x == 9) {
        ypos += 32;
      }
    }
  }
  return 1;
}
void sprite() {
  drawIMG(mySprite, sxpos, sypos);
}
void drawScene() {
  drawMap();
  sprite();
  SDL_Flip(screen);
}
int main(int argc, char *argv[]) {
  Uint8* keys;
  if(SDL_Init(SDL_INIT_VIDEO) < 0) {
    cout<<"Unable to init SDL."<<endl;
    SDL_GetError();
  }
  atexit(SDL_Quit);
  screen = SDL_SetVideoMode(640, 480, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);
  if(screen == NULL) {
    cout<<"Unable to set video mode."<<endl;
    SDL_GetError();
  }
  InitImages();
  drawMap();
  int done=0;
  while(done == 0)
  {
    SDL_Event event;
    while ( SDL_PollEvent(&event) )
    {
      if ( event.type == SDL_QUIT )  {  done = 1;  }

      if ( event.type == SDL_KEYDOWN )
      {
        if ( event.key.keysym.sym == SDLK_ESCAPE ) { done = 1; }
      }
    }
    keys = SDL_GetKeyState(NULL);
    if(keys[SDLK_UP]) {
      for(int sxu=0; sxu<=32; sxu++) {
        for(int syu=0; syu<=32; syu++) {
          sypos -= 1;
        }
      }
    }
    if(keys[SDLK_DOWN]) {
      for(int sxd=0; sxd<=32; sxd++) {
        for(int syd=0; syd<=32; syd++) {
          sypos +=1;
        }
      }
    }
    if(keys[SDLK_LEFT]) {
      for(int sxl=0; sxl<=32; sxl++) {
        for(int syl=0; syl<=32; syl++) {
          sxpos -= 1;
        }
      }
    }
    if(keys[SDLK_RIGHT]) {
      for(int sxr=0; sxr<=32; sxr++) {
        for(int syr=0; syr<=32; syr++) {
          sxpos += 1;
        }
      }
    }
    drawScene();
  }
  return 0;
}

Thanks.

Share this post


Link to post
Share on other sites

if(keys[SDLK_UP]) {
for(int sxu=0; sxu<=32; sxu++) {
for(int syu=0; syu<=32; syu++) {
sypos -= 1;
}
}
}

Not sure what this is trying to accomplish. You want to decrease sypos by 1089?
sxu<=32 means 33 iterations, 33*33. And even then, why loop it, just decrease it by the final calculation.

As for why its not showing, my initial impression is that you don't have a src SDL_Rect in the drawing thing for the sprite, but I'm not sure.

Share this post


Link to post
Share on other sites
Quote:
Original post by Meta Adam
Made the sprite come up, but then I pressed right and it disappeared.


Heed Inmate2993's advice on movement [wink].

[source lang = "cpp"]
if(keys[SDLK_UP])
{
sypos -= 32;
}
if(keys[SDLK_DOWN]) {
sypos +=32;
}
if(keys[SDLK_LEFT])
{
sxpos -= 32;
}

if(keys[SDLK_RIGHT]) {
sxpos += 32;
}




- Drew

Share this post


Link to post
Share on other sites
There, it works now, but the loops were for the sprite, if say down was pressed, it move 1 square, rather than 1 pixel, 1 square is 32 pixels wide and high, so I figured hey add it up in a for loop. Also, I want it to slide there with 1 press, not just appear there.

Share this post


Link to post
Share on other sites
Quote:
Original post by Meta Adam
There, it works now, but the loops were for the sprite, if say down was pressed, it move 1 square, rather than 1 pixel, 1 square is 32 pixels wide and high, so I figured hey add it up in a for loop. Also, I want it to slide there with 1 press, not just appear there.


Ahh yes - that's a better idea than what I posted. Glad it works!

Share this post


Link to post
Share on other sites
Quote:
Original post by Meta Adam
Ahh, I just changed it back to 1, said heck with it, lol, but the next question is, collision detection?


This tutorial from Cone3D should be what you need. Basically you compare "bounding boxes" of the object with each other and handle the even if they overlap. Go ahead and take a look at that - I know of a few more tutorials on collisions, but I can't find them at the moment.

- Drew

Share this post


Link to post
Share on other sites
Alright, this guy is of the wrong impression of how the code flow. If you want to make a sprite move 1 pixel at a time, but across a full box, you need to program the system to automatically move the sprite after each iteration. For instance, look at this code:

while(1)
{
keys = SDL_GetKeyState(NULL);
if(keys[SDLK_UP])
{
if ( ( my_sprite.source_y == my_sprite.target_y )
&& ( my_sprite.source_x == my_sprite.target_x ) )
my_sprite.target_y -= 32;
}
else if (keys[SDLK_DOWN])
{
if ( ( my_sprite.source_y == my_sprite.target_y )
&& ( my_sprite.source_x == my_sprite.target_x ) )
my_sprite.target_y += 32;
}
if (my_sprite.source_y > my_sprite.target_y)
{
my_sprite.source_y -= 1;
}
else if (my_sprite.source_y < my_sprite.target_y)
{
my_sprite.source_y += 1;
}
blit( my_sprite );
}


Its rudimentary, but you should see what I'm pointing at. You have to keep a target destination for the sprite, but draw where the sprite actually is from a different set of variables. Then, on each iteration of the loop, it'll move the sprite accordingly and not allow the player to interrupt the movement.

Share this post


Link to post
Share on other sites
The reason your movement is so fast is because you need to make it time-based.

Your frame rate is so fast that when you hold the key down like that, it registers several "keypresses" per frame. What you need to do is time how long a frame takes, decide how far you want it to move per frame, and increment the position accordingly.

This means that whether your game runs at 20fps or 200fps, the rate of movement is the same. Otherwise if for example it becomes a networked game, the player with the higher framerate has a distinct advantage.

code is something like this:


// these are for calculating FPS and movement
float currentTime;
float lastTime;
float frameInterval;

int SPEED; // set this to how many pixels you want your sprite to move per SECOND. Play with it until you find a value that seems right.

// in your keypress event
// if (<right movement key is down>)
sprite.xpos += SPEED * frameInterval;

// Draw frame here:
void DrawFrame(void ) {
// calculate frame interval
currentTime = SDL_GetTicks() * 0.001f;
frameInterval = currentTime - lastTime;
lastTime = currentTime;

DrawTiles();
DrawSprite();

}



Also, storing your sprite positions as floats makes all this a little easier. Convert to ints immediately before blitting.

Share this post


Link to post
Share on other sites
Quote:
Original post by andyZER0
Why is *** Source Snippet Removed *** evil?


Its (I think) generally considered bad practice to include the entire std namespace when you are only using a few bits of it. You wouldn't want to include the entire namespace when using just cout for instance, you'd just do:

using std::cout;


Share this post


Link to post
Share on other sites

This topic is 4708 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this