C++中的3D游戏环境



我对C++很陌生,很难创建3D游戏板棋盘的大小可以在整个游戏过程中增加

我的第一个想法是使用嵌套向量。vector<vector<vector<int>>> board

我的想法是,它很容易访问(board[z][y][x](,而且我在动态分配方面不会有问题。然而,我听说嵌套向量不是一个好主意,因为它破坏了"缓存友好性"。相反,我应该使用1d向量和使用数学的"假"维度。

我认为这意味着创建大小为(x*y*z(的向量。在这种情况下,当我想"转到"nested_vector_board[0][1][0]时,我使用board[x]。如果我想转到nested_vector_board[1][1][0],我会使用board[x*y+x]。

我的理解正确吗?如果调整板的大小,我该怎么办?例如,如果我想让板更宽,似乎我需要手动转移所有数据。更重要的是,有更好、更简单的方法吗?

我欢迎任何建议,并提前非常感谢!

如果您不知道您的访问模式是什么,则无法选择最佳解决方案。此外,如果你没有有效的解决方案,你就无法衡量你的性能,只能猜测什么是最佳解决方案,而且你可能猜错了。

我建议用一个清晰的界面来实现你自己的3DBoard类,并检查你的琐碎解决方案是否足够好。如果速度太慢,可以将实现换成更适合的实现。

这里有一个例子,你可以如何实现你的板:

#include <iostream>
#include <unordered_map>
#include <map>
template <class ValueType>
class board_3d {
public:
using key_t = std::tuple<size_t, size_t, size_t>;
using value_t = ValueType;
ValueType& operator[](key_t key) {
return m_data[key];
} 
const ValueType& operator[](key_t key) const {
return m_data[key];
} 
private:
std::map<key_t, ValueType> m_data;
};
int main()
{
board_3d<int> my_board;
my_board[{0,0,0}] = 5;
return 0;
}

std::map最终可能不是您想要的。访问权限为O(logn(。为了优化,您可以使用带有O(1(访问的std::unordered_map或任何使用向量的实现。您还可以添加一个调整大小功能,负责将数据从旧存储器复制到新存储器。

我认为您可以使用稀疏表示:

std::map<int, std::map<int, std::map<int, int> > > board;

您可以使用方括号引用此地图中的值:

board[x][y][z] = 13;

然而,这种结构可能混乱且效率低下,因此您可以将x、y和z打包到一个复合密钥中,并在std::unordereded_map中使用它。

struct XYZ_Key {
int32_t  x;
int32_t  y;
int32_t  z;
bool operator==(const XYZ_Key& o) const {
return (x == o.x) && (y == o.y) && (z == o.z);
}
size_t hashCode() const {
return ((((11 + x) * 7) + y) * 5) + z) * 3;
}
};
std::unordered_map<XYZ_Key, int, decltype(std::mem_fn(&XYZ_Key::hashCode)) >  board;

为了避免嵌套向量,在堆栈上构建一个固定大小(设置为板上大小的上限(的2D指针网格,单个向量包含所有数据,怎么样?类似的东西(这里用智能指针实现(:

#include <iostream>
#include <vector>
#include <memory>
int main() {
const int MAXSIZE = 512
int width = 5;
int height = 5;
int depth = 5; 
std::unique_ptr<std::vector<int>> grid[MAXSIZE][MAXSIZE];
for (int i = 0; i < width; ++i) {
for (int j = 0; j < height; ++j) {
grid[i][j] = std::make_unique<std::vector<int>>();
for (int k = 0; k < depth; ++k) {
grid[i][j]->push_back(k);
}
}
}
//To iterate over all the contents:
for (int i = 0; i < width; ++i) {
for (int j = 0; j < height; ++j) {
for (int k = 0; k < depth; ++k) {
std::cout << grid[i][j]->at(k) << " ";
}
std::cout << " // ";
}
std::cout << std::endl;
}
return 0;
}

根据游戏的工作方式,您可能不得不使用std::shared_ptr。我的理解是,这种结构允许比嵌套向量方法更有效的内存访问;也许缺点是必须同时分配更大的网格?

最新更新