说明:

<学习>系列所有的源代码均由《计算机游戏程序设计》提供。本人会在这些代码中融入自己的想法,对其进行迭代优化,旨在个人学习。

教材源代码示例:

示例代码的迷之bug贼多,怪物AI也只有一套固定的行动模式

优化后的效果:

学习目标:

1.了解二维游戏动画合成原理。

2.熟悉Cocos2d-x中的用户交互、触摸事件、碰撞检测机制。

3.熟悉CocoStudio动画编辑器的使用,了解骨骼动画。

主要修改内容:

1.利用cocostudio修改人物骨骼,并将修改结果在游戏中读取,从而改变人物外形,动作等,实现自定义人物骨骼动画效果。

2.增加英雄defend动作,记录成功/失败次数,增加计分板功能。

3.修复bug,使游戏能正常运行。

4.怪物AI设计。

步骤与过程:

1.利用cocostudio修改人物骨骼,并将修改结果在游戏中读取,从而改变人物外形,动作等,实现自定义人物骨骼动画效果。

CocoStudio Animation导入新的部位的图片,如下图的帽子和斧子:

图 1

图 2

创建新骨骼并对图片进行绑定,再绑定到相应父骨骼上,得到新的角色外形:

图 3

之后更新英雄角色每个动作的角色外貌,如下图奔跑动画:

图 4

添加自制防御动画,如下图所示:

图 5

最后给每个动作的最后一帧中的某个部位层添加一个“动作名_end”的帧事件。如下图添加攻击动作的帧事件:

图 6

导出文件后替换掉源代码中英雄文件,运行程序,发现英雄外貌成功改变了:

图 7

2.增加英雄defend动作,记录成功/失败次数,增加计分板功能。

在cocostudio中已制作了“防御”defend的动画,接下来只要将防御按钮和动作加到游戏中去就行。如下为AnimationScene.cpp文件中按钮代码:

图 9

图 10

为区分攻击和防御键,另其分别使用两张不同的按钮照片。其中,攻击按钮为红色,防御按钮为蓝色:

图 11

枚举类型中添加了防御DEFEND后,英雄类文件Hero中,简单模仿攻击方式的代码写一个防御方式,使点击防御按钮后实现防御功能,如下图所示:

图 12

关于防御功能的代码及其相关完善,我将在后文的第5部分再详细说明。

增加计分板:

重新新建一个文件SaveScore (.h和.cpp):

SavaScore.h

图 13

SavaScore.cpp

图 14

把SaveScore.h头文件导入AnimationScene.h文件中被其引用。 SaveScore文件的功能为存储英雄和怪物的比分,heroScore为英雄得分,enemyScore为敌人得分,刚开始都为0。这种做法好处在于,可在AnimationScene文件中直接对heroScore和enemyScore进行操作,在AnimationScene场景被刷新后,计分值也不会改变,直接调用即可。

计分板代码:

图 15

update函数中不断调用judge函数,根据角色的血量来判断输赢,代码为:

图 16

图 17

当每轮游戏结束时(还没到最终输赢),需要刷新当前场景,这里用scheduleOnce的方式调用了restart函数,该函数里执行的代码可刷新场景。由于一轮游戏结束后场景不会被马上刷新,而是在等待几秒中后才刷新,所以这里的scheduleOnce对选择器选择的函数的执行是在3秒后。

restart代码:

图 18

其中,场景过渡使用了部落格特效,持续1.2s 。

3.云朵移动

寻找或自行扣掉一张没有背景的云朵的png图片,替换掉资源原有的cloud.png图片 。

图 19

AnimationScene.cpp初始化时创建3朵云,位置设置为不同,代码较简单,不显示。

再在update函数中不断修正其x轴方向位置,每朵云的位移距离不同。当云朵移动到镜头的一端看不见时,在修正其位置到屏幕另一端,这样就能得到循环播放的3朵云。

