Search code examples
c++iossdlsdl-2

Sprite in SDL2 its not shown


I have a problem rendering an sprite from a sprite sheet loaded as a texture in SDL2. The exercise consists in showing 2 sprites in the top and bottom corners, and the other 2 where I want, the first three sprites renders well, but strangely the number four doesn't gets rendered and has the same code structure. As a result I get a black screen which gets frozen, and a message in the line 99 where I call SDL_RenderCopy in XCode 9 in Mac OS Sierra 10.12.6 saying: Thread 1: EXC_BAD_ACCESS code=1. Hope you can help me, below is the code:

#include <iostream>
#include <SDL2/SDL.h>
#include <SDL2_image/SDL_image.h>
#include <cstdio>
#include <cstdlib>

using namespace std;

const int SCREEN_WIDTH = 1300;
const int SCREEN_HEIGHT = 700;

class WTexture{//Wrapper class to organize all data from texture
    
    SDL_Texture * texture;
    int width;
    int height;
    
public:
    
    WTexture();
    ~WTexture();
    bool loadFromFile(std::string);//Load texture
    void free();//Frees texture
    void render(SDL_Rect *, SDL_Rect *);
    int getWidth();
    int getHeight();
    
};

bool init();//Initialize SDL

bool loadMedia();//Load multimedia data, in this case the sprite sheet
//And initializes coordinates for rendering.

void close();//Quit and clean up all 

SDL_Window * main_window = NULL;
SDL_Renderer * renderer = NULL;

SDL_Rect sprite_coordinates[3];//The rectangles which contains sprites
//coordinates from the loaded texture (sprite sheet).

SDL_Rect window_coordinates[3];//The rectangles which contains the
//coordinates to render sprites in screen


WTexture texture_wrapper;//An object to store the texture

WTexture::WTexture(){//Constructor
    
    texture = NULL;
    width = 0;
    height = 0;
}

WTexture::~WTexture(){//Destructor
    
    free();
}

bool WTexture::loadFromFile(std::string path){
    
    SDL_Surface * surfaceToTexture = IMG_Load(path.c_str());
    if( surfaceToTexture == NULL )
        fprintf(stderr, "%s\n", IMG_GetError());
    else{
        
        SDL_SetColorKey(surfaceToTexture, SDL_TRUE, SDL_MapRGB(surfaceToTexture->format, 0xFF, 0xFF, 0xFF));
        SDL_Texture * texture_to_return = SDL_CreateTextureFromSurface(renderer, surfaceToTexture);
        if( texture_to_return == NULL)
            fprintf(stderr, "%s\n", IMG_GetError());
        else{
            
            texture = texture_to_return;
            width = surfaceToTexture->w;
            height = surfaceToTexture->h;
            SDL_FreeSurface(surfaceToTexture);
            
        }
    }
    return texture != NULL;
    
}

void WTexture::free(){
    if( texture != NULL ){
        
        SDL_DestroyTexture(texture);
        texture = NULL;
        width = 0;
        height = 0;
    }

}

void WTexture::render(SDL_Rect * sprite_coords, SDL_Rect * dest_coords){
    
    SDL_RenderCopy(renderer, texture, sprite_coords, dest_coords);
    
}

int WTexture::getWidth(){
    
    return width;
}

int WTexture::getHeight(){
    
    return height;
}

