   [SDL] Animation not working
  Hi all, I've recently started following the Lazyfoo tutorials and there are a couple different ones I tried to combine. I tried to animate the stick figure from tutorial 20 and place it on the scrolling background of tutorial 21. All that's happening is the whole sprite sheet is being shown rather than the animated frames. I don't know how to fix this. Please let me know if you can help. This is what the code looks like:/* -- Include the precompiled libraries -- */    #ifdef WIN32    #pragma comment(lib, "SDL.lib")    #pragma comment(lib, "SDLmain.lib")#pragma comment(lib, "SDL_image.lib")    #endif //The headers#include "SDL.h"#include "SDL_image.h"#include <string>//Screen attributesconst int SCREEN_WIDTH = 640;const int SCREEN_HEIGHT = 480;const int SCREEN_BPP = 32;//The frame rateconst int FRAMES_PER_SECOND = 20;//The foo dimensionsconst int FOO_WIDTH = 64;const int FOO_HEIGHT = 205;//The direction status of the stick figureconst int FOO_RIGHT = 0;const int FOO_LEFT = 1;//The dimensions of the levelconst int LEVEL_WIDTH = 1280;const int LEVEL_HEIGHT = 960;//The surfacesSDL_Surface *foo = NULL;SDL_Surface *background = NULL;SDL_Surface *screen = NULL;//The event structureSDL_Event event;//The areas of the sprite sheetSDL_Rect clipsRight[ 4 ];SDL_Rect clipsLeft[ 4 ];//The cameraSDL_Rect camera = { 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT };//The fooclass Foo{    private:    //The X and Y offsets of the foo    int x, y;   //The velocity of the foo    int xVel, yVel;    //Its current frame    int frame;   //Its animation status    int status;    public:    //Initializes the variables    Foo();   //Takes key presses and adjusts the foo's velocity    void handle_input();   //Moves the foo    void move();   //Shows the foo on the screen    void show();   //Sets the camera over the foo    void set_camera();};//The timerclass Timer{    private:    //The clock time when the timer started    int startTicks;   //The ticks stored when the timer was paused    int pausedTicks;   //The timer status    bool paused;    bool started;   public:    //Initializes variables    Timer();   //The various clock actions    void start();    void stop();    void pause();    void unpause();   //Gets the timer's time    int get_ticks();   //Checks the status of the timer    bool is_started();    bool is_paused();    };SDL_Surface *load_image( std::string filename ) {    //The image that's loaded    SDL_Surface* loadedImage = NULL;   //The optimized surface that will be used    SDL_Surface* optimizedImage = NULL;   //Load the image    loadedImage = IMG_Load( filename.c_str() );   //If the image loaded    if( loadedImage != NULL )    {   //Create an optimized surface   optimizedImage = SDL_DisplayFormat( loadedImage ); //Free the old surface   SDL_FreeSurface( loadedImage ); //If the surface was optimized   if( optimizedImage != NULL )   {  //Color key surface  SDL_SetColorKey( optimizedImage, SDL_SRCCOLORKEY, SDL_MapRGB( optimizedImage->format, 0, 0xFF, 0xFF ) );   }    }   //Return the optimized surface    return optimizedImage;}void apply_surface( 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 );}void set_clips(){    //Clip the sprites    clipsRight[ 0 ].x = 0;    clipsRight[ 0 ].y = 0;    clipsRight[ 0 ].w = FOO_WIDTH;    clipsRight[ 0 ].h = FOO_HEIGHT;   clipsRight[ 1 ].x = FOO_WIDTH;    clipsRight[ 1 ].y = 0;    clipsRight[ 1 ].w = FOO_WIDTH;    clipsRight[ 1 ].h = FOO_HEIGHT;   clipsRight[ 2 ].x = FOO_WIDTH * 2;    clipsRight[ 2 ].y = 0;    clipsRight[ 2 ].w = FOO_WIDTH;    clipsRight[ 2 ].h = FOO_HEIGHT;   clipsRight[ 3 ].x = FOO_WIDTH * 3;    clipsRight[ 3 ].y = 0;    clipsRight[ 3 ].w = FOO_WIDTH;    clipsRight[ 3 ].h = FOO_HEIGHT;   clipsLeft[ 0 ].x = 0;    clipsLeft[ 0 ].y = FOO_HEIGHT;    clipsLeft[ 0 ].w = FOO_WIDTH;    clipsLeft[ 0 ].h = FOO_HEIGHT;   clipsLeft[ 1 ].x = FOO_WIDTH;    clipsLeft[ 1 ].y = FOO_HEIGHT;    clipsLeft[ 1 ].w = FOO_WIDTH;    clipsLeft[ 1 ].h = FOO_HEIGHT;   clipsLeft[ 2 ].x = FOO_WIDTH * 2;    clipsLeft[ 2 ].y = FOO_HEIGHT;    clipsLeft[ 2 ].w = FOO_WIDTH;    clipsLeft[ 2 ].h = FOO_HEIGHT;   clipsLeft[ 3 ].x = FOO_WIDTH * 3;    clipsLeft[ 3 ].y = FOO_HEIGHT;    clipsLeft[ 3 ].w = FOO_WIDTH;    clipsLeft[ 3 ].h = FOO_HEIGHT;}bool init(){    //Initialize all SDL subsystems    if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )    {   return false;   }   //Set up the screen    screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE );   //If there was an error in setting up the screen    if( screen == NULL )    {   return false;   }   //Set the window caption    SDL_WM_SetCaption( "Move the Foo", NULL );   //If everything initialized fine    return true;}bool load_files(){    //Load the foo image    foo = load_image( "foo.png" );   //Load the background    background = load_image( "bg.png" );   //If there was a problem in loading the foo    if( foo == NULL )    {   return false;   }   //If there was a problem in loading the background    if( background == NULL )    {   return false;   }   //If everything loaded fine    return true;}void clean_up(){    //Free the surfaces    SDL_FreeSurface( foo );    SDL_FreeSurface( background );   //Quit SDL    SDL_Quit();}Foo::Foo(){    //Initialize the offsets    x = 0;    y = 0;   //Initialize the velocity    xVel = 0;    yVel = 0;//Initialize animation variables    frame = 0;    status = FOO_RIGHT;}void Foo::handle_input(){    //If a key was pressed    if( event.type == SDL_KEYDOWN )    {   //Adjust the velocity   switch( event.key.keysym.sym )   {  case SDLK_UP: yVel -= FOO_HEIGHT / 2; break;  case SDLK_DOWN: yVel += FOO_HEIGHT / 2; break;  case SDLK_LEFT: xVel -= FOO_WIDTH / 2; break;  case SDLK_RIGHT: xVel += FOO_WIDTH / 2; break;  }    }    //If a key was released    else if( event.type == SDL_KEYUP )    {   //Adjust the velocity   switch( event.key.keysym.sym )   {  case SDLK_UP: yVel += FOO_HEIGHT / 2; break;  case SDLK_DOWN: yVel -= FOO_HEIGHT / 2; break;  case SDLK_LEFT: xVel += FOO_WIDTH / 2; break;  case SDLK_RIGHT: xVel -= FOO_WIDTH / 2; break;  }  }}void Foo::move(){    //Move the foo left or right    x += xVel;   //If the foo went too far to the left or right    if( ( x < 0 ) || ( x + FOO_WIDTH > LEVEL_WIDTH ) )    {   //move back   x -= xVel;   }   //Move the foo up or down    y += yVel;   //If the foo went too far up or down    if( ( y < 0 ) || ( y + FOO_HEIGHT > LEVEL_HEIGHT ) )    {   //move back   y -= yVel;   }    }void Foo::show(){//If Foo is moving left    if( xVel < 0 )    {   //Set the animation to left   status = FOO_LEFT; //Move to the next frame in the animation   frame++;    }    //If Foo is moving right    else if( xVel > 0 )    {   //Set the animation to right   status = FOO_RIGHT; //Move to the next frame in the animation   frame++;    }    //If Foo standing    else    {   //Restart the animation   frame = 0;   }   //Loop the animation    if( frame >= 4 )    {   frame = 0;    }    //Show the foo    //apply_surface( x - camera.x, y - camera.y, foo, screen );if( status == FOO_RIGHT )    {  //apply_surface( x, SCREEN_HEIGHT - FOO_HEIGHT, foo, screen, &clipsRight[ frame ] );apply_surface( x - camera.x, y - camera.y, foo, screen );}    else if( status == FOO_LEFT )    {  //apply_surface( x, SCREEN_HEIGHT - FOO_HEIGHT, foo, screen ); //, &clipsLeft[ frame ] ); apply_surface( x - camera.x, y - camera.y, foo, screen, &clipsLeft[ frame ] );}}void Foo::set_camera(){    //Center the camera over the foo    camera.x = ( x + FOO_WIDTH / 2 ) - SCREEN_WIDTH / 2;    camera.y = ( y + FOO_HEIGHT / 2 ) - SCREEN_HEIGHT / 2;   //Keep the camera in bounds.    if( camera.x < 0 )    {   camera.x = 0;   }    if( camera.y < 0 )    {   camera.y = 0;   }    if( camera.x > LEVEL_WIDTH - camera.w )    {   camera.x = LEVEL_WIDTH - camera.w;   }    if( camera.y > LEVEL_HEIGHT - camera.h )    {   camera.y = LEVEL_HEIGHT - camera.h;   }    }Timer::Timer(){    //Initialize the variables    startTicks = 0;    pausedTicks = 0;    paused = false;    started = false;    }void Timer::start(){    //Start the timer    started = true;   //Unpause the timer    paused = false;   //Get the current clock time    startTicks = SDL_GetTicks();    }void Timer::stop(){    //Stop the timer    started = false;   //Unpause the timer    paused = false;    }void Timer::pause(){    //If the timer is running and isn't already paused    if( ( started == true ) && ( paused == false ) )    {   //Pause the timer   paused = true;  //Calculate the paused ticks   pausedTicks = SDL_GetTicks() - startTicks;    }}void Timer::unpause(){    //If the timer is paused    if( paused == true )    {   //Unpause the timer   paused = false;  //Reset the starting ticks   startTicks = SDL_GetTicks() - pausedTicks; //Reset the paused ticks   pausedTicks = 0;    }}int Timer::get_ticks(){    //If the timer is running    if( started == true )    {   //If the timer is paused   if( paused == true )   {  //Return the number of ticks when the timer was paused  return pausedTicks;   }   else   {  //Return the current time minus the start time  return SDL_GetTicks() - startTicks;   }   }   //If the timer isn't running    return 0;    }bool Timer::is_started(){    return started;    }bool Timer::is_paused(){    return paused;    }int main( int argc, char* args[] ){    //Quit flag    bool quit = false;   //The foo    Foo myFoo;   //The frame rate regulator    Timer fps;   //Initialize    if( init() == false )    {   return 1;    }   //Load the files    if( load_files() == false )    {   return 1;    }   //While the user hasn't quit    while( quit == false )    {   //Start the frame timer   fps.start(); //While there's events to handle   while( SDL_PollEvent( &event ) )   {  //Handle events for the foo  myFoo.handle_input();    //If the user has Xed out the window  if( event.type == SDL_QUIT )  { //Quit the program quit = true;  }   } //Move the foo   myFoo.move(); //Set the camera   myFoo.set_camera(); //Show the background   apply_surface( 0, 0, background, screen, &camera ); //Show the foo on the screen   myFoo.show(); //Update the screen   if( SDL_Flip( screen ) == -1 )   {  return 1;  } //Cap the frame rate   if( fps.get_ticks() < 1000 / FRAMES_PER_SECOND )   {  SDL_Delay( ( 1000 / FRAMES_PER_SECOND ) - fps.get_ticks() );   }    }  //Clean up    clean_up();   return 0;    }
  You are indeed blitting the entire surface.  The second argument to SDL_Blit will define a source surface rect to blit.  Your apply_surface function actually provides an interface to this.  In fact, you seem to have used that interface in your code but commented it out.  Take a look at the last argument to apply_surface in the code you commented out.   ;  I found my errors. First, I wrote out the set_clips() function but did not include it in main(). Second, for my two calls to apply_surface (one for left, one for right) I had to use “x - camera.x”.Seems like Foo::set_camera() tries to center the view on the guy, but I was ignoring the camera position when drawing the guy.So the code changed to [source = cpp]//Show the foo   if( status == FOO_RIGHT )    {  apply_surface( x - camera.x, SCREEN_HEIGHT - FOO_HEIGHT, foo, screen, &clipsRight[ frame ] );}    else if( status == FOO_LEFT )    {  apply_surface( x - camera.x, SCREEN_HEIGHT - FOO_HEIGHT, foo, screen, &clipsLeft[ frame ] );}