以1号云朵的位移代码为例,其余类似:

图 20

运行效果图:

图 21

4.BUG修正

教材提供的示例代码有许许多多的bug,主要原因是代码逻辑写得不好,这一部分花了大量的时间去Debug来修正。终于解决了游戏中存在的目前能找到的所有Bug,令游戏能正确且流畅的运行起来。

由于游戏bug太多,下面根据解决方法的不同,总结为4类Bug:

  • 按攻击键除了能控制英雄的攻击动作,也能控制怪物的攻击动作。
  • SMITTEN颤抖/硬直动作没有执行、ATTACK动作的动画可被打断、角色被击中后会原地卡在STAND或RUN动作中执行不了任何操作  等一系列稀奇古怪的动作。
  • 莫名其妙连续多次扣血(不是指暴击),在解决②的bug后,容易发现当角色砍中另一角色时,会继续不断使用attack。
  • 角色在奇怪的地方被砍中,或砍不到角色。

下面修正上述bug:

  • 攻击键也能控制怪物攻击。

注释掉或删掉AnimationScene.cpp文件中的attackCallback函数中的红框中代码即可:

图 22

  • SMITTEN动作不执行,被砍后不能操作,attack动作被打断 等奇怪举动的bug。

这个bug为该程序中最主要的bug,以英雄Hero为例,问题主要出现在下面三个地方:

  1. AnimationScene.cpp中的update函数中的:

图 23

  1. Hero.cpp中的play函数:

图 24

  1. Hero.cpp中的整个update函数(代码太长,截取一部分)

图 25

图 26

分析bug原因:

可见,1)根据摇杆的操作情况,调用2)的Hero中play函数,而3)能检测Hero的状态,执行动作。

因为1)在update函数中;2)被1)调用;3)是update函数。 所以理论上1)2)3)都是一直在运作中的,没有固定的先后顺序。因此,由于不能确定运作顺序(除了 2)会在1)后运行),导致程序容易出错。

举例:

当hero被攻击,Hero的play函数会被传入枚举类型SMITTEN作为参数,根据play代码可知,此时受伤状态变量m_ishurt会变为true,当前角色状态m_state会被赋值为SMITTEN。

理论上来说,下一步该执行Hero中的update函数,判断并执行SMITTEN动作了才对。 然而,这里也有可能在执行Hero的update函数之前,先执行了AnimationScene的update函数。

如果先执行了AnimationScene的update函数,那么1)的“控制角色移动”的代码段就先被执行了,如果此时没有动摇杆,那么枚举类型STAND将作为Hero的play函数的参数传进去,之后就会重新赋值给m_state,SMITTEN状态就会被STAND状态给覆盖掉了。

此时,m_state的值为STAND,而m_ishurt的状态依然是true(因为SMITTEN动作没有被执行)。 再进入Hero的update函数时,由于m_ishurt也是各个动作是否该执行的判断依据,当m_ishurt == true时,这些动作都不会被执行。

因此,当hero被攻击后,hero的操作都将失效。

根据上面分析,想要解决这个bug必须要保证两个前提(暂不讨论DEFEND防御)

  1. 状态m_state一旦被改变后,只有执行完了该动作(ATTACK和SMITTEN)后,才能再次改变状态m_state。
  2. ATTACK和SMITTEN对应动作在执行中时,一定要运行到最后一帧,不能被打断。

解决上述1)和2):

1)在Hero.h中声明新的布尔类型私有变量actionFlag,其作用为  当m_state被赋值为ATTACK或SMITTEN时,actionFlag被赋值为true,当其为true时,m_state不能被再改变,只有在ATTACK和SMITTEN动画运行到最后一帧时,actionFlag变为false,此时m_state允许被赋值。

修改相关代码:

图 27

图 28

