GochenRyan的博客

往者不可谏,来者犹可追。

0%

【游戏客户端】读取并绘制图块地图

这篇文章是《C++游戏编程:创建3D游戏》第二章的练习题3的题解。看了看Gihub的提交记录,已经是4月13号的事了。作为一名有羞耻心的懒癌症患者,我会迟到,但我永远不会缺席……

思考

先看一下题目🤔:
20200511001300-image.png
感觉和项目中经常使用的导表很像,都是读取编辑器生成的特定格式的文档,然后编写解析程序读取并输出,不过导表是生成py文件,这里是绘制纹理(也就一个SDL_RenderCopyEx就能解决的事)。
所以思路应该是这样:分析csv文件格式>读取有效数据>根据映射关系绘制纹理

编程

对C++不是很熟悉,Google一下:C++如何读取CSV文件?
go on😀

分析csv文件格式

不要用excel打开,直接用记事本打开可以看到格式
20200511004253-image.png
行与行之间用回车分隔,每一行的数字索引都用”,”分隔。

读取有效数据

这里根据数据格式的特点,直接读取需要的数字索引。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
std::ifstream fin(tilemap.csvName);
std::string line;

std::vector<std::vector<int>> fields;
while (getline(fin, line))
{
std::istringstream sin(line);
std::vector<int> rowContent;
std::string field;
while (getline(sin, field, ','))
{
rowContent.push_back(std::stoi(field));
                }

fields.push_back(rowContent);
}

根据映射关系绘制纹理

这里需要关注的是大小位置,easy😋。

  • 大小:宽度除以列数、高度除以行数
  • 位置:因为需要的是左上角的坐标,遍历的时候直接列序号x宽度、行序号x高度
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
rows = fields.size();
cols = fields[0].size();
for (int i = 0; i < fields.size(); i++) {
for (int j = 0; j < fields[i].size(); j++) {
if (fields[i][j] == -1) continue;
tile.w = static_cast<int>(mTextureWidth / mTileCols);
tile.h = static_cast<int>(mTextureHeight / mTileRows);
tile.x = (fields[i][j] % mTileCols) * tile.w;
tile.y = (fields[i][j] / mTileCols) * tile.h;
r.w = static_cast<int>(mScreenSize.x / cols);
r.h = static_cast<int>(mScreenSize.y / rows);
// Center the rectangle around the position of the owner
r.x = r.w * j;
r.y = r.h * i;
// Draw this tile
SDL_RenderCopyEx(
renderer,
mTexture,
&tile,
&r,
-Math::ToDegrees(mOwner->GetRotation()),
nullptr,
SDL_FLIP_NONE
);
}
}

绘制出来就是这个样子:
20200511013654-image.png
很有年代感🤣,完整的代码可以在我的仓库找到。

最后

emmm,由于码完之后直接睡觉了,所以一些异常输入(csv文件每行个数不一致、索引不是数字等)没有考虑到,后续会优化的😑,欢迎给我提issue。