这么大的字都看不见我就没办法了。
全部代码及完整版实验报告下载地址:
https://download.csdn.net/download/qq_33614902/10517208
一、实现的功能
1、 两个坦克。
2、 沙漠地形,地形中加了灌木丛。
3、 坦克可以运动,可以用键盘控制炮筒旋转。
4、 能够用键盘控制坦克上下左右运动,坦克之间可以碰撞,检测到碰撞后两坦克会停止运动。
5、 按v键能触发视点切换(orbit)。也可直接用鼠标控制,不过要修改源码,见注意事项的第三条。
6、 两个坦克分别有自己的烟雾粒子系统。
7、 坦克运动时会随地形上下浮动,且无法跑出地形。
二、键盘控制
a) 1号坦克:wsad键分别控制其上下左右运动,q键使其停止运动,e键和r键分别控制炮筒旋转和停止旋转。
b) 2号坦克:ikjl键分别控制其上下左右运动,u键使其停止运动,o键和p键分别控制炮筒旋转和停止旋转。
c) v键触发视点切换。
三、注意事项
1、 运行程序后,按小写的v键触发。
2、 如何关闭粒子系统?
如图修改main.cpp中559、560行,rate_x=0;rate_y=0;
3、 如何关闭视点切换功能?
如图,修改main.cpp中的766行,取消注释。
四、编程实现
完整代码参见源代码,每个功能都有对应的模块,代码结构很清晰,也给出了比较详细的注释。
按照从上到下的顺序,代码包括的部分有:头文件,定义结构体和类,定义全局变量,声明函数,定义函数,主函数。
4.1加载地形和坦克
Node可表示地形和坦克,readNodeFile函数用于加载坦克和地形模型,osg::MatrixTransform用于保存坦克的位置信息。
部分代码如下:
4.2地形中加入灌木丛
在确定灌木丛与地形接触的位置时,用到了线与地形的碰撞检测。
函数createShrub用于创建灌木丛,碰撞检测用于确定灌木丛在地形中的位置。
部分代码如下:
4.3坦克随地形起伏
已知坦克位置中的x,y坐标,用与z轴平行的线段与地形做碰撞检测,就可以确定坦克的z坐标了。
部分代码如下:
4.4键盘控制坦克炮筒旋转和停止
需要用到事件类型、键盘响应的相关知识,挺复杂的,不过老师已经给出了demo,我只是补充了一点:给另外一个坦克也加了这个功能。
部分代码如下:
4.5键盘控制坦克上下左右运动
键盘控制是通过仿照“键盘控制炮筒旋转”来实现的。
坦克的移动是通过不断修改坦克的位置来实现的。
为了使坦克在键盘触发对应动作后持续运动,用到了更新与回调相关知识。
首先:定义坦克的向前、向后、向左、向右、停止动作。如下图:
然后,完成键盘控制部分。如下图:
最后,完成回调与更新部分。如下图:
4.6坦克之间的碰撞检测
原理
1、 因为坦克是随地形起伏的,不需要考虑坦克的高度。那么每个坦克可以分别用一个矩形来表示。坦克间的碰撞检测就转化成了求解矩形是否有交集的问题。
2、 每个矩形可以用四条线段来表示,那么矩形间是否有交集的问题就可以转化成线段的相交问题。
3、 两个点可以确定一条线段。
4、 点由横坐标x和纵坐标y组成。
代码
定义点和线段。如下图:
线段之间的碰撞检测。如下图:
坦克之间的碰撞检测。如下图:
检测到碰撞后,坦克停止运动。如下图:
4.7视点切换(orbit)
这部分老师已经给出demo,我只是理解整合了一下。
部分代码如下:
4.8烟雾粒子系统
粒子系统中的类之间的关系如下图:
部分代码如下图:
五、运行效果图
上图可看出:地形中增加了灌木丛,两个坦克都有自己的烟雾粒子系统,并且还能随地形起伏。
上图中可看出:按v键能切换多视角,坦克无法跑出地形,其实炮筒一直在旋转(只是需要动态图才能展现出来)。
从上面两张图可看出:两个坦克间是有碰撞检测的,也能看到坦克随地形起伏。