maps, tilesets, and blitting (SDL)
my prog segfaults on the line that i try to blit on. everything is loaded correctly... but its just being stupid or whatever. rect.x and rect.y are correct, so forget about that (i kno that they are going to be either 0 or negative numbers but thats what i wnat). please help!
Code:
struct rpgOnMap{
int ref;
int x, y;
};
class rpgTileset{
public:
vector<SDL_Surface*> set;
void init( const char* filename ){
int i;
string image_file;
SDL_Surface* tmpsurface;
ifstream file( filename );
if( file.bad() ){ cerr << "Could not find tileset file!"; exit(1); }
for( i = 0; i != 256; i++ ){
getline( file, image_file );
tmpsurface = IMG_Load( image_file.c_str() );
if( tmpsurface == NULL ){ cerr << image_file << " not loaded correctly.\n"; exit(1); }
set.push_back( tmpsurface );
SDL_FreeSurface( tmpsurface );
if( file.eof() ) break;
}
}
rpgTileset( const char* filename ){
init( filename );
}
rpgTileset(){}
}; vector<rpgTileset> tileset;
class rpgMap{
public:
int x, y;
int w, h;
vector< vector<bool> > wall;
int tileset_ref;
vector< vector<int> > data[3];
char frame;
vector<rpgOnMap> object[7];
void init( const char* filename );
rpgMap( const char* filename ){ init( filename ); }
rpgMap(){}
void Blit( int xparam, int yparam );
void Move( char direction );
void Animate();
}; vector<rpgMap> map;
void rpgMap::init( const char* filename ){
ifstream file( filename );
if( file.bad() ){ cerr << "Could not find map file!"; exit(1); }
char erase;
int i, j = 0, tmpint, temp;
bool tmpbool;
rpgOnMap tmpobj;
vector<rpgOnMap> tmpobjvec;
vector<int> tmpvec;
vector<bool> tmpboolvec;
frame = 0;
file >> x;
file.get( erase );
file >> y;
file >> w;
file.get( erase );
file >> h;
file >> tileset_ref;
if( tileset.size() < tileset_ref ){ cerr << "Tilesets loaded incorrectly!\n"; exit(1); }
for( i = 0; i != h; i++ ){
for( j = 0; j != w; j++ ){
file >> tmpbool;
tmpboolvec.push_back( tmpbool );
}
wall.push_back( tmpboolvec );
tmpboolvec.clear();
}
file.get( erase );
for( temp = 0; temp != sizeof(data)/sizeof(data[0]); temp++ ){
for( i = 0; i != h; i++ ){
for( j = 0; j != w; j++ ){
file >> tmpint;
tmpvec.push_back( tmpint );
}
data[i].push_back( tmpvec );
tmpvec.clear();
}
file.get( erase );
}
for( i = 0; i != sizeof(object)/sizeof(object[0]); i++ ){
erase = '\0';
while( erase != '\n' ){
file >> tmpobj.ref;
file >> tmpobj.x;
file >> tmpobj.y;
file.get( erase );
object[i].push_back( tmpobj );
if( file.eof() ) break;
}
}
file.close();
}
void rpgMap::Blit( int xparam, int yparam ){
SDL_FillRect( screen, NULL, 0 );
int i, j, temp = 0;
x = xparam;
y = yparam;
SDL_Rect rect;
rect.w = TILE_W;
rect.h = TILE_H;
for( i = 0; i != h; i++ ){
rect.y = -y + ( TILE_H * i );
for( j = 0; j != w; j++ ){
//check if the current tile is on the screen, and if so, blit
if( j * TILE_W > x - (TILE_W - 1) && j * TILE_W < SCREEN_W + (TILE_W - 1) && i > y - (TILE_H - 1) && i < SCREEN_H + (TILE_H - 1) ){
if( i == 0 ) rect.y = -y;
rect.x = -x + ( TILE_W * j );
if( tileset[tileset_ref].set.size() < data[frame][i][j] ){ cerr << "Tilesets loaded incorrectly!\n"; exit(1); }
if( SDL_BlitSurface( tileset[tileset_ref].set[data[frame][i][j]], NULL, screen, &rect ) < 0 )
cout << "BlitSurface error: " << SDL_GetError() << endl;
}
}
}
}
void rpgMap::Move( char direction ){
switch( direction ){
case UP: Blit( x, y - 1 ); break;
case DOWN: Blit( x, y + 1 ); break;
case LEFT: Blit( x - 1, y ); break;
case RIGHT: Blit( x + 1, y ); break;
case UPLEFT: Blit( x - 1, y - 1 ); break;
case UPRIGHT: Blit( x + 1, y - 1 ); break;
case DOWNLEFT: Blit( x - 1, y + 1 ); break;
case DOWNRIGHT: Blit( x + 1, y - 1 ); break;
}
}
void rpgMap::Animate(){
if( frame == 2 ) frame = 0;
else frame++;
Blit( x, y );
}