【问题标题】:C++ Efficiently store Tile Map tilesC++ 高效存储瓦片地图瓦片
【发布时间】:2014-10-16 06:41:43
【问题描述】:

我正在制作一个基于 TileMap 的游戏引擎。

我有一个“Tile”类,它用于定义块类型和设置标志以确定属性(isSolid、isEmitter)。现在我有一个 2d 平铺对象数组 [MAP_WIDTH][MAP_HEIGHT]。

现在我知道为游戏中的每个实际图块存储一个新图块是不必要的,但我需要找到一种方法以更简单的格式存储地图数据。我最初的想法是存储一个无符号整数的二维数组(或向量),但我无法使它成为一个可扩展的解决方案。

如何用数字表示每个 Tile?所以在渲染函数中我可以说“从存储在数组中的整数值渲染图块的类型”。 renderTileType(map[x][y])

对不起,这是我的第一个问题,请原谅我的任何罪过。

提前致谢!

【问题讨论】:

  • 你有多少块瓷砖?数组不起作用需要很多。您可以使用unsigned char 的数组而不是int,具体取决于您必须处理多少“图块类型”。
  • 它确实有效,但我已经可以看到很多开销。我有一个数组,但是在加载地图时,我实际上为每个地图创建了一个“新”平铺对象,但我正在寻找一种方法来为每个平铺添加某种标识符,以告诉引擎什么“类型”瓦岛因为我不需要瓷砖是唯一的,只是类型。那有意义吗?我可能解释得不好,抱歉
  • 您可以使用每个二维数组元素的值作为唯一Tile 对象数组(向量)的索引吗?
  • 哇,我不知道为什么我想不出这么简单的东西……谢谢!我接受了根据您的评论得出的答案,部分归功于您。
  • 请注意,提供的答案意味着您仍然会为每个图块消耗一个内存指针(通常为 4 或 8 个字节);而如果您拥有少于 256 种类型的图块,您仍然可以使用 unsigned char 数组作为单独数组的索引。不过,不管怎样。这完全取决于您实际拥有多少瓷砖。

标签: c++ sfml


【解决方案1】:

只需将所有独特的 Tiles 存储在一个向量中,除了在程序启动期间不需要更改。然后像这样制作一个二维数组:

Tile* map[MAP_WIDTH][MAP_HEIGHT]

然后,您可以简单地将这个 2D 数组中的指针分配到 vector<Tile> 中的相应 Tile。 Tiles 的生命周期当然会由向量管理,所以你不需要 newdelete 任何东西。

【讨论】:

  • 我最初接受了另一个答案,但这会占用更少的资源,而且很简单。谢谢!
【解决方案2】:

您可以使用享元模式的实现。

所以你有一个二维的瓦片数组。

Tile map[MAP_WIDTH][MAP_HEIGHT];

但磁贴包含有关本地信息的信息和指向共享信息的指针。

class Tile {
   // Stuff that is really shared between all tiles of the same type.
   TileImpl * impl;

   // Other stuff that varies with location in the map.
   // maybe you want to store items there, or flags, or procedures.
   ItemInfo * items;
   Flags    * flags;
   Procedures* procs;
}

// This is the stuff that all tiles of this type share.
class TileImpl {
  string imageFile;
  bool hurtsMeIfIStandOnIt;
  bool isPassable;
}

【讨论】:

    【解决方案3】:

    当我在游戏服务器设置中执行此操作时,我使用了一个 2D 指针数组,并且大多数指针都引用共享 Tiles(在我的情况下是 Room* ),并且我的 Room 有一个用于共享 vs 的位标志独特。我可以进行惰性实例化,如果玩家在沙漠中徘徊,我会在他访问每个房间时按需实例化共享沙漠房间的唯一副本。 Room 具有诸如玩家/对象列表之类的数据结构,因此任何具有内容的房间也可能被预先实例化。但是 99% 的地图指向共享房间,这使得堆使用效率更高。

    Tile/Room 也有一个低基数枚举类型,或者是一个简单的短字节或短整数,它是另一个 Tile 类型数组的从零开始的索引,其中包含颜色、位图、规则等详细信息。

    如果数组大小成为问题,只需将数组分解为象限系统,并根据需要进行按需加载/卸载。

    【讨论】:

      【解决方案4】:

      您需要一个特定的数据结构,将整数 ID 映射到实际的 Tile 对象。 如果您可以访问 C++11(更好的查找复杂性),则有一个名为 std::map 的类,或者 std::unordered_map

      只需声明您的整数数组(一维或二维,随便),在加载时填充它,当您需要使用实际的Tile(碰撞检测、绘图等)执行操作时,只需获取它从地图上看。

      例子:

      std::unordered_map<std::uint16_t, Tile *> tileMap;
      tileMap[0] = /* get tile object for ID 0 */;
      tileMap[1] = /* get tile object for ID 1 */;
      …
      
      Tile *currentTile = tileMap[idMap[x][y]]; // Here you get the tile from the ID at (x, y)
      

      另一种解决方案是使用InternalTile 类,该类拥有所有昂贵的资源(纹理……),并将指向适当实例的指针或引用传递给正在构造的每个Tile 对象。但它不太有用,因为您不使用每个 Tile 的唯一属性。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-12-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-12-16
        • 2015-03-03
        • 2014-09-18
        相关资源
        最近更新 更多