0

我了解指针和引用的基础知识,但我遇到的最大问题是决定何时使用它们(以及使用哪个)。我将给出的主要示例是基本游戏之一。假设设置类似于:

  • 新世界
    • 相机
    • 地图

World 是一个指针,因为每次游戏开始新的存档或加载现有的存档时,它都会删除世界并加载新的世界。但是在 World 内部,Camera 和 Map 应该只存在一个,并且只存在于 World 的持续时间内。如果世界被摧毁,那么显然他们也应该被摧毁。但是.. 假设 Map 需要访问相机(但其他对象也需要),Camera 应该通过引用传递给 Map 还是作为指针传递,还是?例如,如果它应该是通过引用,它应该是:

map = Map(&camera);
(inside map class) Map(Camera camera) {...}

或者更像:

map = Map(camera);
(inside map class) Map(Camera &camera) {...}

另外,假设 Map 包含一个称为网格的二维图块矢量。就像是:

std::vector< std::vector< Tile > > > grid;

现在假设我有一个 PathFinder 类,需要传入该网格。它需要直接编辑图块以更改 f、g 等值(用于寻路)。该 2D 向量是否应该只是 Tile 的普通 2D 向量,而整个事物通过引用传递给 PathFinder?还是应该是 Tile 指针的 2D 向量?

此外,NPC 和玩家将有一个 currentTile,即他们当前所在的图块。他们需要有一个指向该图块的引用或指针,以便他们还可以通过 NPC/Player 类中的类似内容将自己设置为该图块上的占用者:

currentTile = tile;
currentTile->SetOccupant(this);

当我破坏该网格以加载新地图时,另一个问题出现了,我如何轻松处理以确保没有任何东西指向不再存在的瓷砖。我是否只需要遍历这些类并将 currentTile 设置为 NULL?

这就是我开始对这些东西感到困惑的地方。任何帮助表示赞赏,因为我显然很nooby。@_@; 抱歉,如果这不是真正的游戏主题。如果它需要移动到不同的 stackexchange,请告诉我或移动它(如果可以的话)。>_<

4

1 回答 1

1

考虑 Map 类。您可以通过引用或作为指针传入相机。真的没关系。重要的是传入的相机会发生什么。您要将其分配给相机*的成员吗?否则,在构造函数中设置 Camera 不会有太大的作用。每次调用需要相机的 Map 时,您都必须提供相机指针/参考。

对于存储 Tile 对象,一维 std::vector<> 就可以了。通过使用一些简单的数学,可以很容易地遍历这个瓦片网格。在里面嵌套另一个向量只会导致不必要的开销。这是这样做的示例算法:

std::vector<Tile> tiles = makeTiles();
for (int y=0; y<mapHeight; y++)
{
   for (int x=0; x<mapWidth; x++)
   {
      Tile tile = tiles.at(x + y*mapWidth);
      tile.doSomethingWithTile();
   }
}

决定如何将切片数据从地图获取到路径查找器实际上是您希望保护地图数据的程度的问题。通过提供对所有磁贴数据的引用,您实际上是在使其公开访问。由于路径查找器需要编辑单个图块而不是整个图块数组本身,因此更好的方法是使用如下方法:

Tile* Map::AccessTile(int tx, int ty);

这样一来,瓦片数据的整个向量就不会暴露,但 PathFinder 将能够得到它需要的东西。此外,可以将 Map::AccessTile() 设为私有,并将 PathFinder 声明为 Map 的朋友。另一种方法是提供类似 Map::SetTileF(int tx, int ty, float f) 的方法。不过,这可能很乏味。

对于 NPC 和 Player,可以使用类似的解决方案。他们实际上不需要对他们所在的磁贴有直接的写访问权。添加类似 Map::SetTileOccupant(Entity *entity) 的方法和相应的 Map::GetTileOccupant()。

现在您担心删除对象。您应该看看 C++ 提供的一些模拟指针(特别是std::shared_ptr<>std::weak_ptr<>)。对这些的快速解释是 shared_ptr 是一个“拥有”对象的指针,而 weak_ptr 知道在哪里访问该对象,但实际上并不“拥有”该对象。

使用这些模拟指针,您可以执行以下操作:

//prototype for setWorld
//note that shared_ptr<> casts to weak_ptr<> nicely
Camera::setWorld(std::weak_ptr<World> world);

//setup the camera and world
std::shared_ptr<World> world(new World);
Camera camera;
camera.setWorld(world);

使用上面的代码,相机有一个指向世界的指针。如果世界由于某种原因被删除,相机可以通过以下方法解决这个问题:

bool Camera::worldIsValid()
{
   return (this->mWorld.expired() == false);
}

此外,您将相机封装在 World 中,这可能是您不需要做的事情。相反,Camera 可以是独立的,只要它需要有关 World 的信息或 World 中包含的 Map 的信息,就可以引用它。

于 2013-10-15T02:29:19.777 回答