2019-07-25 UE4《吃豆人-下》

2019-07-30  本文已影响0人  静静静静静_4fba

《吃豆人》接上一篇。(其实是在等下载《火焰纹章-风花雪月》顺便来续写)

七、走向胜利

统计豆子的数量,每吃一个就自减,减到0胜利。

打开PacmanGameModeBase.h ,声明一个 int 类型的变量用来表示豆子数量,再声明一个函数,就叫 BeanWereEaten 吧...重写父类的BeginPlay。

在BeginPlay中通过迭代器获取豆子数量并统计,在 BeanWereEaten 中减少豆子数量,默认每次-1。减到0玩家胜利。

豆子数量管理

在Bean类中声明一个DestroyBean函数,记得要加UFUNCTION() 。

豆子销毁监听

然后在BeginPlay中绑定监听

绑定销毁监听

最后实现DestroyBean函数,获取GameMode,调用BeanWereEaten方法。

实现销毁监听

我们在豆子管理中加了log,当豆子被吃时就会打印当前的剩余数量。

打印当前剩余豆子数量

超级豆,吃了会削弱敌人。

新建SuperBean类,继承自Bean。本来想重写DestroyBean,在里面添加削弱敌人的逻辑,但是编译时被告知,不能重写UFUNCTION修饰的函数。最后只好新建一个DestroySuperBean,然后重写Bean的BeginPlay函数,在调用Super::BeginPlay之后,再新增一个OnDestroyed的事件绑定,绑定到新建的DestroySuperBean。这样SuperBean的OnDestroyed就被添加了两次监听,据我观察AddDynamic是会追加的,不是覆盖,因此在新的DestroySuperBean中,只需要添加削弱敌人的调用就好了。

SuperBean的定义 SuperBean的实现

接下来去GameMode里添这个WeakenEnemy方法,添加后先写个空方法,暂时只打印个log。待会再去实现。

创建基于SuperBean的蓝图,调整下尺寸和材质,以便和普通豆子区分,然后在四角删除4个普通豆子,将超级豆拖进场景,运行发现超级豆被吃时,可以打印计数,也可以触发WeakEnemy。

那么,可以去实现WeakEnemy方法了。

打开PacmanGameModeBase类,声明个敌人的结合,用来存储所有敌人,这样在WeakEnemy时方便获取敌人的引用。

声明敌人集合 初始化敌人集合,并实现削弱逻辑

在BeginPlay中收集敌人,在WeakenEnemy中遍历敌人,调用敌人的Weaken函数。Weaken是 一个新增的函数,需要在敌人类中去声明并实现。

打开Enemy类,这里需要用到UE4的定时器,首先在Enemy类中声明一个FTimerHandle。还要两个函数用来削弱敌人、正常化敌人。另外,再写个枚举记录敌人的当前状态。

敌人声明修改

在BeginPlay中设置默认状态,设置敌人的最大移动速度,因为虚弱状态会改变速度。

初始化敌人

然后去实现削弱和正常化函数。削弱时改变状态,更换材质,减少速度,然后在指定时间后调用恢复正常的方法。

削弱 和 还原

编译播放,再吃到超级豆时,敌人就会被减速和变色,然后计时结束后又会恢复原样。

八、玩家与敌人交互

现在玩家与敌人接触时,只会相互阻挡,修改敌人和玩家的碰撞描述文件,修改Pacman与Enemy的碰撞响应为overlap。最后在敌人类中添加碰撞监听。

接下来的一些内容,都是基本的游戏逻辑,胜利、失败、暂停、继续也都是有限状态机实现的,与虚幻4特性无关,已经消耗了太多时间在学习UE4上,项目那边要补进度了,因此不再一一记录。

这里主要说一些遇到的问题。敌人的控制器忽然失灵了,看引擎的日志,发现有个警告 warnin C4458 查了一下,说是自己声明的变量名和父类中的变量名冲突了,改个名就好了。另外有时候项目连续崩溃,无法重启虚幻4,需要在vs中重新生成解决方案。

还遇到个问题是,玩家与敌人碰撞时,会连续多次触发overlap事件,这是因为,我在之前调试碰撞时,把玩家胶囊体、球体、网格的碰撞预设都改成了Pacman,其实只要设置一个胶囊体就可以了,其他还原。

还遇到一个巨坑的问题,google也没找到解决办法。

上面的设置虽然能使overlap触发一次,但是当地人自动回家时,会被玩家挡住去路。于是,新增一个Empty碰撞通道和描述,所有碰撞响应都设为忽略。将Pacman和Enemy加给各自的胶囊体,然后各自的其他组件都使用Empty,这样在敌人回家时,不会被玩家挡住。

但是,问题就回来了

OnComponentBeginOverlap总是调用两次,研究很久,发现如果碰撞后,不立即将玩家放置到出生点,就不会overlap两次。。于是将“玩家返回出生点”改成了异步方式。就好了。

九、UI和音效

新建HUD的子类,声明一个字体UFont,重写一个DrawHUD函数,在蓝图中给字体赋值,在DrawHUD中绘制想要的内容。我这里只写了玩家生命值。

HUD 运行效果

添加音效。

需要使用 wav 格式的音频文件,将文件直接拖进Content Browser下的目录中就导入了。这里添加两种,一个是用引擎添加的背景音乐,一个是用C++添加的敌人被攻击音效。

背景音乐是自动播放且循环的,右键拖进来的音频文件->创建Cue 然后在SoundCue编辑面板的右侧找到 looping 添加到节点中,放在WavePlayer和Output之间

SoundCue

然后在游戏场景中添加一个环境音效,把刚刚新建的SoundCue丢给环境音效,播放游戏就有了一个自动播放且循环的背景音乐了。

接下来是敌人音效,首先找到要使用的音频文件,右键复制引用,接下来敌人类中声明一个USoundWave,用ConstructHelpers去获取刚刚复制的路径来实例化USoundWave。在敌人被杀时调用UGameplayStatics::PlaySoundAtLocation来播放。

创建USoundWave 播放音效

到此,音效添加完成。

十、结束

我想以H5的方式启动游戏时,又出现了一些错误,基本都是需要引入头文件的问题。如果是.h文件,类名前加上class,如果是.cpp文件,需要include,可以去官网搜索用到的类,将网页滑倒最后,找到类的路径 引入即可。

查询类的头文件路径

H5运行效果,字体有点奇怪。

后续我还想在敌人的家里放一个只阻挡玩家,不阻挡敌人的“墙”,玩家的出生点也放一个只阻挡敌人的,这样就都有基地了。还有场景的两个出口,现在走过去就会掉进深渊。。。想加个左右互传的传送阵。还有视角问题,想改成第一人称视角的,再把球换成人形,做个小地图。。。想想简直就是旷野之息的迷宫了喂 ԅ(¯﹃¯ԅ)。

放个项目工程文件

链接:https://pan.baidu.com/s/110aKqjRNIzwPG0d_raP-Ew

提取码:e9hi

上一篇下一篇

猜你喜欢

热点阅读