2)研究源代码中attack相关函数,发现Hero中的m_isAttack的作用为判断hero是否“正在攻击”,这里指的是“动作”而不是“状态”。通过这一变量,在动作执行时(动画播放时)才赋值为true,在最后一帧播放完了再赋值为false。把该变量作为动作执行的判断依据,能有效地控制并防止动作的被打断以及持续进行(譬如一直点击攻击键,攻击动作不断被打断并重新执行,只播放前几帧);

模仿m_isAttack变量,把m_ishurt变量的意义从原来的“受伤状态”更改为“受伤动作”。

同时,在监听帧事件的函数中,要在动作执行完后加入play(STAND)的代码,防止其带着原来的m_state先执行Hero的update函数又引起什么奇怪的操作。

模仿着更改代码:

图 29

图 30

同理修改Enemy的代码即可。

  • 莫名其妙连续多次扣血(不是指暴击),在解决②的bug后,容易发现当角色砍中另一角色时,会继续不断使用attack。

查看碰撞检测文件MyContactListener.cpp,查看其update函数:

图 31

以敌人攻击英雄为例,关键代码部分放大↓:

图 32

分析:

由上面代码可知,当其他条件满足的前提下,Enemy的m_isAttack变量为true时,表示此时敌人正在执行攻击动作,if满足条件,执行Hero的hurt函数,hero受伤掉血。然后Enemy执行setAttack(false)把其m_isAttack置为false。

然而,当m_isAttack置为false后,在Enemy中,会把其视为攻击动作已经结束,在m_state还是ATTACK时,会把m_isAttack==false作为再次执行攻击动作的判断依据。而检测碰撞文件的update函数又会很快的被再次执行,m_enemy->isAttack()又会被视为true……如此地连续执行,可能会造成角色的连续多次掉血,或者角色一旦攻击到另一角色时,会不断地执行攻击动作。

解决:

通过上述分析,我们了解到,解决问题的关键点在于不能在检测碰撞中执行m_enemy->setAttack(false)来改变破坏Enemy的攻击动作。

综上,我们保留其思想,但是不改变m_isAttack的值,为角色引入一个新的私有变量attackHurtFlag,表示被攻击伤到伤害的标志,增加set和get方法。以enemy攻击hero为例,关键代码为:

图 33

Hero的update函数中:

图 34

  • 角色在奇怪的地方被砍中,或砍不到角色。

观察碰撞检测文件MyContactListener.cpp,查看其update函数中enemy攻击hero部分:

图 35

分析:

发现其碰撞检测的基本原理为:为enemy的ax层(即enemy的斧子部件)添加2个检测点,再根据hero的位置创建一个矩形。当enemy为攻击状态,并且其斧子的2个检测点在hero的矩形范围内时,即为实现碰撞。

因此,这里该如何创建矩形成为关键。

分析Rect方法的参数,其第1个参数为矩形左下角的x坐标,第2个参数为矩形左下角的y坐标,第3个参数为矩形的宽,第4个参数为矩形的高。

结合游戏运行图来分析:

假设在使用cocoStudio Animation时,角色的中心点在身体的中心点,随意创建一个矩形,则有:

图 36

假设还是同一程序,当hero转身后,其矩形不会根据角色的转身而左右颠倒,如下图所示:

图 37

由上面两张图可知道,创建矩形时,宽(即x轴)的中间位置的x坐标最好落在角色中心点的x坐标上。只有这样,hero无论转身与否,其前后的被攻击的判定范围都是一样的,这样才不会出现奇怪的“有时能砍到,有时又砍不到”的奇怪现象。

最后只要不断调整矩形的宽度即可(即调整第1个参数和第3个参数)。而矩形的高度只要足以涵盖住角色即可(即调整第2个参数和第4个参数)。

最终矩形参数修改为:

图 38

图 39

5.防御机制

防御机制设定为:

  • 点击蓝色按钮进入防御状态
  • 防御状态下,角色最后会保持防御动画的最后一帧
  • 防御状态下能减少一段暴击及暴击伤害,受到的伤害值以蓝色数

