bvn过程记录
本文最后更新于 2024年12月20日 下午
此为研开大作业——仿《死神vs火影》(Bleach vs Naruto,故名bvn)的项目开发过程记录
实际上是类似草稿本的存在
11.13
配好了环境,SFML需要:
- 下载
- 设置项目的附加lib和include,还有链接的文件,再把dll文件复制到x64下的debug。
把图片准备好,地图后景和前景。
人物目前暂定就itachi、garra跟一护,特效和人物动作都齐全,鸣人的三段变身缺第三段变身的素材,第二段的缺技能特效。
地图得做视差滚动,看是直接贴图还是以材质形式贴上去
小坑
visual studio的相对路径是以sln所在的目录开始的,不是exe的。
11.14
- 调好窗口大小
- 贴好图片
- 放个人物上去,先左右,再上下,根据人物的位置实现地图视差滚动
- 实现地图的高台站立
只有一张地图?先弄好一个地图吧,记得面向对象,后面才好换地图和人物。
软件工程起作用了,不能直接开始写,不然就是堆在一个文件里了,得OOP,就要先设计好整体的架构,先整个类图出来。
暂定Game、Character分Player,Enemy、Map、Platfrom、SoundManager、GameClock、Effect这几个类,共同组成Game大类(感觉要重构,一开始就设计好太难了,软件工程上是怎么敏捷开发的呢?)
- 远景永远不动
- 在一定距离内,窗口不缩放
- 角色尝试分离并离开窗口,窗口放大以装下角色,同时窗口被拖动
- 窗口达到最大放大程度,不再放大,同时限制角色离开窗口
- 角色靠近,窗口缩小,窗口两侧与角色的间距不变(约1/10宽度,平滑),直到进入一定距离,缩放达到最大程度,角色很靠近。
搜了一下,这可以叫盒子模型,SFML正好有机制能够实现这种类似于有一个镜头的逻辑,叫做“视图”。先学习一下。
引入视图,实现大地图固定绘制,移动视图来实现镜头感
视图有最小尺寸和最大尺寸,最大会反过来限制人物的位置,但是视图的坐标好像和实际2D空间的坐标不一致,写写停停没时间了,调试之前还需要初始化人物和视图的位置,但是已经初步完成了视图聚焦图像的一部分,只不过背景没固定,前景没铺开。
背景固定铺满窗口需要在view中绘制,而不能在window中绘制,window对应着2D世界,而view是可视界面
明天继续
11.15
人物是贴上去了,速度如何设置呢?
按键->运动->松开->不运动,所以按键就让速度生效,不按键就不影响position。抛开牛顿定律,按键影响速度,不按键速度归零,位置每一帧都得加上速度
游戏循环为:处理事件 ==> 更新状态 ==> 绘制画面。
问题:人物不能同时跳跃和左右移动,只能垂直起跳,且朝向切换迟滞
预估是事件队列的原因
问题2:
窗口的跟随移动稍微有点大,还需要做:
窗口的极大限制;人物与窗口边缘的间距
BUG1:
把按键逻辑放在处理事件中,就会很卡,但是如果鼠标一直移动就会顺畅,甚至能够在空中保持水平速度!
如果把按键逻辑放在update中,就会顺畅,但是速度值会莫名变大,同样的数值会有更快的速度
解决:
之前是从窗口捕获的事件队列里逐个取出然后传给handle函数判断,显然效率很低
现在改为sf::Keyboard::isKeyPressed(),执行到的时候即时查询键盘状态,由于这个游戏大部分都会长按AD键移动,所以即时更合理
但是,原游戏只有AD可以长按,其他都只能点按,例如长按K不会一直跳跃。
BUG2:
又无法二段跳了。。
解决:
测了下当前的帧率,基本都有300+帧/秒,所以在短时间内就跳了两段,要么引入限制,要么用事件取消K的即时查询而放过AD,技能释放肯定也会有这样的问题,短时间释放了好几个,现在就解决掉。
又把事件队列引回来了,正好实现了跳跃的:无法长按连跳、按键事件区分
和原型游戏对比,得到镜头最大放大2.5倍。用mapPixelToCoords函数转坐标来固定后背景,前景就设在绝对2D坐标系下,图片的大小和人物的比例正好匹配,当前图像尺寸是800600,窗口尺寸1600 1200,人物是背景图的1/10高。
已经完成地图贴图和角色控制移动了
然后需要:
- 定义平台,实现站立、主动落下
- 人物贴图轮播,实现动态效果
- 敌方贴图
定义了个枚举类,给不同的状态区分不同的图片组。
感觉得用上GameClock类来控制帧率了,不然不好贴图,每帧一张图片,人物、特效的贴图都需要更新,需要统一帧率和时间。
明天白天进“大观园”开眼界,晚上再写
11.16
下午四点,开工。
先弄好帧率
使用elapsedTime记录当前时间,在update时传入距离上次更改贴图的时间,如果大于了deltaTime,就根据当前状态切换贴图。
这样相当于实际每秒有几百帧,极短时间内有好几帧都相同,以此降低了看到的整体帧率,整体帧率由各对象的deltaTime决定。
但是切换到哪一张呢?站立、跑动、空中姿态需要轮播;防御需要按顺序切换后停在最后一张图片;释放技能、受击只播一轮,结束后回到站立姿态;击飞则是受击后停在最后的状态直到重新站起
所以有:
- 只要状态不变,就一直轮播
- 只播一轮然后停在最后一帧
- 只播一轮然后必须切换到其他状态
仅播一轮最后也会停留,比如释放技能,最后一两帧为了营造慢动作效果,切换时间更久
每组贴图都需要一个变量记录当前的图号,以便按顺序切换贴图——可以状态切换时置零唯一的图号变量。
每个角色对应的贴图不同,所以要根据Player的角色名来选择相应的loadImage方法,加载正确的资源,同样的,每个角色的技能组各不相同,所以还需要统一的技能分类对应到正确的技能组。
如果给每个角色都重写一遍函数,好像有点冗余和复杂了,所以!得重构!
第一次重构
Character类变抽象类,现有的实现具有共通性的保留,其他的变纯虚函数让子类单独实现
取消单独设置的Player类和Enemy类,而为每个角色都建立一个类,继承Character
对应的,Game类中的Player和Enemy改为Character类的智能指针,用来多态。
利用工厂模式,新建CharacterFactory类,在Game主类中将原来的Player类和Enemy类改为两个Character类型的成员Player和Enemy,游戏开始前通过选择类型,从工厂中获得选取的子类赋给player和enemy(多态的典例应用场景啊!大一学的竟然忘光了😭)
特效类和Effect和地图类Map也可以这样,但是先就一个地图做着吧,如果后面有时间加地图就把Map类也这样重构了。
BUG记录:
- 重构完贴图失败,原因未知——Texture用了个局部变量,对SFML的机制不了解,set给sprite的并不是sprite保存的,如果texture被释放,sprite的纹理就没了。
- 运动出问题,左右走可以,跳可以,跑跳就会直接飞天——状态机没设置好
状态转移的时候还需要更谨慎和精细,最好能把状态转移都集中到一个地方,但是键盘事件处理和位置信息处理分别在process和update层,没法集中,也许可以改架构。
明天再写。
11.17
贴图基本完成,接下来是:
方向:
引入敌人==完善双角色的视图逻辑和边界设置==设计人物作为敌人时的逻辑==方向状态转移==方向变化时镜像素材==方向
确实是改一个小功能就要大改整个项目🥲
敌人如何行动呢?要想象是另一个玩家在与我对战,他会如何行动,我要为他设计操作接口。
玩游戏的流程是:
看画面(获取地图、敌方信息)==>心中指定策略(根据信息,进入状态机转移状态)==>按键控制,实施策略(敌方调用控制方法)——>进入update,使行为真正实施到游戏系统中——>绘制画面==>重新循环
所以,敌方的获取信息和行为的状态机都放在process层,敌方需要map信息和player信息,凡是在画面上能展示的,敌方都能够获取。
此时敌方已经不仅仅是enemy了,而是另一个更类人的事物,于是新建类AIController
表示与玩家对战的智能,该智能操纵Game中的enemy与我操纵的player对战。
为了打字简单,命名为Controller好了
经过:
引入敌人、完善双角色的视图逻辑和边界设置、设计人物的方向状态转移、方向变化时镜像素材
最终实现了人物自动面对面,以下是错误示范:
然后需要:
- 做完地图
- 做更多的人物
11.18
碰撞检测:
- 人物与人物——player和enemy都需要互相判断,或者先判断的传递结果给另一个
- 人物与平板——player和enemy都需要与所有的platform判断是否在其上
- 人物与视图边界——视图会获取player和enemy的坐标动态扩大,player和enemy也会根据视图限制运动
- 人物与特效——特效类尚未开发,暂时忽略
都需要在update层判断。都是人物的,都传给人物的update
似乎原游戏存在重量,人物相推速度变化不一致,有的减半,有的更慢 这里都设置为一样的重量,如果有人物挡道,则速度减半
人物碰撞:
- 从垂直方向碰撞,依据相对位置互斥,直到无重叠,各自垂直速度不变
- 从水平方向碰撞
- 如果碰撞方有速度,则减半,同时被撞方互斥,与碰撞方一起运动,直到不重叠
- 如果碰撞方无速度,依据相对位置互斥,直到无重叠
角色互斥效果类似于引力和库仑力,与距离平方成反比,越近互斥速度越快
因碰撞产生的运动不改变当前运动状态,比如正在站立或跳跃,被碰撞获得水平速度,不会转移为running状态,因此贴图组不变
🤣🤣🤣,如果我闲的没事的话,一定会录个gif贴出来,照着引力公式写,结果写出楞次定律的效果了,来拒去留🤣。(没有在消除碰撞后消除掉加速度)
为了测效果,一不小心打了一个多小时,原游戏的人机也没那么厉害,但是也足够厉害了
平台的判定有问题,站上去就被锁住不能离开了,移速也变慢了,应该还是状态转移的错误:必须在站立或跑动状态下离开平台才转移为下落/跳跃状态。再将按键效果的实施提前到平台效果前,并且如果还有上升速度,就不检测平台。这样就能丝滑地飞檐走壁啦!
继续搞定人物相斥的功能:在速度生效后取消掉速度就可以了:
1 |
|
然后把系数调大一点,看似完成,实际有大bug,当把对方推到角落后,斥力竟失效了,待越过对方,竟直接将对方弹射出去? !😭
原因未知,把update的顺序调整了一下就过了,似乎是智能指针的问题,前一轮循环赋的速度,到下一轮循环就没了,不得已只能在同一轮循环中处理掉碰撞产生的速度。
之前用队列替代即时检测实现二段跳,但是现在需要检测多键了,事件队列没办法检测多键,而且改为即时检测多键似乎也有点问题,要测试一下即时检测多键的可行性和队列检测单键+状态转移实现多键操作的可行性。
连续按键盘间隔一般为0.1秒,而当前的帧率,每0.1秒平均有90帧,也就是90次主循环,垂直速度减去90次GRAVITY,那么只需要在按下K时限制垂直速度必须小于 \(v_{init}-90\times g\) 即可,若大于则不执行逻辑。
判断完状态合法后,让纵坐标下移平板碰撞误差多一点的距离即可:
1 |
|
最终还是使用即时查询,添加了防连点机制,队列暂时舍弃。
11.19
注意到程序运行时电脑很烫,目前没有限制帧率,都是把核显跑满的,切换Nvidia的独显也是跑满,10秒钟就70度了,风扇呼呼转。但是限制帧率后,当前的数值就全乱了,全部开了慢速,限制100帧都还是慢。暂时不调整,后面加了操作可能帧率还会降,到时候快写完了再限制帧率调整数值。
找到了原游戏的仓库,从里面找到了游戏的源码和资源,源码是用ActionScript写的,规模比较庞大,借鉴难度可能和自己写差不多,于是放弃借鉴。
经过探索,发现游戏的人物资源等都是.swf文件,用于Flash的,于是下载了个swf的反编译工具JPEX,把人物素材提取出来,所幸素材比较齐全,人物、特效、音效、图像都在里面,不过普通的通用灰尘特效和冲刺特效没有。
里面的图片相对分散,缺乏组织和顺序,所以从sprite里提取,似乎每个人物包都会有一个展示所有操作的sprite动画,包含一千多张png图片,导出后发现尺寸很怪异,明明实际大小只有100100左右,但是图片却是2600
1300那么大,所以又让GPT写了个自动裁切图片的python脚本,总算把人物素材搞齐了。提取了两个人物软件就崩了啊啊啊啊
然后需要给素材分好组,确定是什么操作。
分组时突然发现,游戏实现前后摇的方法竟然是插入连续相同帧,比如普攻3段后有后摇,在普攻3段后就会有连续多张相同姿势的帧。甚至频闪效果都是一帧有一帧无来实现的
所以,也许可以以贴图播放时间来决定状态转移,而不是以状态转移来决定贴图变化。
大招的束缚效果是否被防御、是否命中,效果都会不同,还是需要根据状态来决定贴图。
那么至此这周的人物就算基本完成了,差个冲刺姿态和招式动作,加个vector<sf::Texture>
和配套的贴图切换case、按键控制就行。
11.20
整理好素材,分门别类,然后写好loadImage函数,注意文件前缀常数化和文件下图片数量,可以问问GPT有没有什么更好的load方式。
保存了目前能运行的分支,但是git操作还是不熟练,又出问题了,两个平行的分支竟然冲突了,合并来合并去,结果推送不上去了QAQ。
GPT写了更集成的load方式,但是load进去之后,之前想到的问题出现了,原本的素材图像很大,播放时人物始终在中间,位置没有动。如果自动裁剪之后,因为坐标始终设置为底部中间,所以人物就无法保证在中间了,要等比例裁剪才行,不然素材对不齐,白整了一天啊😭。
重来:先把素材导出,然后确定裁剪方法,从所有等大小图片中确定一个相对原点,程序中都以这个点为参照点,素材都是朝右的,所以以左下角为参照点,右边有图像就保留,没有就截掉。对应地,程序中的镜像逻辑也需要修改,要保证镜像后参照点位置不变,不能转向后发生突变。
裁剪恐怕需要针对每张图片做定制化方案了,只定制了stand、animation、run。感觉工作量有点大,要简化,不然整理素材都得两三天。还要好好设计一下裁剪的算法
走路的时候突然有思路了:
- 仍然采用自动裁剪空白区域的脚本,保留原图片全部的有效信息,但同时要记录中心点在裁剪后图片的相对位置(依照SFML的源点定义记录,比如sprite采用左上角作为原点,就记录中心点相对于图片左上角的坐标),依照图片的文件名序号,依次保存在文件中(txt、json、甚至excel等等)
- 在Character类中仍然保留一堆Texture,加载方式改变,不分开调用函数了,因为所有的图片都不会再细分各种文件夹,而是在类中使用区间来指定图片,比如[1, 9]是stand状态的图片,就加载给standTexture.
- 最最核心的:每个Texture都要配一个Vector2f,即中心点的相对坐标,从第一步产生的文件里面读取出来,用于sprite纹理的原点重设,从而实现人物的原点不变,就解决了素材错位问题。
- 每个子类仍然需要重写loadImage,可以不重写,但要单独指定每个子类各个操作对应的素材号区间。
11.21
裁剪好了图片,得到了相对坐标表。然后要得到各动作的图号区间,改写load方法,通过表重设sprite的origin。又有问题,图和图号没建立关系,load进程序后就没有图号了,关联就没了。
还得重构:需要建立“状态-图号区间”、“图号-图片”、“图号-原点坐标”的关系,把图片都拉通存在一个vector里,stand、jump都改pair<int, int>
,origin不变。得到状态==>索引图号==>得到图片和原点==>完成sprite更新
好消息:完成了
坏消息:原点坐标有误差,还是会抽搐,而且原点不是脚底,平面高度都错了
😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭
太难了!!素材整理都花了两天时间了😭😭😭
GPT真神了!向其寻求减一,他说可能是同一帧内多次调用setOrigin方法可能导致异常,然后我把每帧默认调用的setOrigin放到了帧切换里面,就不抖动了!!太好啦!
经过这一通重构,update已经完全与人物子类解耦,直接提升到Character类层级,现在人物子类实现了0个接口,不过还是需要实现的,毕竟技能数值效果不同,发生的位移也不同。
11.22
完成其他任务,搁置一天。
11.23
晚上七点才开始,事情好多,不能像上周那样90%的空余时间都投在这上面了😰
之后的开发顺序是:
- 完成各种招式的动画
- 完成招式与敌方的碰撞检测
- 引入技能条
动画播放==>无法控制+前后摇+无敌时间==>冲刺
冲刺不能直接把x坐标加减,只是在几帧之内脱离键盘控制快速移动,中途以空白帧表示瞬移,实际仍然在移动。关键要实现状态的中断和转移,之后释放大招时也会有中途无法控制的时候。
经过实测,I的优先级最高,可以打断冲刺,复合键位则看绝对先后顺序,SL是幽步,中途不会被任何操作打断。但是我不开发幽步,所以废置SL键位,为了简化开发,放弃I打断L的操作。
无法控制状态为Default,脱离于常规状态,此状态下无法通过键盘操控角色。
正在变复杂和混乱,我想到可以用实现状态机的一些C++库来开发游戏的状态机,这样在后面开发敌方状态机的时候可能会更容易更清晰一些。
但是学习状态机的库需要时间,还是学一下吧,磨刀不误砍柴工,也许这会极大简化后续开发,也许这只是进一步复杂化问题,总之,先看一下,今晚的时间就用于学习C++的状态机相关API好了。
整体上看,改变人物状态的地方有:
- 键盘控制(ADJKUIS)
- 2D世界的物理特性(下落和站立)
- 敌方的行为(攻击命中)
而角色的position、velocity等在状态不变时也会改变,与状态无关,状态用于控制贴图、限制键盘操作逻辑。贴图有单独的方法,输入状态,输出贴图;键盘也是,输入当前状态和键盘输入,输出velocity变化以及下一步状态。
开始状态为Stand;
AD键控制左右移动,如果当前在平台上,则切换为Running状态,动画改变,如果在空中处于跳跃Jump或下落Fall状态,则不改变状态,只造成位移效果。释放AD键则取消位移效果,同时离开Running状态。
K键单独按下且跳跃次数有剩余且当前状态为Stand或Running则进入Jump状态,同时获得向上的速度
SK同时按下且位于平台上且处于Stand或Running状态时,转为Fall状态,发生向下的极短位移以脱离平台向下坠落
11.24
感觉状态机可行,结果导入库的时候寄了,明明说的是导入hpp文件就行,结果导进去一堆报错。耗费3小时,配置仍未成功,放弃使用状态机,采取if-else堆砌的方式😞。
通过打补丁的方式,写好了冲刺。接下来是引入技能动作。先写个平A,每个技能都不好写,各有特色,机制复杂。
平A的动画和控制主要就是连续J的判定和状态转移,至少现在动画不错。为了展示工作量,先不写碰撞判定,把各种动画写完吧。
11.25
防御状态和AD一样,按着才生效,不按就不生效,而且放开之后还有松开的动画,松开的几帧还不能AD,但是已经不是S状态了,可以被揍。S状态被揍还要扣chakra。
即时查询没有按键释放的事件,所以用状态残留来判断是否释放。(bug留给之后,先实现再说)
复习了一下SFML的教程,发现SFML建议我不要经常切换纹理,会造成显卡负担,我仔细了解了一下,原来贴吧的素材以大图的方式给是有原因的啊,所有的动画帧在同一张图上,这叫纹理图集,通过滑动窗口的方式切换纹理,这才是性能最高的方式。 (重构任务+1😭)
简单的动态都写完了,为了之后开发,先搞纹理图集。
重构:纹理图集
纹理图集需要将所有动画帧放在一张大图上,sections和origins不变,原来的textures变成窗口的坐标,另外单开一个texture存大图。有之前的基础,重构还是挺简单的,只需要改load方法和改setTexture为setTextureRect就可以了
完善了S系列的状态之后,我爱罗的J、SJ、SU、S、WJ、L、ADK就都完成了
接下来的工作路线是:
把有特点的方法迁移到子类==》特效图片整合==》特效类==》特效的图片整合进大图==》完成远程攻击和追身攻击
特效图片原点不规则,不是在正中心,迷惑,得一组一组找中心才能用分割程序。还差一个SI的,弄完再把空帧的坐标补了就完成第二步了。
11.26
特效图片整合完了,编写特效类,为了正确展示,基本的成员得有,沿用currentFrame。由于特效可能属于不同的技能,每个人物具有单独特效的技能又不一样,开个Map,加个枚举类当索引,有就放map里,没有就不放,切图的时候先检查一下map有没有就行了。
特效类定义完了,得让角色能打出特效,以及特效能动飞或者追身。
又有问题,如果一个任务的wu是追身,另一个是远程,那怎么分辨呢?还是要给每个人物写特效类,贴图可以通用,但是逻辑没法通用。
触发逻辑参照人物,像触发人物动作那样,用人物状态触发特效。
又想到问题了,一个人物不一定只有一个特效,即使是u也可以连发,那是在人物里开特效池还是特效里面开组呢?在人物类里面开特效池比较好。开个vector,每个都先构造了,设置成Default。放技能就拿出一个Default来用,绘制的时候就批量绘制。
11.27
U的特效打不出来,很奇怪,调试时明明都看到坐标变化和render调用了,但是没有。
今天没什么进度。
11.28
U的特效没对齐,延后11帧再播放特效。位置偏移量硬编码。完成U。KU、WI_before直接贴图。
然后是追身系列技能。I只获取x,而SI获取完整坐标。SIbefore的追身写好了,写I的时候发现I没有before,将就把miss的倒放。
现在所有招式都写完了,把人物的特效改为特效池,然后开发招式与敌人的碰撞检测。
在自己的update里面新增updateWithEffect,然后传入敌方的位置。
11.29
将人物的特效改为特效池之后,实际帧率断崖式降低,竟然只有25帧左右,非常卡,尝试优化优化,如果还是这么低就只能放弃多特效了。
帧率计算一直用的0.1秒,所以实际帧率一直是几百甚至上千帧,离谱了。
而且多次测试,发现帧率其实是变动的,很不稳定,使用率低的时候就很流畅,一旦多任务忙起来就会变慢,甚至在游戏过程中都会时快时慢。还是把帧率限制一下吧,天晴了,写这玩意火气都没那么大了🌞。差个WU,给补了。
现在需要:弄好特效池=》特效与人物的碰撞判定=》hit和kick的状态转换=》hit和kick的击飞位移=》加入仙鸣
攻击判定,要有延后,得能躲过去,要给判定函数滞后的位置信息,但是帧内好像没区别,总会先更新一个人物,再更新另一个人物,同一帧内的顺序好像不太大,看状态转换图而定吧,应该会有个优先级的。
检测到碰撞后,得让敌人被击打或者击飞,不能直接在自己的操作里修改敌人的状态,得调一个敌人的方法来,受击也有位移,击飞更有位移,所以实际是给对手一个速度,所以受击和击飞函数都得接收一个力也就是速度,像冲刺那样,不可操作,速度不可抵消,只能自行消失。冲刺是贴图播放完就结束,受击时间也是固定的吗?测试一下,是的,受击时间都是一致的,但是存在多段攻击,像I系的前摇、SU的流沙,都会在持续时间内每次更新给予敌人一次伤害判定。
如果在技能更新的每一帧都检测碰撞,多段伤害好办,但是单段伤害就会麻烦,因为不能通过敌人的状态来判断是不是已经受到了当前这个技能的单段伤害,敌人处于Hit状态,有可能是当前技能已经造成了单段伤害正在位移,也可能是之前的招式造成的Hit状态还未结束,Hit状态仍可以被击打,但是当前的招式无法得知是否已经造成了伤害和位移效果。
给敌方写一个命中效果(加速度,打成受击还是击飞,消耗多少chakra条)=》在己方判定与敌方碰撞后,给己方施加这一命中效果=》处理后续的状态转移逻辑,保证受击状态优先
敌方还得有受击效果定义,是静态的,还能写成文件config。
攻击状态都排除人物大小就可以了,而人物都位于左下角,取min(人物h,锚框h),宽度取个平均值写死,排掉做小脚
还要排除防御状态,还得写chakra机制.
11.30
碰撞检测的矩形框计算错了,怪不得一直碰撞错误。
12.1
人物和人物的判定写了80%左右,还有前后摇误判的问题,特效还没出来,然而已经判定被攻击了。
攻击效果还有很大问题,主要是多重受击的问题。
原型应该是有一个攻击判定冷却时间,短于任意两个招式的连接时间和单个招式的持续时间,但是长于每帧的时间。在攻击碰撞检测那里加个攻击判定的定时器,限制攻击检测的频率。这样可以实现SU的多段攻击。
记录上一段伤害来源,hit状态结束后清空来源记录,受到伤害前对比来源,如果相同,则不受重复伤害。但对于SU这样多段伤害,可以不记录来源或者不用来源屏蔽伤害。
12.2
继续写碰撞检测,与特效的碰撞和与人的差不多,但是获取效果的函数有问题,是依照攻击发出方的即时状态决定给什么效果,但对于U,特效碰到的时候,状态早就不是U了,甚至可以替身攻击(其实作为特性还挺有新意的。。)
把状态对齐,转成int,统一伤害来源。
现在还差各种攻击的击飞速度设置,击倒还要细分,落地并弹起就不能再水平位移了,加个帧数限制,这个数值是人物类的静态数值,各个不同。
kick的击飞并不是按播放时间来的,或者说,不同的招式击飞的距离不同,SJ明显更远,3J适中,U最小。飞的动画只有7帧,很短,速度过大很容易产生突变感。
12.3&12.4&12.5
把仙鸣加进去了,跟Gaara相同的部分兼容得很好,不同的部分全部失效,等着写就行。
加了个丐版选人界面,字体没找到,随便上了一个,背景没有。
周三四没什么进度,备考计网+写作业+安恒星火的答辩+打球
碎碎念:
答辩被拔尖班的科研大手子用论文K爆了,也许我还应该再去接触下科研,对于科研和后端开发的好恶程度差不多,那显然是科研更优。
12.6
把gaara的大招效果bug修了,顺带解决了视图的平滑过渡问题。
但是还有大招miss没写,以及大招I和SI碰到S的快速爆条
12.7
今天把NarutoS的控制写了。后面就写各种动画和可视化。视图平滑带来的初始化问题也需要修一下。
把NarutoS的所有攻击动画修好了,包括分体攻击KI和特效,命中效果没写完,因为仙鸣的碰撞判定和Gaara很不一样,不能复用。
由于只写两个角色,所以只得放弃通用性,为两个角色针对性地写对于另一个角色的碰撞判定了。
12.8
写完了全部的技能效果。测试一下,存在BUG,在NarutoS的U冲刺时如果起跳,可能会直接飞天。但是复现不是次次成功,暂时不修。
至此,战斗部分基本完成。
12.9
开始写界面。
加了个开始界面,大概能用,接下来写血条气条之类的。
12.10
对于UI,有固定元件和动态更新元件,固定的元件只需要在一开始设定好position,之后通过遍历绘制;动态更新的元件每次都需要根据人物状态来选择不同的sprite绘制。也许可以在动态更新的时候就保留更新的sprite,在绘制时直接绘制保存的sprite。
12.11
加了震屏,有视图机制,实现起来很容易,用了下事件队列,又学到了,好方法。还有打击感的暂停,暂停有:
全局暂停:
- 某方受击
- 某方被击倒
排除性暂停:
- 一方释放大招,另一方暂停,特效也暂停
仍然采用相同的事件队列方式实现。
大招时停的背景图没找到
敌方AI规则:
- 在同一高度
- 距离远:放U/冲刺过去/跑过去
- 距离中:SU/U
- 距离近:SJ/J/WJ
- 如果是gaara,概率放WI、I,若有SI则立马释放SI
- 如果是naruto,概率U和I,若有SI则绝对距离进了立马释放SI
- 在不同高度
- 根据人物来:gaara
- 敌人低:WU/I/KU,或主动下落
- 敌人高:WU/I/WJ,或主动跳跃
- naruto
- 敌人高:WU+WUU/SJ/WJ,或SI
- 敌人低:KU/KI,或主动下落
- 根据人物来:gaara
- 敌方在墙角:
- KU连,每两套停顿一下
- 敌我同时跳跃且位置合适:KU/KI
- 检测到敌方攻击:概率灵敏S+SJ/SU反击
- 敌方在空中:优先跳跃追击KU,概率使用追身技
12.12
敌方AI很难写啊,周末没写出来就改数值了。if-else凑不出来就没招了,状态机行为树也就听个乐,写不出来,代码能力太差了。
用if-else凑出来的很呆,偶尔能够按我的想法打出不错的连招,但是绝大多数时候一动不动,或许可以设置一个固定的行为模式。一套打完再开另一套,有自动转向机制,不至于很呆。
改成了双人的,效果很好。
加了一些音效和bgm。
也许,可以初步完工了!!!!
后面修改一下飞天的bug,改一下双人的键位,把2p的键位弄好,有时间有闲心可以多写几个地图。
4503行,有效代码3839行,算是迄今为止自己写的最大的工程了。(面向GPT搓的代码统计小工具,函数统计结果是错的)
12.14
加点地图,做个选地图界面,游戏结束的字体改小一点点。
把键位bug修了,选人界面改成可以选相同角色,黄框1P选,蓝框2P选,2P的角色渲染粉红一点
下午三点半,全部完成。收工!
录视频,粉饰视频,写报告。
12.15
完工!