Reputation: 762
I have been working on a tiling system for a video game I've been designing through C++ and SDL. The code is loosely based off of the tutorials available on lazyfoo.net, but with a different system to draw the tiles to the screen. The code works as follows: I have a class called Map
that creates an array of another class called Tile
. It also has a function called set_tiles
that reads numbers from a .map file and copies them to the array of tile
's using two for loops; one for the x's and one for the y's. I then blit each surface to a temporary map according to the Tile
's specific variables. Here is the actual code:
SDL_Surface* Map::set_tiles ( SDL_Surface* tile_image ) {
Setup setup;
SDL_Surface* temp_map = NULL;
//Open the map
std::ifstream map ( "Test.map" );
//Catch any errors
if ( map.fail() ) return NULL;
//Initialize the tiles
for ( int y = 0; y < MAP_HEIGHT / TILE_HEIGHT; y++ ) {
for ( int x = 0; x < MAP_WIDTH / TILE_WIDTH; x++ ) {
//Determines the tile type
int tile_type = -1;
//Read the tile type from the map
map >> tile_type;
//Make sure it's a real tile
if ( tile_type < 0 || tile_type >= TILE_SPRITES ) {
map.close();
return NULL;
}
//Error check for the .map file
if ( map.fail() ) {
map.close();
return NULL;
}
//Add the tile to the array
tile_array[x][y] = &Tile ( x, y, tile_type );
//Create the temp. image crop
SDL_Rect* temp_crop = &tile_array[x][y]->get_crop();
//Check for crop errors
if ( ( temp_crop->h || temp_crop->w ) == 0 ) return NULL;
//Edit the temp. map
setup.apply_surface ( x * TILE_WIDTH, y * TILE_HEIGHT, tile_image, temp_map, temp_crop );
}
}
map.close();
//Return the modified map
return temp_map;
}
Tile::Tile ( int x, int y, int tile_type ) {
//Get the offsets
box.x = x;
box.y = y;
//Set the collision box
box.w = TILE_WIDTH;
box.h = TILE_HEIGHT;
//Get the tile type
type = tile_type;
//Choose the crop option
crop.w = TILE_WIDTH;
crop.h = TILE_HEIGHT;
switch ( tile_type ) {
case TILE_RED:
crop.x = 0 * TILE_WIDTH;
crop.y = 0 * TILE_HEIGHT;
break;
case TILE_GREEN:
crop.x = 1 * TILE_WIDTH;
crop.y = 0 * TILE_HEIGHT;
break;
case TILE_BLUE:
crop.x = 2 * TILE_WIDTH;
crop.y = 0 * TILE_HEIGHT;
break;
case TILE_CENTER:
crop.x = 3 * TILE_WIDTH;
crop.y = 0 * TILE_HEIGHT;
break;
case TILE_TOP:
crop.x = 0 * TILE_WIDTH;
crop.y = 1 * TILE_HEIGHT;
break;
case TILE_TOPRIGHT:
crop.x = 1 * TILE_WIDTH;
crop.y = 1 * TILE_HEIGHT;
break;
case TILE_RIGHT:
crop.x = 2 * TILE_WIDTH;
crop.y = 1 * TILE_HEIGHT;
break;
case TILE_BOTTOMRIGHT:
crop.x = 3 * TILE_WIDTH;
crop.y = 1 * TILE_HEIGHT;
break;
case TILE_BOTTOM:
crop.x = 0 * TILE_WIDTH;
crop.y = 2 * TILE_HEIGHT;
break;
case TILE_BOTTOMLEFT:
crop.x = 1 * TILE_WIDTH;
crop.y = 2 * TILE_HEIGHT;
break;
case TILE_LEFT:
crop.x = 2 * TILE_WIDTH;
crop.y = 2 * TILE_HEIGHT;
break;
case TILE_TOPLEFT:
crop.x = 3 * TILE_WIDTH;
crop.y = 2 * TILE_HEIGHT;
break;
}
}
The problem is that set_tiles
returns a NULL pointer when it is called. Through a bit of debugging I found that it makes it all the way to the end and then returns a NULL, it doesn't do it somewhere in the for loops. I've also tried setting all tile
crop.x's and y's to 0, just to see if it would work, but it doesn't.
NOTICE
The problem is not my image or the .map file.
I think that my understanding of pointers may be a bit faulty, and that I may have made a mistake when calling apply_surface
.
void Setup::apply_surface ( int x, int y, SDL_Surface* source, SDL_Surface* &destination, SDL_Rect* clip ) {
//Temporary rectangle to hold the offsets
SDL_Rect offset;
//Get the offsets
offset.x = x;
offset.y = y;
//Blit the surface
SDL_BlitSurface ( source, clip, destination, &offset );
}
Upvotes: 0
Views: 2578
Reputation: 103733
SDL_BlitSurface
blits one surface to another. They both must be initialized, otherwise the function does nothing. You are passing a NULL pointer to it. You need to initialize the pointer with a call to something like SDL_CreateRGBSurface.
Upvotes: 1