值显示

  • 防御状态下,操作摇杆,点击攻击按钮,能打断防御状态,并执行其他相应动作
  • 防御状态下,再点击一次防御按钮可以取消防御状态

根据以上设定,编写代码:

Hero中的update:

图 40

并为每个动作的执行加上m_isDefend=false,以STAND站立动作为例:

图 41

Hero的showBloodTips函数 “减少暴击数和暴击伤害”以及“防御状态下伤害值为蓝色”:

图 42

图 43

运行图:

图 44

6.AI设计

观察AI文件AIManager的原代码,发现怪物AI仅仅是根据一套固有的动作反复执行而已,关键代码为:

图 45

分析上面代码,可知这个AI并不智能。并且根据上面的执行结果,可知moveLeft的动作持续最久,因此游戏中的后半段,敌人emeny会一直往左边界“推墙”,moveRight的持续时间太短,因此无法往右半边回来。

因此,重新编写一个AI代码文件,使其能够根据hero的位置,实现自动跟踪,在适宜的位置进行攻击的功能。

编写后的关键代码为(以hero在enemy的左方为例):

图 46

hero在enemy的右方时也同理可得,而当hero和enemy位置相同时,enemy直接攻击即可。

由上述得到了敌人AI的最佳方案,但是如果直接把bestAI函数放到update函数不断调用的话,会发现游戏会变得非常困难,几乎没有赢的可能性。并且,敌人enemy的行动模式不够随机也反而显得不是那么的“智能”。因此,在此基础上减少bestAI的执行次数,插入随机行动模式,并适当地减少攻击频率,让游戏变得更简单,令AI变得更随机些。

修改后的代码为:

图 47

bestAI()中以hero在enemy的左方为例:

图 48

AI的随机方案:

图 49

通过上述操作后,敌人AI能够保持在最佳行动方案的基础上,也进行些许随机行动了。

7.其余Label显示细节

① 每轮游戏开始时都会出现“Round X”,X表示游戏的第几轮,1.5s后消失(移除)

图 50

② 每一小轮游戏结束后,都会在对应角色的血条下方显示“win”字样

图 51

③ 场景有部落格特效过渡

④ 游戏结束后会显示玩家的输赢,赢了显示“YOU WIN!”;输了显示“YOU LOSE!”

图 52