bool init(){
    
    bool success = false;
    if(SDL_Init(SDL_INIT_VIDEO) < 0)
        fprintf(stderr, "%s\n", SDL_GetError());
    else{
        
        main_window = SDL_CreateWindow("CLip Rendering", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH,
                                       SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
        if(main_window == NULL)
            fprintf(stderr, "%s\n", SDL_GetError());
        else{
            
            renderer = SDL_CreateRenderer(main_window, -1, SDL_RENDERER_ACCELERATED);
            if(renderer == NULL)
                fprintf(stderr, "%s\n", SDL_GetError());
            else{
                
                SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
                
                if(!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1"))
                    fprintf(stderr, "%s\n", "Warning: Couldn't initialize linear filtering");
                else{
                    
                    if(!(IMG_Init(IMG_INIT_PNG) & IMG_INIT_PNG))
                        fprintf(stderr, "%s\n", IMG_GetError());
                    else success = true;
                    
                }
                
            }
            
        }
        
    }
    return success;
    
}

bool loadMedia(){
    
    bool success = true;
    
    if(!texture_wrapper.loadFromFile("/Users/linuxshotgun/Engineering/SDL_tutorial/Sources/spritesheet.png")){
        fprintf(stderr, "%s\n", SDL_GetError());
        success = false;
    }
    else{
        
        //First sprite coords (in left to righ order)
        sprite_coordinates[0].x = 0;//x coordinate of the top left corner of the sprite
        sprite_coordinates[0].y = 0;//x coordinate of the top left corner of the sprite
        sprite_coordinates[0].w = 214;//Width in pixels
        sprite_coordinates[0].h = 260;//Height in pixels
        
        //Second sprite coords
        sprite_coordinates[1].x = 268;
        sprite_coordinates[1].y = 0;
        sprite_coordinates[1].w = 192;
        sprite_coordinates[1].h = 260;
        
        //Third sprite coords
        sprite_coordinates[2].x = 0;
        sprite_coordinates[2].y = 266;
        sprite_coordinates[2].w = 212;
        sprite_coordinates[2].h = 262;
        
        //Fourth sprite coords, this sprite has the problem
        sprite_coordinates[3].x = 219;
        sprite_coordinates[3].y = 264;
        sprite_coordinates[3].w = 190;
        sprite_coordinates[3].h = 264;
        
        //Screen coordinates in which the sprites will be displayed (in order, first sprite, second).
        
        window_coordinates[0].x=0;
        window_coordinates[0].y=0;
        window_coordinates[0].w=sprite_coordinates[0].w;
        window_coordinates[0].h=sprite_coordinates[0].h;
        
        window_coordinates[1].x=650;
        window_coordinates[1].y=0;
        window_coordinates[1].w=sprite_coordinates[1].w;
        window_coordinates[1].h=sprite_coordinates[1].h;
        
        window_coordinates[2].x=0;
        window_coordinates[2].y=350;
        window_coordinates[2].w=sprite_coordinates[2].w;
        window_coordinates[2].h=sprite_coordinates[2].h;
      
        //fourth sprite display coords: Could have a bug 
        window_coordinates[3].x=650;
        window_coordinates[3].y=350;
        window_coordinates[3].w=sprite_coordinates[3].w;
        window_coordinates[3].h=sprite_coordinates[3].h;
        
    }
    return success;
    
}

void close(){
    
    
    SDL_DestroyRenderer(renderer);
    renderer = NULL;
    SDL_DestroyWindow(main_window);
    main_window = NULL;
    IMG_Quit();
    SDL_Quit();
    
    
}


int main(int argc, char *argv[]){
    
    if(!init()){
        fprintf(stderr, "%s\n", SDL_GetError());
        _Exit(EXIT_FAILURE);
    }
    if(!loadMedia()){
        fprintf(stderr, "%s\n", SDL_GetError());
        _Exit(EXIT_FAILURE);
    }
    bool quit = false;
    SDL_Event event;
    while(!quit){
        
        while(SDL_PollEvent(&event) != 0 ){
            
            if(event.type == SDL_QUIT)
                quit = true;
        }
        
        //Clear screen
        SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
        SDL_RenderClear(renderer);
        
        //render top left sprite
        texture_wrapper.render(&sprite_coordinates[0], &window_coordinates[0]);
        texture_wrapper.render(&sprite_coordinates[1], &window_coordinates[1]);
        texture_wrapper.render(&sprite_coordinates[2], &window_coordinates[2]);
        texture_wrapper.render(&sprite_coordinates[3], &window_coordinates[3]);
        
        SDL_RenderPresent(renderer);
        
    }
    close();
    return EXIT_SUCCESS;
    
}

Solution

  • Arrays sprite_coordinates[3] and window_coordinates[3] have size 3 and so accessing fourth sprite coordinates causes buffer overrun.