OpenGL 与 Go 教程(二)绘制游戏面板
这篇教程的所有源代码都可以在 GitHub 上找到。
欢迎回到《OpenGL 与 Go 教程》。如果你还没有看过第一节,那就要回过头去看看那一节。
你现在应该能够创造一个漂亮的白色三角形,但我们不会把三角形当成我们游戏的基本单元,是时候把三角形变成正方形了,然后我们会做出一个完整的方格。
让我们现在开始做吧!
利用三角形绘制方形
在我们绘制方形之前,先把三角形变成直角三角形。打开 main.go
文件,把 triangle
的定义改成像这个样子:
1 |
|
我们做的事情是,把最上面的顶点 X 坐标移动到左边(也就是变为 -0.5
),这就变成了像这样的三角形:
很简单,对吧?现在让我们用两个这样的三角形顶点做成正方形。把 triangle
重命名为 square
,然后添加第二个倒置的三角形的顶点数据,把直角三角形变成这样的:
1 |
|
注意:你也要把在 main
和 draw
里面命名的 triangle
改为 square
。
我们通过添加三个顶点,把顶点数增加了一倍,这三个顶点就是右上角的三角形,用来拼成方形。运行它看看效果:
很好,现在我们能够绘制正方形了!OpenGL 一点都不难,对吧?
在窗口中绘制方形格子
现在我们能画一个方形,怎么画 100 个吗?我们来创建一个 cell
结构体,用来表示格子的每一个单元,因此我们能够很灵活的选择绘制的数量:
1 |
|
cell
结构体包含一个 drawable
属性,这是一个顶点数组对象,就像我们在之前创建的一样,这个结构体还包含 X 和 Y 坐标,用来表示这个格子的位置。
我们还需要两个常量,用来设定格子的大小和形状:
1 |
|
现在我们添加一个创建格子的函数:
1 |
|
这里我们创建多维的 切片 ,代表我们的游戏面板,用名为 newCell
的新函数创建的 cell
来填充矩阵的每个元素,我们待会就来实现 newCell
这个函数。
在接着往下阅读前,我们先花一点时间来看看 makeCells
函数做了些什么。我们创造了一个切片,这个切片的长度和格子的行数相等,每一个切片里面都有一个 细胞 的切片,这些细胞的数量与列数相等。如果我们把 rows
和 columns
都设定成 2,那么就会创建如下的矩阵:
1 |
|
还可以创建一个更大的矩阵,包含 10x10
个细胞:
1 |
|
现在应该理解了我们创造的矩阵的形状和表示方法。让我们看看 newCell
函数到底是怎么填充矩阵的:
1 |
|
这个函数里有很多内容,我们把它分成几个部分。我们做的第一件事是复制了 square
的定义。这让我们能够修改该定义,定制当前的细胞位置,而不会影响其它使用 square
切片定义的细胞。然后我们基于当前索引迭代 points
副本。我们用求余数的方法来判断我们是在操作 X 坐标(i % 3 == 0
),还是在操作 Y 坐标(i % 3 == 1
)(跳过 Z 坐标是因为我们仅在二维层面上进行操作),跟着确定细胞的大小(也就是占据整个游戏面板的比例),当然它的位置是基于细胞在 相对游戏面板的
X 和 Y 坐标。
接着,我们改变那些包含在 square
切片中定义的 0.5
,0
, -0.5
这样的点。如果点小于 0,我们就把它设置成原来的 2 倍(因为 OpenGL 坐标的范围在 -1
到 1
之间,范围大小是 2),减 1 是为了归一化 OpenGL 坐标。如果点大于等于 0,我们的做法还是一样的,不过要加上我们计算出的尺寸。
这样做是为了设置每个细胞的大小,这样它就能只填充它在面板中的部分。因为我们有 10 行 10 列,每一个格子能分到游戏面板的 10% 宽度和高度。
最后,确定了所有点的位置和大小,我们用提供的 X 和 Y 坐标创建一个 cell
,并设置 drawable
字段与我们刚刚操作 points
得到的顶点数组对象(vao)一致。
好了,现在我们在 main
函数里可以移去对 makeVao
的调用了,用 makeCells
代替。我们还修改了 draw
,让它绘制一系列的细胞而不是一个 vao
。
1 |
|
现在我们要让每个细胞知道怎么绘制出自己。在 cell
里面添加一个 draw
函数:
1 |
|
这看上去很熟悉,它很像我们之前在 vao
里写的 draw
,唯一的区别是我们的 BindVertexArray
函数用的是 c.drawable
,这是我们在 newCell
中创造的细胞的 vao
。
回到 main 中的 draw
函数上,我们可以循环每个细胞,让它们自己绘制自己:
1 |
|
如你所见,我们循环每一个细胞,调用它的 draw
函数。如果运行这段代码,你能看到像下面这样的东西:
这是你想看到的吗?我们做的是在格子里为每一行每一列创建了一个方块,然后给它上色,这就填满了整个面板!
注释掉 for 循环,我们就可以看到一个明显独立的细胞,像这样:
1 |
|
这只绘制坐标在 (X=2, Y=3)
的格子。你可以看到,每一个独立的细胞占据着面板的一小块部分,并且负责绘制自己那部分空间。我们也能看到游戏面板有自己的原点,也就是坐标为 (X=0, Y=0)
的点,在窗口的左下方。这仅仅是我们的 newCell
函数计算位置的方式,也可以用右上角,右下角,左上角,中央,或者其它任何位置当作原点。
接着往下做,移除 cells[2][3].draw()
这一行,取消 for 循环的那部分注释,变成之前那样全部绘制的样子。
总结
好了,我们现在能用两个三角形画出一个正方形了,我们还有一个游戏的面板了!我们该为此自豪,目前为止我们已经接触到了很多零碎的内容,老实说,最难的部分还在前面等着我们!
在接下来的第三节,我们会实现游戏核心逻辑,看到很酷的东西!
回顾
这是这一部分教程中 main.go
文件的内容:
1 |
|
让我知道这篇文章对你有没有帮助,在 Twitter @kylewbanks 或者下方的连接,关注我以便获取最新的文章!
via: https://kylewbanks.com/blog/tutorial-opengl-with-golang-part-2-drawing-the-game-board
作者:kylewbanks 译者:GitFtuture 校对:wxy