SDL_BlitSurface segmentation fault (surfaces aren't null)

Posted by Trollkemada on Game Development See other posts from Game Development or by Trollkemada
Published on 2012-11-24T12:48:28Z Indexed on 2012/11/24 17:19 UTC
Read the original article Hit count: 280

Filed under:
|

My app is crashing on SDL_BlitSurface() and i can't figure out why. I think it has something to do with my static object. If you read the code you'll why I think so.

This happens when the limits of the map are reached, i.e. (i>width || j>height). This is the code:

Map.cpp (this render)

Tile const * Map::getTyle(int i, int j) const {
    if (i >= 0 && j >= 0 && i < width && j < height) {
        return data[i][j];
    } else {
        return &Tile::ERROR_TYLE;  // This makes SDL_BlitSurface (called later) crash
        //return new Tile(TileType::ERROR); // This works with not problem (but is memory leak, of course)
    }
}


void Map::render(int x, int y, int width, int height) const {
    //DEBUG("(Rendering...) x: "<<x<<", y: "<<y<<", width: "<<width<<", height: "<<height);
    int firstI = x / TileType::PIXEL_PER_TILE;
    int firstJ = y / TileType::PIXEL_PER_TILE;
    int lastI = (x+width) / TileType::PIXEL_PER_TILE;
    int lastJ = (y+height) / TileType::PIXEL_PER_TILE;

    // The previous integer division rounds down when dealing with positive values, but it rounds up
    // negative values. This is a fix for that (We need those values always rounded down)
    if (firstI < 0) {
        firstI--;
    }

    if (firstJ < 0) {
        firstJ--;
    }

    const int firstX = x;
    const int firstY = y;

    SDL_Rect srcRect;
    SDL_Rect dstRect;

    for (int i=firstI; i <= lastI; i++) {
        for (int j=firstJ; j <= lastJ; j++) {

            if (i*TileType::PIXEL_PER_TILE < x) {
                srcRect.x = x % TileType::PIXEL_PER_TILE;
                srcRect.w = TileType::PIXEL_PER_TILE - (x % TileType::PIXEL_PER_TILE);
                dstRect.x = i*TileType::PIXEL_PER_TILE + (x % TileType::PIXEL_PER_TILE) - firstX;
            } else if (i*TileType::PIXEL_PER_TILE >= x + width) {
                srcRect.x = 0;
                srcRect.w = x % TileType::PIXEL_PER_TILE;
                dstRect.x = i*TileType::PIXEL_PER_TILE - firstX;
            } else {
                srcRect.x = 0;
                srcRect.w = TileType::PIXEL_PER_TILE;
                dstRect.x = i*TileType::PIXEL_PER_TILE - firstX;
            }

            if (j*TileType::PIXEL_PER_TILE < y) {
                srcRect.y = 0;
                srcRect.h = TileType::PIXEL_PER_TILE - (y % TileType::PIXEL_PER_TILE);
                dstRect.y = j*TileType::PIXEL_PER_TILE + (y % TileType::PIXEL_PER_TILE) - firstY;
            } else if (j*TileType::PIXEL_PER_TILE >= y + height) {
                srcRect.y = y % TileType::PIXEL_PER_TILE;
                srcRect.h = y % TileType::PIXEL_PER_TILE;
                dstRect.y = j*TileType::PIXEL_PER_TILE - firstY;
            } else {
                srcRect.y = 0;
                srcRect.h = TileType::PIXEL_PER_TILE;
                dstRect.y = j*TileType::PIXEL_PER_TILE - firstY;
            }

            SDL::YtoSDL(dstRect.y, srcRect.h);

            SDL_BlitSurface(getTyle(i,j)->getType()->getSurface(), &srcRect, SDL::getScreen(), &dstRect); // <-- Crash HERE

            /*DEBUG("i = "<<i<<", j = "<<j);
            DEBUG("srcRect.x = "<<srcRect.x<<", srcRect.y = "<<srcRect.y<<", srcRect.w = "<<srcRect.w<<", srcRect.h = "<<srcRect.h);
            DEBUG("dstRect.x = "<<dstRect.x<<", dstRect.y = "<<dstRect.y);*/
        }
    }
}

Tile.h

#ifndef TILE_H
#define TILE_H

#include "TileType.h"

class Tile {
private:
    TileType const * type;
public:

    static const Tile ERROR_TYLE;

    Tile(TileType const * t);
    ~Tile();

    TileType const * getType() const;
};

#endif

Tile.cpp

#include "Tile.h"

const Tile Tile::ERROR_TYLE(TileType::ERROR);

Tile::Tile(TileType const * t) : type(t) {}

Tile::~Tile() {}

TileType const * Tile::getType() const {
    return type;
}

TileType.h

#ifndef TILETYPE_H
#define TILETYPE_H

#include "SDL.h"
#include "DEBUG.h"

class TileType {
protected:
    TileType();
    ~TileType();

public:
    static const int PIXEL_PER_TILE = 30;

    static const TileType * ERROR;
    static const TileType * AIR;
    static const TileType * SOLID;

    virtual SDL_Surface * getSurface() const = 0;

    virtual bool isSolid(int x, int y) const = 0;
};

#endif

ErrorTyle.h

#ifndef ERRORTILE_H
#define ERRORTILE_H

#include "TileType.h"

class ErrorTile : public TileType {

    friend class TileType;
private:
    ErrorTile();

    mutable SDL_Surface * surface;

    static const char * FILE_PATH;
public:
    SDL_Surface * getSurface() const;
    bool isSolid(int x, int y) const ;
};

#endif

ErrorTyle.cpp

(The surface can't be loaded when building the object, because it is a static object and SDL_Init() needs to be called first)

#include "ErrorTile.h"

const char * ErrorTile::FILE_PATH = ("C:\\error.bmp");

ErrorTile::ErrorTile() : TileType(), surface(NULL) {}

SDL_Surface * ErrorTile::getSurface() const {
    if (surface == NULL) {

        if (SDL::isOn()) {
            surface = SDL::loadAndOptimice(ErrorTile::FILE_PATH);
            if (surface->w != TileType::PIXEL_PER_TILE || surface->h != TileType::PIXEL_PER_TILE) {
                WARNING("Bad tile surface size");
            }
        } else {
            ERROR("Trying to load a surface, but SDL is not on");
        }
    }
    if (surface == NULL) { // This if doesn't get called, so surface != NULL
        ERROR("WTF? Can't load surface :\\"); 
    }

    return surface;
}

bool ErrorTile::isSolid(int x, int y) const {
    return true;
}

© Game Development or respective owner

Related posts about c++

Related posts about sdl