学习3 二维游戏动画合成(侠客行)相关推荐

  1. Unity3D官方二维游戏开发教程中文版分享

    什么二维游戏这么重要? 的三维游戏已不是什么秘密. 很容易的创建经常的游戏.Unity无疑是一个伟大的三维游戏引擎. 游戏想法,可能会受到二维的限制.但事实上有许多游戏可以很好的利 识.我们还 会包含 ...

  2. 专属自己的二维游戏引擎【二】

    我给客户制作美术素材从来没有崩溃过,最近给一个客户制作二维游戏素材的时候就直接崩溃了. 次时代模型的流程虽然麻烦,但是我还没有见过比它更麻烦千倍的东西,这次算是见识了. 韩国的泡菜确实比较不太好吃.你 ...

  3. PS制作心跳二维码动画 学会后能增加粉丝关注率哦

    现在二维码到处都是,若想用户关注到你的二维码,必须搞点新花样才行哦,早期我们分享过「设计灵感:二维码也玩创意」一文,里面有很多不错的设计创意,然而有没有想过自己他创建一个可以长按识别并且是动态的二维码 ...

  4. 二维卡通动画制作学习教程

    与霍华德·威姆斯特一起掌握动画 Mastering Motion with Howard Wimshurst 这门课就像6门课合二为一.它将包含以下方面的详细课程: 1)图纸 2)动画/特效 3)使用 ...

  5. 学习:二维码、QR码、J4L-QRCode、java

    转自:http://baijinshan.iteye.com/blog/1004554 学习:二维码.QR码.J4L-QRCode.java Java企业应用网络应用Rails应用服务器  开源码 J ...

  6. 鼠标悬停出现二维码动画放大,url转二维码

    鼠标悬停出现二维码动画放大,url转二维码 效果 首先引入jq和qrcode.js <script type='text/javascript' src='http://cdn.staticfi ...

  7. 杠子老虎鸡虫 《python二维游戏编程》课后项目一

    <python二维游戏编程>项目一:杠子老虎鸡虫 V0.0.2.20210629 项目简介 <python二维游戏编程>课后项目1 适用于中国农业出版社,张太红主编,2015版 ...

  8. asp生成带参数的二维码并合成推广海报图片,asp合并合成推广海报图片asp代码

    最近做的一个项目中,客户要求用asp生成二维码,然后合并到一张背景图片上,合并生成一张推广海报来,可把我愁坏了,经过一个晚上的努力,成功了,下面把这个:asp生成带参数的二维码并合成推广海报,asp合 ...

  9. 深度强化学习笔记(二)——Q-learning学习与二维寻路demo实现

    深度强化学习笔记(二)--Q-learning学习与二维寻路demo实现 文章目录 深度强化学习笔记(二)--Q-learning学习与二维寻路demo实现 前言 理论 什么是Q-Learning 算 ...

  10. asp生成带参数的二维码并合成推广海报图片,asp合并合成推广海报图片asp代码...

    最近做的一个项目中,客户要求用asp生成二维码,然后合并到一张背景图片上,合并生成一张推广海报来,可把我愁坏了,经过一个晚上的努力,成功了,下面把这个:asp生成带参数的二维码并合成推广海报,asp合 ...

最新文章

  1. 以太坊经典逆势上涨,行情能否继续?
  2. c++堆内存默认大小_C++|array new 和 array delete的堆内存细节
  3. php文件安全实现方法,php安全下载大文件的实现代码
  4. JAVA学习笔记--初识容器类库
  5. 物联网落地三大困境破解
  6. ceph iscsi安装
  7. 实战:MongoDB 分片集群Shard Cluster 搭建(1台路由节点,3台配置节点,9台分片节点)
  8. Android 系统(152)---Android多线程:HandlerThread详细使用手册
  9. 数据库-几个重要的数据库相关概念
  10. 大厂2020届实习生笔试题
  11. C#使用带参数的存储过程
  12. 农作物分布数据、作物类型分布、农田分布数据、土地利用数据、植被类型数据、物候数据、NDVI数据
  13. 计算机cpu占用率高,CPU占用率高怎么解决?Win10系统电脑CPU占用率100%的解决方法...
  14. 中国露营、户外和越野拖车市场运行动态与发展趋势分析报告2022-2028年
  15. 2018年北京信息科技大学第十届程序设计竞赛暨ACM选拔赛 C:计算几何
  16. 微型计算机控制数字量输入输出,计算机控制系统输入/输出通道
  17. 深入理解地址翻译 CSAPP
  18. 中国地址英文翻译,英文网站注册
  19. The Load Slice Core Microarchitecture
  20. cad中怎么随意移动图形_CAD中需要挪动图形到准确位置?试试这几种方法

热门文章

  1. xamarin android pdf,Xamarin 中的Android资源及使用.pdf
  2. 博弈论分析题_博弈论习题及参考答案
  3. linux 安装adobe字体,Adobe Creative Cloud应用程序已更新,为iOS 13和iPadOS提供免费的自定义字体...
  4. 框架分析--框架的类关系图
  5. 2021.12.13(第一周) 实习周记lzhuan
  6. Java 软件安装流程详解
  7. IDEA放大和缩小代码字体的快捷键设置
  8. 零基础30天入门Python教程第6节:数据结构
  9. 计算机组成原理笔记(王道考研) 第一章:计算机系统概述
  10. sd卡写保护解除工具_U盘格式化工具怎么用