实验5 游戏中的人工智能(迷宫寻宝)

说明:

课程教材《计算机游戏程序设计》(基础篇)(第3版) 提供示例代码,而课程实验在示例代码的基础上提出更高的实验要求。除此之外,本人也会额外加入些个人创意,希望同学们在参考之余也能加入自己的想法。

实现效果:

(因为雾效粒子太逼真导致gif动图随便一录就几十M,而博客里只能上传5m以下的图……费劲功夫减时长 减帧数 减质量才弄出一张……)

实验报告:

一、实验目的与要求

1. 理解A*寻路算法原理。

2. 进一步熟悉地图编辑器的使用。

3. 实现游戏中的人工智能。

二、实验内容与方法

1.完成游戏编译(60分)

成功编译并运行教材P200“游戏AI实例-迷宫寻宝”。

 

2.完成修改内容一 (10分)

修改游戏代码,实现修改内容一,即修改窗口大小。

 

3.完成修改内容二 (10分)

修改游戏代码,实现修改内容二,即增加DANGEROUS区域。

 

4.完成修改内容三 (10分)

修改游戏代码,实现修改内容三,即增加按键监听。

 

5.完成修改内容四 (10分)

修改游戏代码,实现修改内容四,即增加地图层次。

三、实验步骤与过程

1.完成游戏编译(60分)

老套路编译运行游戏:

图 1

2.修改窗口大小 (10分)

AppDelegate.cpp文件中修改自设窗口大小为1024*768,游戏窗口尺寸刚好。

图 2

再次运行游戏,成功容纳所有游戏内容:

图 3

 

3.增加DANGEROUS区域 (10分)

用TiledMap编辑原地图,进行些许改动并加上“墓碑”(ID为290),如下图红框内所示:

图 4

 

为实现以下功能:

  • 当玩家宝藏设置在“墓碑”处,或途径“墓碑”,屏幕中央提示“Dangerous!”信息
  • 当玩家到达“墓碑”处时,“笑脸”角色会停在“墓碑”处,屏幕中央“Dangerous!”改换显示为“Die!”,此时点击屏幕没有反应。
  • 如果“宝箱”刚好在“墓碑”处,则当“笑脸”角色到达时,“宝箱”也会消失,但是不会显示“Found Treasure!”。

 

 

下面介绍两种实现原理:

  • 算路径时就判断检测该路径上是否有“墓碑”,有则提示“Dangerous!”; 设置“墓碑”为精灵,在update函数中不断检验“笑脸”精灵是否和“墓碑”精灵相碰,相碰则通过用stopActionByTag等方法停止角色运动,判断为角色死亡。
  • 算路径时就判断检测该路径上是否有“墓碑”,有则提示“Dangerous!”; 在为“笑脸”角色决定运动路径时就只加入遇到“墓碑”前的路径即可(白色的预测路径的线段还是完整的),因此实际运动时的目标点为途经的“墓碑”,如果到达“墓碑”则角色死亡。

 

下面用第二种方法来实现这一部分功能:

moveOnPath函数:

 

图 5

 

Judge函数:

 

 

图 6

 

 

4.增加按键监听 (10分)

下面添加键盘按键监听事件,按Z键重启游戏。

代码为:

图 7

 

5.增加地图层次 (10分)

TiledMap绘制第二层地图。并且为地下第一层添加向下的楼梯,地下第二层地图添加向上和向下的楼梯。“向下楼梯”id为3,“向上楼梯”id为26 。

与判断“死亡”方法类似,角色只运动到“楼梯”为止则停下,然后判断是“向下楼梯”还是“向上楼梯”。

如果是“向下楼梯”,并且当前位置为(x,y),则把表示“下一张地图角色的起始位置坐标”的全局变量beginX和beginY设置为(x-1,y)。如果当前位置在第一层,则把表示“读取的地图路径名”mapName设为“Chapter11/superMaze2.tmx”。最后再通过restart函数重载第二层地图即可。

如果是“向上楼梯”,并且当前位置为(x,y),则把表示“下一张地图角色的起始位置坐标”的全局变量beginX和beginY设置为(x+1,y)。如果当前位置在第二层,则把表示“读取的地图路径名”mapName设为“Chapter11/superMaze.tmx”。最后再通过restart函数重载第一层地图即可(“向上楼梯”仅在第二层有)。

 

相关代码请参考上文第3部分“增加DANGEROUS区域”的代码处的moveOnPath函数。

 

第2层执行效果图如下,见个人学号后3位“190”:

图 8

 

 

以下为个人增加部分,实现“是男人就下100层”游戏:

6 . 自动生成地图

下面在原实验基础上实现一个“是男人就下100层”的游戏,但实际上不可能去用TiledMap绘制100层地图。所以除了第一二层地图外,第三层以下的地图采用“自动生成随机地图”系统来实现。

 

