2013-02-17 79 views
0

我一直在为我一直在通过C++和SDL设计的视频游戏开发平铺系统。该代码松散地基于lazyfoo.net上提供的教程,但使用不同的系统将图块绘制到屏幕上。代码的工作原理如下:我有一个名为Map的类,它创建了另一个类Tile的数组。它还有一个叫set_tiles的函数,它读取.map文件中的数字,并使用两个for循环将它们复制到tile的数组中;一个用于x的,另一个用于y的。然后,根据Tile的特定变量,将每个表面都映射到临时映射。下面是实际的代码:平铺系统C++ SDL

Map.cpp

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.cpp

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; 
} 

}

的问题是,set_tiles返回NULL指针时它被称为。通过一些调试,我发现它一直到最后,然后返回一个NULL,但它不会在for循环中的某处执行。我也尝试将所有tile crop.x's和y's设置为0,只是为了确定它是否可行,但事实并非如此。

通知 问题不在于我的图像或.map文件。 我认为我对指针的理解可能有点错误,并且我在致电apply_surface时可能犯了一个错误。

Setup.cpp
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); 

}

+0

定义了什么'Setup'类?除非'apply_surface'函数将SDL_Surface指针作为第四个参数(即'SDL_Surface *&')引用,否则此函数中没有任何内容将temp_map从其初始化更改为NULL指针。 – 2013-02-17 05:12:27

+0

谷歌搜索“apply_surface”将我引向[this](http://lazyfoo.net/SDL_tutorials/lesson06/index.php),但在这种情况下,它不是一个类的成员。如果这是你从中获取代码的地方,并且只是将它封装在一个名为'Setup'的类中而不改变参数类型,那么是的,你在调用'apply_surface'时犯了一个错误。 – 2013-02-17 05:17:43

+0

好Google fu - 我删除了我的答案。我错误地假设了一些东西。 – 2013-02-17 05:23:15

回答

1

SDL_BlitSurface的blit一个表面到另一个表面。它们都必须被初始化,否则该函数什么都不做。你传递一个NULL指针给它。你需要通过调用SDL_CreateRGBSurface来初始化指针。

+0

这很有道理。我做了一些研究,并发现如何使用'SDL_CreateRGBSurface'。它不再返回NULL。但是,它仍然没有返回我想要的图像。某处还有其他问题。 – 2013-02-17 06:02:22

+0

@JimHurley:我不怀疑,但每个帖子都有一个问题。 – 2013-02-17 06:05:29

+1

是的,先生。我会自己处理一段时间。 – 2013-02-17 06:09:18