网格方块绘制位置不符:原因分析及修复方法咨询
绘制网格方块位置异常的原因与修复方案
问题描述
绘制网格方块时出现位置异常,方块位置与地图数组定义不符。屏幕原点为左下角,相关实现细节如下:
1. 地图数组定义
// Here, 1 means a wall and 0 means an empty square const int mapX = 8, mapY = 8, mapSize=mapX*mapY; int map[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, };
2. 顶点与索引数组填充逻辑
typedef struct { Vertex vertices[4]; } Tile; for(int y = 0; y < mapY; y++) { for(int x = 0; x < mapX; x++) { int x0 = x * mapSize; int y0 = y * mapSize; Tile tile = { (Vertex){{x0+1, y0+1, 0.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}, (Vertex){{x0+1, y0 + mapSize-1, 0.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}, (Vertex){{x0 + mapSize-1, y0 + mapSize-1, 0.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}, (Vertex){{x0 + mapSize-1, y0+1, 0.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}, }; mapVertices[y*mapX + x] = tile; } } for(size_t i = 0; i < mapSize*6; i += 6) { static int offset = 0; mapIndices[i + 0] = 0 + offset; mapIndices[i + 1] = 1 + offset; mapIndices[i + 2] = 2 + offset; mapIndices[i + 3] = 2 + offset; mapIndices[i + 4] = 3 + offset; mapIndices[i + 5] = 0 + offset; offset += 4; }
3. 主循环绘制逻辑
// Changing color for wall for(int y = 0; y < mapY; y++) { for(int x = 0; x < mapX; x++) { if(map[y*mapX + x] == 1) { memcpy(mapVertices[y*mapX + x].vertices[0].color, (vec4){1.0f, 1.0f, 1.0f, 1.0f}, sizeof(vec4)); memcpy(mapVertices[y*mapX + x].vertices[1].color, (vec4){1.0f, 1.0f, 1.0f, 1.0f}, sizeof(vec4)); memcpy(mapVertices[y*mapX + x].vertices[2].color, (vec4){1.0f, 1.0f, 1.0f, 1.0f}, sizeof(vec4)); memcpy(mapVertices[y*mapX + x].vertices[3].color, (vec4){1.0f, 1.0f, 1.0f, 1.0f}, sizeof(vec4)); } } } mat4 mapTransform; glm_mat4_identity(mapTransform); glm_translate(mapTransform, (vec3){0.0f, 0.0f, 0.0f}); mat4 mvp; glm_mat4_mulN((mat4* []){&projectionMatrix, &viewMatrix, &mapTransform}, 3, mvp); glUniformMatrix4fv(glGetUniformLocation(mapShaderProgram, "mvp"), 1, GL_FALSE, (float*)mvp); bindVAO(&mapVertexAttributes); bindVBO(&mapVertexAttributes); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(mapVertices), mapVertices); glDrawElements(GL_TRIANGLES, sizeof(mapIndices)/sizeof(mapIndices[0]), GL_UNSIGNED_INT, 0);
问题原因
瓦片尺寸计算完全错误:
代码中误用mapSize(总瓦片数,值为64)作为单个瓦片的边长,导致每个瓦片的尺寸被设置为64个单位,瓦片之间严重重叠甚至超出屏幕范围,完全偏离预期位置。Y轴坐标与地图行顺序不匹配:
屏幕原点在左下角,但地图数组的第一行对应场景顶部。代码直接用循环变量y计算屏幕Y坐标,导致地图顶部的墙体被绘制到屏幕底部,整体场景上下颠倒。
修复方案
1. 修正瓦片尺寸计算
- 单独定义单个瓦片的尺寸(比如
tileSize = 1.0f,可根据需求调整),替换错误的mapSize用于坐标计算。 - 移除顶点坐标中多余的
+1偏移,直接基于瓦片尺寸计算顶点位置。
2. 修正Y轴坐标映射
- 将地图数组的行顺序反向映射到屏幕Y轴,用
(mapY - 1 - y)计算屏幕Y坐标,确保地图顶部的元素绘制到屏幕顶部。
修复后的顶点填充代码
typedef struct { Vertex vertices[4]; } Tile; // 定义单个瓦片的尺寸,可根据需求调整 const float tileSize = 1.0f; for(int y = 0; y < mapY; y++) { for(int x = 0; x < mapX; x++) { // 修正X/Y坐标计算:使用tileSize作为瓦片边长,反向映射Y轴 float screenX = x * tileSize; float screenY = (mapY - 1 - y) * tileSize; Tile tile = { // 左下角顶点 (Vertex){{screenX, screenY, 0.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}, // 左上角顶点 (Vertex){{screenX, screenY + tileSize, 0.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}, // 右上角顶点 (Vertex){{screenX + tileSize, screenY + tileSize, 0.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}, // 右下角顶点 (Vertex){{screenX + tileSize, screenY, 0.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}, }; mapVertices[y*mapX + x] = tile; } } // 索引数组逻辑无需修改,保持原代码即可 for(size_t i = 0; i < mapSize*6; i += 6) { static int offset = 0; mapIndices[i + 0] = 0 + offset; mapIndices[i + 1] = 1 + offset; mapIndices[i + 2] = 2 + offset; mapIndices[i + 3] = 2 + offset; mapIndices[i + 4] = 3 + offset; mapIndices[i + 5] = 0 + offset; offset += 4; }
3. 主循环颜色设置逻辑无需修改
因为顶点数组的索引y*mapX + x与地图数组的索引保持一致,所以原有的颜色设置代码可以直接使用,无需调整。
内容的提问来源于stack exchange,提问作者Techie-Guy
相关产品推荐
相关产品推荐