下面介绍“自动生成随机地图”原理:

(由于网上已经有很成熟的该算法基础原理,下面引用网上的原理图来进行讲解。引用图网址为:https://zhuanlan.zhihu.com/p/27381213)

① 先生成基础大地图。下图中灰色格子“0”代表墙,黄色格子“1”代表通路。可见墙的格子一般要比路的格子多。

图 9

 

② 选择一个黄色格子“1”为起点,并且把该点涂红,红色表示已被检测并可联通的通路(见下图标为“起”的红色格子);然后在它的周围随机找另一个黄色的1(这里的“周围”指的是上下左右4个方向,斜边不算),找到后则把该格子、以及两格子间的灰色格子“0”一起“打通”涂为红色,此时它们就算是被确认的红色“通路”。

图 10

 

③ 一直重复②的过程,直到类似下图这种“找不到下一个黄色1的格子”的情况:

图 11

 

④ 这时候,原路往回走(即不停去找前一个格子),直到找到一个格子,这个格子周围有黄色的1,那么从这个格子开始重复②的步骤。

图 12

 

⑤ 重复以上的过程,直到最终填充完整个地图,并记录最后一个到达的终点即可。

图 13

 

代码实现要点:

  • 第三层后,取消掉“向上的楼梯”,只保留“向下的楼梯”。而角色的起始点位置为上一层楼梯的位置。因此,编写上述原理第①步的代码生成基础大地图时,要调整代码使角色的起始位置在“路”上,而不是在“墙”上。否则后续代码还要判断许多种情况,带来麻烦。
  • 路径关系通过节点间的parent属性决定,确定谁是谁的parent,而parent属性为nullptr的则表示当前格还没被检验。
  • 随机生成地图路径过程中不断记录当前被拓展的最新格子。直到地图生成完毕后,记录的该格子将被设置为“终点”格子。
  • “墙”“楼梯”“墓碑”都是由图片精灵组成的。
  • “墓碑”随机生成0~3个。为保证“起点”到“终点”的路径一定是安全无阻的,“墓碑”一定不能被设置在这主路径上。实现方法可以为随机生成“墓碑”坐标后,判断该“墓碑”坐标是否在这条安全的路径上。(“终点”通过parent属性回溯到“起点”)。

 

代码为:

对应上文“随机生成地图”原理的第①步的initRandMap方法:

图 14

    对应上文“随机生成地图”原理的②~④步的createRandMap方法:

图 15

 

绘制随机地图的函数drawRandMap:

图 16

 

随机生成的地图:

图 17

图 18

 

 

7 . 其他新增项

由于想要限制报告篇幅,这里举出新增的、或者与原代码不同的地方,并且不一一进行详细的说明:

  • 修改了源代码中“点击角色屏幕会出现‘NO WAY’的BUG”(只需判断点击的是否为角色,如果是的话不执行寻路算法即可,不细述)

 

  • 修改了源代码“笑脸”和“宝箱”间的碰撞方式 以及 图片尺寸。  因为update函数中的碰撞方式为“俩精灵”sprite碰撞,按原代码逻辑,精灵碰撞后则视为“笑脸找到宝箱,运动结束”并执行后续代码,但是,假设精灵间只是刚好接触到边,也算是产生了碰撞,而此时“笑脸”精灵并没有完全停止运动。代码逻辑矛盾,容易引发错误。因此碰撞检测方案更改为“精灵坐标中心相等”。    又由于“笑脸”和“宝箱”和普通格子的边长都是32*32比例,因此,在原有的碰撞检测方法中,“笑脸”只要在“宝箱”旁边的一个格子时,就算是发生碰撞了(边相触了),因此,图片可适当改为30*30大小。

图 19

 

  • 为增加趣味性,修改原“笑脸”图片,并且角色在“NO WAY”状态时,“笑脸”变为“喷口水脸”。角色在“DIE”状态时,“笑脸”变为“吓哭脸”。

“滑稽笑脸”:

“喷水脸”:

“哭脸”:

 

  • 增加背景音乐,并且可通过右下角的“开关按钮”来控制背景音乐的有无。

    代码:

图 20

图 21

 

    见右下角开关:

图 22

  • 增加音效。 添加在上下楼梯,与死亡时的音效。

图 23

 

  • 增加粒子系统。 particle2dx在线编辑粒子效果,实现“雾气”粒子特效,为游戏增加阴深神秘感。

    初始化函数init中:

图 24

 

演示效果:

图 25

  • 为场景切换添加2种随机特效(如上下楼、重启游戏)。

图 26

 

  • 每层开始时都提示当前层数,突破100层时会有成功提示。(层数提示数秒会自动消失)

图 27

图 28

猜你喜欢

转载自blog.csdn.net/purers/article/details/82386310