设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 4916|回复: 4
打印 上一主题 下一主题

[原创发布] 【玩坏MV】制作音游的思路过程

[复制链接]

Lv3.寻梦者

梦石
0
星屑
1502
在线时间
115 小时
注册时间
2020-5-10
帖子
82
跳转到指定楼层
1
发表于 2020-8-31 23:59:57 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有帐号?注册会员

x
本帖最后由 shmily0725 于 2020-10-23 10:45 编辑

前言
无所谓的前言


我已经有一段非常长的时间没有碰过MV了,所以需要一个项目来练练手,这个时候我想到或许可以MV来做音游。关于音游的插件我记得已经有了,我记得是MOG系列的?但是我还是想要用事件试着做一下,毕竟这样很多东西都可以自己设定(但是不会写插件,限制还是很大啊)

这个系列我想写的东西,有一些是很以前研究的,所以可能记不清花了多少时间。但是我还是想尽可能每次都记录一下每一个项目花的时间。这次研究大概花了将近20小时

P.S. 我看见帖子编辑器里有非常多的功能,我想试试,所以添加了个目录。不过在【保存草稿】的情况下,似乎分页是真的分页,在同一页里看不见其他页的内容。我原本的打算是想要在同一页里写所有东西,然后用目录进行页内跳转,方便读者查看







构思
每一次制作或者尝试一个项目,都需要首先进行构思,对你想要做的事情有个相对来说比较全面的设想,比如原理(也即项目的内容),画面布置,可能的实现方法等,方便后面进行尝试和调整



原理
这次我想做的是【音游】,它的【原理】就是:
  • 有一个物件(我们暂且称之为【音符】,我暂时懒得画,全部用引擎自带的【!Door2】里的漩涡来代替)从远处向【判定点】运动
  • 如果玩家在【音符】经过【判定点】的时候按下了【互动键】,那么判定玩家的此次操作成功,得分加一
  • 如果不是如同2所说的那样,玩家在【音符】经过【判定点】之前或者之后按下了【互动键】,或者干脆就没有按,则判定玩家此次操作失败,得分不变




画面布置
我的构思一开始是根据需要将画面分成三个区域:
  • 游戏区(玩家所能看见的部分。能看见运动向【判定点】的【音符】的区域,让玩家预判什么时候按【互动键】;同时起到判定是否成功的区域)
  • 准备区(所有本次音游会出现的【音符】都先存在这里,等到曲目播放到需要它们出现的时候,它们才运动到【游戏区】)
  • 弃置区(所有已经经过判定的音符,都必须离开【游戏区】,避免扰乱玩家视线以及影响【判定点】的判定)

    但是因为如果玩家能够看到的游戏画面只有【游戏区】,画面内容可能太空洞,而且也填不满画面,所以我参考了【节奏医生】的某些卡关,添加了一个新的区域
  • 舞台区(在这里可以放一些随着曲子而变化的动画,比如跳舞的小人(不是密码那个)


最后设计的画面布局如下(浅绿色为玩家可见区域,深绿色为玩家看不见的地方),【音符】一列列放置在【准备区】,到点了,它们就上号,一列列出发经过【游戏区】,最后到达【弃置区】停止运动


示意图


实现设想
我一开始的设想是抓取【音符】的x坐标和【判定点】的x坐标进行对比,如果刚好相等的同时玩家按下了【互动键】,则操作成功,反之失败

只抓取x坐标是因为音游里的【音符】经过【判定点】的时候,总是从【判定点】的同一个方向经过。比如我刚刚设计的那个画面,就是所有【音符】都是从【判定点】的右边穿过【判定点】,所以它们的y坐标一定一样

但这样会有一个问题,就是一个曲子里需要按到的【音符】是非常多的,这样一来就单纯抓取【音符】的x坐标就会占用过多的变量。而且如果【游戏区】上有多个【音符】,总不能按一下【互动键】就全部判定了吧,如果真的是这样,哪怕正在经过【判定点】的【音符】判定成功了,后续的【音符】却全部判定为失败,这样显然不合理。所以还需要有变量或者其他什么东西来判断当前需要判定的是哪个音符







触发条件:玩家接触/事件接触
这时候一个灵感从我脑海闪过,我为什么不试试【玩家接触】亦或者是【事件接触】呢?这样一来只要是接触了玩家的事件就是当前要判定的【音符】。当【音符】到达【判定点】(即玩家)的时候,如果玩家按下了【互动键】则操作成功加一分。但是这种实现的设想有至少两个比较明显的缺点:
  • 因为【判定点】(玩家)只有一个,所以只支持单轨道音游(比如【节奏医生】【冰与火之舞】,所有的【音符】都是用同一个【互动键】进行操作),不支持多轨道音游(比如【Deemo】【musedash】【LL】【劲舞团】,不同轨道上的【音符】需要对应不同的【互动键】进行操作)
  • 无法进行失败(miss)的判断,因为所有miss的判断,不管是在经过【判定点】之前还是之后,都是基于【判定点】之外的判断。在【音符】没有接触到玩家的时候,【玩家接触】【事件接触】都不起作用,无法进行判断。所以最后只能通过操作成功一次得一分,操作失败分数不变来判断成功了几次


所以我打算只做单轨道音游

因为许久没有接触RM,我已经不太记得【玩家接触】和【事件接触】的区别,我花了点时间进行测试,因为不明原因,此时我的MV出现了bug,【玩家接触】和【事件接触】变得没有区别,导致我浪费了非常多的时间在上面而且还变得非常困惑

bug


然后又是因为不明原因,MV变正常了,使得我通过测试能了解它们之间的区别以及其它各种细节:
  • 【玩家接触】:玩家主动接触事件,如果是事件来碰玩家则不会触发。如果优先级是【与人物相同】的话,触发是发生在事件与玩家相邻一格同时玩家面向事件的时候(同时如果事件还设了【穿透】,则通过走向(方向键)事件的方式无法触发,必须使用【确定键】);如果优先级是【在人物上/下方】的话,触发发生在事件与玩家处于同一格的时候
  • 【事件接触】:不管是哪方主动接触都可以触发。如果优先级是【与人物相同】的话,事件可以主动接触玩家来触发,位置在与玩家相邻一格的位置,没有朝向要求(如果同时事件还设了【穿透】,同样也是得通过【确定键】才能触发);如果优先级是【在人物上/下方】的话,事件无法主动触发,需要玩家去触碰事件才能触发,位置在同一格
  • 如果事件优先级不是【与人物相同】的话(即玩家和事件不在同一层),则无论是【玩家接触】还是【事件接触】的触发都是接触的那个瞬间触发,也就是说如果玩家和事件处于同一格只要过很小的一段时间,都无法达成触发条件,必须其中某一方离开另一方然后再在接触的瞬间才能触发
  • 【设置移动路线】会导致【玩家接触】和【事件接触】无效。相反,事件的【自主移动】不会使它们失效


这上面的内容我是经过了非常长的测试才搞明白,尤其3和4。因为我是先把我之前写得那个实现设想的内容做出来后再边测试边修改的,后来发现单独开个新地图来针对性地对每一种可能进行测试可能效率更高

经过了一部分测试后,我发现我一开始的实现设想并不能达成我的目的:(其实我已经记不太清我当时是怎么测试的了,因为是一个月前的事情了,而且当时的测试现场非常混乱)
我先做的是把【音符】的所有【移动路线】一次性做完,从【准备区】到【弃置区】,经过了几轮测试,我发现了第4点问题
然后我让【音符】通过【移动路线】移动到和玩家同一格或相邻一格的位置,发现了第3个问题。同时怎么送走【音符】也是个问题
又或者让【音符】通过【移动路线】移动到和玩家比较近的位置后改为【自主移动-接近】同时【自主移动】里的速度和频率调得和【移动路线】里的最终情况一样
... ...







触发条件:确定键
或许【接触】可以达成我想要实现的样子,但是经过了非常长的测试,出现了非常多的问题,我已经对这个方案失去了耐心,所以抛弃了这个方案。我开始尝试将【触发条件】改为【确定键】。但是【确定键】这个方案也出了非常多的问题,比如说:
  • 它的判定条件比较严格,必须玩家和事件都在格子上才能触发,如果其中某一方在移动,触发概率就会变小,哪怕理论上符合触发条件也可能出现按下【确定键】也没有触发的情况
  • 如果两个事件叠在了一起,事件ID比较大的那个,会导致事件ID比较小的那个无法达成【触发条件:确定键】的情况,即,就算触发条件符合,事件ID小的那个按下【确定键】也不会触发(事件编辑器左上角那个就是本事件的ID)

... ...


事件ID

在这期间我还测试了不少有趣的东西,比如说我中途试着把画面布局从“事件移动,玩家固定”改为“事件固定,玩家移动”的模式。不过这种模式下,【舞台区】可能就是一个巨大的问题,因为镜头一直随着玩家角色的移动而移动,【舞台区】的内容必须保持同样的移动


示意图

其实最后真正让我放弃【触发条件:确定键】的原因是:它虽然能做出【单击音】,但却无法做出【长按音】的效果。【触发条件:确定键】的触发是在你按下【确定键】的瞬间触发的,如果你一直按着【确定键】则没有任何效果
另外,由于该方案无法识别miss的情况,玩家可以一直不停地反复按【确定键】,那玩家甚至可以全部成功,那就失去了音游原本的意义







触发条件:并行处理(获取指定位置的信息)
这个时候我终于想起有一个东西叫做【区域ID】,我一直以为它在【变量操作】里,找了好一会才发现它在【获取指定位置的信息】里
我一开始的想法是抓取当前【音符】的x坐标和y坐标,代入到【获取指定位置的信息】里获取它下面地图的【区域ID】,以此来判断该【音符】到底走到哪里了,应该对应什么情况下的判定(【判定点】前,中还是后)


示意图(其中“H”为【判定点】)


单独测试画面(按F9实时查看变量)


并行处理,抓取【区域ID】,(变量名,抓取类型,抓取所选取坐标)



但是使用【区域ID】需要的变量还是太多了,经过研究后,我决定改用为【事件ID】,以此来抓取经过【判定点】的事件的ID(得知哪个事件需要进行判定)

注意,如果使用【获取指定位置的信息-事件ID】的时候,判定点的绘制绝对不可以使用事件来绘制,而应该直接用地图图块来绘制,避免事件对【音符】的【事件ID】抓取的影响


判定点的绘制


并行处理,抓取【事件ID】,(变量名,抓取类型,抓取所选取坐标)

这里解决了一个非常重要的问题,那就是可判定时长。在上面的【触发条件:确定键】里有一个很大的问题,就是玩家和事件都需要在格子里,由于其中一方一直在移动,导致这个可以触发的时长非常的短。但是我们换成【触发条件:并行处理】之后,这个时长被大大地延长了
这样一来,解决了非常多的问题,同时因为不需要玩家操控的这个角色参与(接触),所以也可以弄成多轨道音游







事件ID(分页式)
我们想要做的【音游】经过多次试错,修改方案,最终终于敲定使用【触发条件:并行处理(获取指定位置的信息)】的形式进行制作。可喜可贺可喜可贺!让我们来看看现在的画面布置是怎么样的吧(为了使画面简洁,我把我原本地图上表示区域的指示牌删掉了)


示意图

音符:就是音符
音符驱动器:告诉每一个音符怎么运动,是要快还是慢;是要直直走还是上蹿下跳(左右跳动)。最好是一列音符放一个,(相当是一个小节?),专门只控制这一列的音符(编辑器里也不会写太多,太难找),方便制作者调整。一列音符运动完就换下一个音符驱动器
音游启动器:玩家走到上面按下【确定键】开始音游。同时换新的事件页并行处理,玩家移动路线等待,以此来阻止玩家在音游中移动影响音游
音符位置读取器:其实应该叫做音符ID读取器,它能时时读取miss_previous,prefect,miss_after上的事件ID,以此来了解当前应该对哪一个音符(事件)进行判断
miss_previous:判定点前一格,如果玩家过早(也就是在这里)按下了互动键,则判定当前的音符失败
prefect:判定点,如果玩家在这里按下互动键,则判定当前的音符成功,加一分
miss_after:判定点后一格,如果玩家过了prefect(判定点)还没按下互动键(也就是到达了miss_after),则直接判定当前的音符失败
(也就是说,在miss_previous和prefect都需要检查玩家是否有按下互动键,但是在miss_after就不用了)
(其实我原本打算是读取事件ID的任务一起交给【音游启动器】,但是发现如果【音游启动器】一边担负着限制玩家移动的任务,一边又要读取事件ID,会导致游戏比较严重的掉帧,所以最后将【音符位置读取器】单独分了出来)


第一个音符是单击音,后四个是长按音。在音符移动过程中,可以随意调整速度以及上下位置来提高音游难度。其中红色为“未判定”,绿色为“成功”,蓝色为“失败”

之后我又发现,无论在【音游启动器】里让玩家等待多少帧,玩家都有一定几率可以移动。所以最后我干脆取消了“让玩家等待来限制玩家移动”的方式,改为“音游开始的时候玩家四方都出现与玩家相同优先级不可穿透的事件”以此来限制玩家移动


老方案


修改示意图







接下来让我们详细地看看具体是怎么设定的吧

为了使我的记录更加清晰,我打算从变量和开关开始下手,简化掉其中一些我比较累赘的思考历程


变量

音游阶段:你需要告诉游戏开始了,然后现在进行到那一个阶段,这个阶段指的不是小到针对每一个音符,而是用来控制【音符驱动器】,告诉游戏现在应该开启哪一个【音符驱动器】了。最后游戏结束了,也是通过这个变量来告诉游戏。总之我们的思路就是:将小的细节的东西(音符),交给一个比较大的东西(音符驱动器)来控制,最后我们只要统一管理这个比较大的东西就可以掌控全局了。有一个分级的概念
音游得分:只要有一个音符判定为成功就加一分,失败则分数不变,最后可以用来看成功了几个音符
miss_previous:判定点前一格上是否有音符(事件),有就读取其事件ID,没有则为0
prefect:判定点上是否有音符(事件),有就读取其事件ID,没有则为0
miss_after:判定点后一格上是否有音符(事件),有就读取其事件ID,没有则为0
combo:当前连击数
MAX combo:最大连击数


开关

长按失败:音游里有一些连起来的音符需要你整个过程长按互动键,一旦你中间松开了互动键,前面已经成功的音符不会收到影响,但是长按音中当前的音和后续的音都会直接判定为失败
combo:是否连击失败
校准(一个回合):校准用的音符是否从右到左走完了一个回合。后两个开关会在文章后面详细解释
开始校准:是否开始校准



这些变量和开关其实是和我们游戏进程的思路紧密相关的,现在我们来看看我们的游戏进程思路:


游戏进程示意图

  • 当我们在【音游启动器】上按【确定键】开始后,变量【音游阶段】+=1。【音游启动器】换新的事件页,对玩家使用等待,限制玩家移动
  • (【音游阶段】==1)【音符位置读取器】出现,开始读取miss_previous,prefect,miss_after上的事件ID
  • (【音游阶段】==1)第一列【音符驱动器】启动,开始移动音符
  • 判定点前中后发现有音符(事件)到达了,开始分别进行判定
  • 本列音符全部告知移动路径后,变量【音游阶段】+=1
  • 第一列【音符驱动器】打开独立开关A,结束它的使命(魔术师倒下)
  • (【音游阶段】==2)接下来一列的【音符驱动器】启动
  • ... ...
  • 最后一个【音游驱动器】完成任务,最后一个【音符】经过miss_after,【音游阶段】最后一次+=1,【音符位置读取器】关闭,【音游启动器】取消对玩家的移动限制
  • 玩家可以查看游戏得分








了解完游戏进程(至少有个设计思路),我们就可以对我们的事件进行编写了

首先有请我们的【音游启动器】选手


名字:音游启动器
年龄:12周岁
个性:低调奢华不张扬
种族:魔法阵
喜好:红色蜡笔;《深入理解计算机系统》(机械工业出版社)
工作:启动音游

工作档案:




评价:
其实【音游启动器】只有第一个事件页有干事情,后面都在摸鱼。原本打算让它限制玩家移动,可惜它干不了这活。但老板不在意,就一直让它这么呆下去了
注意,最后一页的【出现条件】里的变量【音游阶段】>=2,是因为我测试的时候,只做了(column=)1列音符,所以最后要表明这个音游结束了就得是变量【音游阶段】=column+1(==2)(音符列数加一)



接下来欢迎【音符位置读取器】的到来


名字:音符位置读取器(酱)
年龄:秘密
性格:表面是三无少女,实际上用脑电波一直在说个不停
种族:读取器(这里不是让你填兼职啦)
爱好:这跟喜好有什么不同吗
工作:读取经过判定点前中后的事件ID(不想干了啊,过于枯燥)

工作档案:



评价:
虽然看起来非常的叛逆,但实际上哪怕只是中途才突然拉过来干活的,工作也是很勤勤恳恳(并不是反差萌)。不善言语,沉默寡言,但心理的话已经多得溢出来了,用文字代替话语进行交流的时候可能会变毒舌,但更多的是无厘头的俏皮话
当一个读取点上的事件多于一个的时候,它只会告诉你ID比较大的那个
最后一页结束的出现条件跟【音游启动器】一样,都是变量【音游阶段】=音符列数+1



紧跟而来的是【阻碍器】


名字:阻碍器
年龄:how much it is
性格:that will be 18 dollar
种族:here you go, keep the change. hi, doggy
爱好:you are my favorite customer
工作:thanks a lot, bye

工作档案:
you are lying, i never hit you. you are tearing me apart, Lisa

评价:
它们其实没啥工作的实质性内容,单纯只是为了阻碍玩家的移动,避免影响音游。它们的出现时候的出现条件以及消失时候的出现条件都和【音符位置读取器】一样,因为它们大都是【音符位置读取器】的分身,其中只有一个是【音符位置读取器】的双胞胎妹妹



战神一声令下,【音符驱动器】也出现了


名字:音符驱动器
年龄:9 3/4
性格:捉摸不透
种族:麻瓜魔法师
爱好:Ridikuius
工作:驱动音符运动

工作档案:



评价:
排号,等到变量【音游阶段】到了自己负责的序号的时候,就驱动音符运动。Mobiliarbus!
等自己的负责序号过了之后,就趴在地上装死。其实是为了给后面的【音符驱动器】好的视野。Stupefy!
它【工作档案】里的第一页里的【设置移动路线】部分不用细看,就是按照你想要的意思移动每一个音符的移动路线
注意,最好不要在移动路线里的左下角选项那里给【等待完成】打勾,否则你后面的音符都得等前面的音符运动完才可以动
但是有一个特例,那就是最后一列的【音符驱动器】控制的最后一个音符,这个音符就必须加上【等待完成】,否则音游会在最后一列音符开始运动的时候结束。因为其实【音符驱动器】告知音符怎么运动都是一瞬间的事情,只要前面其他音符没有【等待完成】,后面的音符都是可以和前面的音符几乎是同时获得指令运动。音符获得运动指令之后就不需要【音符驱动器】了

另外,【音符驱动器】需要操控音符达到的位置可以参考这个:
如果判断为分页式:音符驱动器让音符到达第一个触发点(miss_previous)
如果判断为一页式:音符驱动器让音符到达最后一个触发点(miss_after)
(这里的是否分页,指的是音符事件内,判定音符是否操作成功的指令是否在同一个事件页内)


驱动所到达的最终位置示意图

其中左图为分页式。它的第一页为等待音符到达判定点,二三四页为判定页(分别对应miss_previous,prefect,miss_after),最后五六页为显示成功与否图像且不再参与任何判定的事件页(失败,成功)
而右图为一页式。它的第一页融合了所有的判定,第二三页为显示成功与否图像且不再参与任何判定的事件页(失败,成功)

为什么不同形式(分页式/一页式)的【音符】需要【音符驱动器】驱动到的最后位置不一样呢?
这是因为,事件之前接收的【移动路线】,一旦在这个事件更换事件页就会立马失效
在分页式的情况下,它到达miss_previous就需要从第一页换到第二个事件页,这时候之前哪怕【音符驱动器】给它下再多的【移动路线】命令都没有用,只要之后再没有后续新的【移动路线】指令,它就会停下来(不只是影响到自身的移动,甚至会影响到后续其他音符的判定)
而一页式的情况中,它在判定点前中后都不换页,直到到miss_after才换页到最后两页显示成功与否图像,所以【音符驱动器】必须驱动它达到的最后位置就是miss_after
当然,你在【音符驱动器】里可以写非常长的【移动路线】甚至是超过所需的内容,只要你到达了我上面所说的两种情况分别所需达到的点就行,只是后面的内容都不会应用。所以这里我说的就是最精简的模式
如果这部分你单纯看这里的文字看不懂,可以看接下来【音符】部分的具体表现,再来结合这段文字,(最好有实际操作测试),可能更能明白我这里在说啥



最后出场的就是压轴的【音符】,它们分别有【单击音】,【长按音序列】(【长按音序列】包括【长按音·伯】(开头第一个)【长按音·仲】(中间部分)【长按音·季】(最后一个))

强烈建议其他所有事件都建完了,最后再来建【音符】,以达到它们的事件ID都是连续的目的
另外,建议在一个新的地图把每四种【音符】的模板都设定好了,然后再直接复制进你制作音游的那个地图,可以极大的提高效率
所以最好的制作方案,就是你一开始就在选择音乐/制作音乐的时候就选好所有节拍点(音符),并确定它们的类型
否则因为事件ID的连续性,后期要改可能比较麻烦(但其实这并不是死规定,不一定要完全连续,只是后面的音符的事件ID一定要比前面的大就行。连续只是为了容易读以及好看)


名字:单击音


单击音(分页式)的第一页

  • 它在这一页中是被【音符驱动器】驱动着运动,等待到达miss_previous,自身不做任何事情
  • 这里我勾选了【固定朝向】是因为如果不固定朝向,在【!Door2】里红色漩涡向左运动会变成另一种颜色。如果是自制音符就不需要在意这一点
  • 另外我还勾选了【穿透】。这是因为我考虑到了有一些音游里的音符是有出现在运动的途中,后面的音符超过前面的音符的情况(我的印象中,【musedash】的【milk】曲子里就有类似情况),当然,在这种情况下,后面的音符的事件ID需要小于前面的音符的事件ID。哪个音符的事件ID更小,是要看哪个先到达判定点



单击音(分页式)第二页

  • 它在这一页中达到了miss_previous的位置,开始第一轮判断,看玩家是否提前按下了互动键(确定键),造成了失败。如果玩家这个时候没有按下互动键,则进入下一个阶段
  • 本页的【出现条件】就是当miss_previous那个位置读取到本音符的事件ID,所以把本音符事件ID填进去
  • 这里需要注意的是:从这一页开始往后,【自主移动】部分的设定都要和该【音符】在【音符驱动器】里最后的速度,频率状态相同,(或者你在该页的【移动路线】里设置为相同),否则在判定点附近音符突然变速会扰乱玩家对音符运动的判断,极大地破坏游戏体验
  • 还有,这里往后三页就都是我们前面提到的【触发条件:并行处理(获取指定位置的信息)】,记得都设定好。优先级那里,因为没有玩家的参与,设置什么都无所谓
  • 另外,就如图里的注释写得那样。因为事件页变了,之前所有接受到的【移动路线】都被取消了。这个时候只能靠音符自身事件里所带的【移动路线】继续推进移动,每换一次事件页就至少推动一次,所以这里写了“传递”。(传递的推进【移动路线】是图里“如果[确定]正被按着(分歧条件)”上面那一个。我原本是把“传递”写在分歧条件的后面的,发现不起效,所以改写在了前面,然后就起效了)
  • 分歧条件里的内容就是本页的重点,如果玩家在本音符经过miss_previous的任意一瞬间按下了【确定键】(过早操作,miss),则判定为失败。打开独立开关A(跳转到第五个事件页,显示失败图像),同时将音符移到【弃置区】,避免影响其他音符的判定
  • 分歧条件里的【独立开关】一定要在【移动路线】之前,否则【移动路线】会失效。即,我们的目的是先换事件页,之后再移动到【弃置区】。之所以这么做,是因为我们不想在结算页面(成功/失败)使用【触发条件:确定键】之外的触发条件,尤其是【触发条件:并行处理】,这样才不会占用太多电脑资源。可是如果结算页面是【触发条件:确定键】,意味着你不去它面前按【确定键】,它是不会执行事件页内的指令的,所以不能把将本【音符】移动到【弃置区】的指令放在结算页面。这样一来,我们就只能放在跳转前的那个事件页的跳转那个点(打开独立开关)紧接着的地方



单击音(分页式)第三页

  • 它在这一页中到达了prefect的位置,开始第二轮判断,如果玩家这个时候按下了【确定键】,则成功,同时得分加一。如果玩家没有按下【确定键】,则进入下一个阶段
  • 本页的【出现条件】是当prefect那个位置读取到了本音符的事件ID,所以把本音符事件ID填进去
  • “传递”写在分歧条件之前
  • 如果玩家在本音符经过prefect的任意瞬间按下了【确定键】,则判定为成功。变量【音游得分】+=1,打开独立开关B(跳转到第六个事件页,显示成功图像),同时将音符移到【弃置区】



单击音(分页式)第四页

  • 它在这一页中到达了miss_after的位置,开始第三轮判断(其实并没有)。因为玩家在此之前并没有对该音符进行任何操作,所以已经无力回天了,无论如何都会被判定为失败
  • 本页的【出现条件】是当miss_after那个位置读取到了本音符的事件ID,所以把本音符事件ID填进去
  • 打开独立开关A(跳转到第五个事件页,显示失败图像),同时将音符移到【弃置区】



单击音(分页式)第五页

  • 本页为失败图像页,记得把图像改为失败时候的图像
  • 不进行任何额外的操作
  • 记得后两个事件页因为都要进入【弃置区】,【弃置区】最后会堆一堆【音符】,【音符】不会凭空消失,所以都需要打开【穿透】



单击音(分页式)第六页

  • 本页为成功图像页,记得把图像改为成功时候的图像
  • 不进行任何额外的操作
  • 记得后两个事件页因为都要进入【弃置区】,【弃置区】最后会堆一堆【音符】,【音符】不会凭空消失,所以都需要打开【穿透】





名字:长按音·伯


长按音·伯(分页式)第一页

  • 它在这一页中是被【音符驱动器】驱动着运动,等待到达miss_previous,自身不做任何事情



长按音·伯(分页式)第二页

  • 长按音符的第一个音符到达了miss_previous的位置,将其事件ID填入【出现条件】中
  • “传递”写在分歧条件前
  • 其他地方都和【单击音】的第二页一样,这里只需要再在分歧条件里加上打开开关【长按失败】,告诉本长按音序列的后续音符本长按音序列已经失败了。后续的长按音就会直接变为失败。打开独立开关A(跳转至第五页,变为失败图像),移入【弃置区】



长按音·伯(分页式)第三页

  • 跟【单击音】第三个事件页一模一样,变量【音游得分】+=1,不再累述



长按音·伯(分页式)第四页

  • 其他的跟【单击音】第四页一模一样。唯一不一样的是还要再打开开关【长按失败】,告诉本长按音序列的后续音符本长按音序列已经失败了。后续的长按音就会直接变为失败。打开独立开关A(跳转至第五页,变为失败图像),移入【弃置区】



长按音·伯(分页式)第五页

  • 跟【单击音】第五页一样



长按音·伯(分页式)第六页

  • 跟【单击音】第六页一样





名字:长按音·仲


长按音·仲(分页式)第一页

  • 好吧,所有分页式的音符第一页都是一样,空白的



长按音·仲(分页式)第二页

  • 第二页是当【长按音序列】的【长按音·伯】到达了miss_previous开始的,所以它的【出现条件】是变量【miss_previous】>=【长按音·伯】的事件ID
  • 第二页的目的是为了看本【长按音序列】内的前面部分是否有失败的,有的话,本音符直接也同样算为失败。即,如果前面有【音符】失败,就会打开开关【长按失败】,后续【音符】读取到开关【长安失败】打开了,就打开独立开关A(跳转至第五页,变为失败图像),同时移动到【弃置区】
  • “传递”在分歧条件之上
  • 退出/移除移动路线(移动至【弃置区】)参考【长按音·伯】如果在miss_previous就失败,本【音符】所处位置的情况(最大距离),取消等待,打开跳过



长按音·仲(分页式)第三页

  • 本音符达到了prefect的位置,【出现条件】那里填上变量【prefect】>=本音符的事件ID
  • 注意,将本页的图像改为成功时候的图像。这样一来,一是和之前“未判定”时的图像形成了差异,告诉玩家本【音符】已经达到prefect这个【判定点】了;二是告诉玩家,到目前为止玩家的操作都是成功的(保持长按),如果玩家中途松了手,本【音符】就会立马变成失败图像,形成对比
  • “传递”在分歧条件之上
  • 因为这个是【长按音】,所以中途任意时刻都不可以松手,因此我们需要在分歧条件里开启“创建条件不满足时候的分支”来判断玩家是否有松过手。因为是【并行处理】,所以它会一直不停地循环对分歧条件进行判断
  • 如果玩家中途有松手,则打开开关【长按失败】,同时打开独立开关A,将已经更改为失败图像的本【音符】移出【游戏区】



长按音·仲(分页式)第四页

  • 本页是本【音符】到达miss_after而切的事件页,所以【出现条件】填变量【miss_after】>=本音符的事件ID
  • 和上一个事件页一样,保持着成功的图像
  • 与前面的【单击音】和【长按音·伯】恰恰相反,如果【长按音·仲】达到了miss_after却还没有因为判定而结算(变成成功/失败图像),说明【长按音·仲】在前面的操作都是成功的,所以应该变量【音游得分】+=1,打开独立开关B,移动到【弃置区】



长按音·仲(分页式)第五页

  • 所有的失败事件页都是一样的,不再累述



长按音·仲(分页式)第六页

  • 所有的成功事件页都是一样的,不再累述





名字:长按音·季


长按音·季(分页式)第一页

  • 空白页



长按音·季(分页式)第二页

  • 跟【长按音·仲】第二页无他样
  • 唯一的区别,是在分歧条件里多加了一个关闭开关【长按失败】。以确保后续的【长按音序列】可以再次用同样的方法使用这个开关



长按音·季(分页式)第三页

  • 跟【长按音·仲】第三页道理类似
  • 唯一区别就是如果中途松手了,不需要再打开开关【长按失败】了,因为本【长按序列】没有后续其他【音符】,所以并没有告知后续【音符】失败的必要



长按音·季(分页式)第四页

  • 跟【长按音·仲】第四页内容完全一致



长按音·季(分页式)第五页

  • 失败事件页



长按音·季(分页式)第六页

  • 成功事件页




完成了上述内容,一个既有【单击音】又有【长按音】音游的基础设定就完成了,你就可以依照前面的模板完成一个完整的音游。另外要注意的是,经过反复测试,本方案目前的所有判定点在实际操作中都会往前半格,这并不是什么大的问题,你只要在制作以及绘制【miss_previous】【prefect】【miss_after】的图块时,将它们往前移动半格就行


实际判定点所处位置



附录(关于何时关闭开关【长按失败】)




事件ID(一页式)
正如前面在【事件ID(分页式)】里所说的一样,一页式和分页式的主要差别在【音符】的事件里,它的判定方法是否有合为一页

其它不一样的就是,【音符驱动器】控制【音符】最远路线的差别:
如果判断为分页式:音符驱动器让音符到达第一个触发点(miss_previous)
如果判断为一页式:音符驱动器让音符到达最后一个触发点(miss_after)
(这里的是否分页,指的是音符事件内,判定音符是否操作成功的指令是否在同一个事件页内)

这一小节是【事件ID(一页式)】,就让我们看看如何把所有判定方法合为一页吧

P.S. 因为前面说了那么多,图里也有注释,所以我就不额外在这里打注解了。另外这里只展示【单击音】的第一页,二三页就是常规的空白结算页(失败/成功)。因为其他的都和【事件ID(分页式)】的差不多,所以都不再展示。剩余其他的【音符】道理也差不多,根据【事件ID(分页式)】里对应的内容,再结合【单击音(一页式)】就可以做出来了。(本来就啰哩八嗦,再说下去就没完没了了)

单击音(一页式)

单击音(一页式)事件编辑器



其他内容(消失&combo&校准&音游重置)

消失
在一般的音游里
如果是【单击音】,一旦经过判定,就会显示判定结果图像,然后立马消失,以免影响玩家的注意力
而如果是【长按音】,则会在成功的时候保持成功的图像,不会消失;而失败的时候更改为失败的图像,同时不透明度大幅度降低
要做出这种效果非常简单,只要在控制【音符】退出到【弃置区】的那个【移动路线】开头加上【开启透明状态】,或者【不透明度:100】
跟在【事件ID(分页式)】里【单击音(分页式)第二页】的最后一点所说的一样,因为我们是先打开【独立开关】,再【设置移动路线】,所以所有【音符】都会先闪一下结算图像,然后再【开启透明状态】或者【不透明度:100】

这里一样也只提供【单击音(一页式)】的第一页,其他【音符】的道理一样一样


单击音(一页式)外加判定后消失效果

这时候我们会发现,不管成功与否,【音符】都是在原本设定的【miss_previous】【prefect】【miss_after】的位置消失(而不是提前半格)
我猜测这是因为【读取指定位置的信息】(数据向)是读取事件的中心点所在位置,所以只要【音符】的中心点过了格子的边界,它就算是在另一个格子里了
而无论怎么样,【移动路线】(移动向)都是整一格整一格地完成的,所以哪怕它换了事件页,由于之走到了格子与格子的中间,哪怕它之前的【移动路线】的失效了,但它还是要把当前这半格走完
所以这之间的差异会导致结算图像显示的比较久,而没有达到闪一下的目的,不过不那么纠结的话,目前的方案也无伤大雅


单击音成功


单击音失败


长按音_previous


长按音_prefect


长按音_prefect_interrupt


长按音_after

这里如果是【长按音_after】出问题了应该比较好理解(比如【长按音·伯】后面的【长按音·仲】更换失败图像慢了一拍),因为【长按音·伯】到达【miss_after】打开开关【长按失败】的同时,跟它相邻的那个【长按音·仲】也刚好到达了【prefect】换了事件页,而【长按音·仲】的【prefect】事件页并不包括对开关【长按失败】的判断,按道理来说相邻的【长按音·仲】如果此时按紧了【确定键】是不会失败的。可能是因为要【长按音·仲】进入【prefect】的瞬间才按紧【确定键】的操作太过于极限了,所以才可以不考虑这种情况会出现。实在担心这种情况的发生,你可以在【长按音·仲】的【prefect】事件页加入对于开关【长按失败】的判断



combo
因为我测试用的图里音符只有5个很少,所以一开始我设定是音游开始就显示combo,音游结束就关闭combo的显示。这时候只需要设定combo的出现条件是变量【音游阶段】>=1就行


一开始combo出现条件的设定

但现在到了码字的时候,我突然意识到,正常combo的出现是需要玩家连击到一定程度才会显示的,比如有些游戏需要连击3次或者5次才会出现。单纯一次音符判定成功并不能称之为combo,至少也要有两个吧。所以现在combo的出现条件改为变量【combo】>=2

有关于combo的变量/开关有以下三个:
combo失败(开关):用以告诉游戏连击失败了
combo(变量):记录当前的连击数
MAX combo(变量):记录目前为止最大的连击数

前两个需要在各个【音符】里进行额外的设定

其中,变量【combo】的设定比较简单,因为变量【combo】的增加往往意味着得分,所有【音符】事件里只要出现了“变量操作:音游得分+=1”的部分,后面直接加上“变量操作:combo+=1”就行


变量【combo】的设定

开关【combo失败】恰恰和变量【combo】完全相反。变量【combo】是在所有成功的地方出现;而【combo失败】却并不需要在所有失败的地方出现,它只要出现在【单击音】以及【长按音·季】就行,因为【长按音序列】前面任意音符失败都会打开开关【长按失败】从而导致后面的音符一起失败,所以【长按音序列】里的开关【combo失败】只要根据最后的【长按音·季】失败而变化就行。打开开关【combo失败】请设定在对应的打开独立开关A(音符失败)前面





【单击音】以及【长按音·季】里添加“开关操作:combo失败 = on”的位置

最后一个变量【MAX combo】主要由【最大连击数修改器】操作,我把显示图片【combo】的第一个事件设为【最大连击数修改器】


左上角第一个就是【最大连击数修改器】,第二行是显示【combo】的事件





【最大连击数修改器】事件页展示



用以展示combo这个词的事件,跟【最大连击数修改器】的出现/消失条件相同

之后就是本部分最重要的如何显示连击数的具体实现方式。其实最好的实现方式果然还是使用插件,因为变量【combo】是一个实时变化的量,而RMMV自带的【显示文字】会阻碍玩家的操作,这让实时显示并改变文字内容的难度大大提升了。但我们这里的目标是尽量不使用插件,所以让我们尝试看看如何仅使用事件的情况下如何实时显示变量【combo】

其实我使用的方法非常笨拙。将官方自带的【img-system-Damage.png】里的数字取出来做成行走图。然后并行处理,穷举所有可能出现的情况,用【分歧条件】判断当前位数的数字,然后用【设置移动路线】来实时更改要显示的数字图像(存放在【img-characters】里)


【number_1.png】和【number_2.png】

正是因为一首正常的音游曲目少说都有几十上百个音符,我们不可能把所有可能出现的数字都一个个画出来,所以我们要把变量【combo】里的各个位数上的数字提取出来,降为只剩0~9这十个数字的工作量。提取的方法并不难,只要简单的混用除法和取模这两种运算方法就行

我们还要意识到一点,虽然测试时用F9打开【开关/变量查看器】,可以实时查看开关/变量,里面的变量都是以整数形式显示,但实际上储存的变量都是浮点数。所以这个时候直接用【分歧条件】判断它们是否为0~9这十个整数中的任意一个,将不会成功。我们需要将除法/取模后的数字整数化后再进行判断




我们可以通过【显示文字】的方式验证确实是“以浮点数的方式存储变量”

根据前面的探讨,我们可以得出各个位数的写法:
个位:单纯使用取模就行。$gameVariables.value(x)%10
中间位数:混用除法和取模,最后取整。parseInt($gameVariables.value(x)/10^(n-1))%10
最大位数:单纯使用除法,最后取整。parseInt($gameVariables.value(x)/10^(n-1))

解释
  • "%"是取模的符号,"/"是除法的符号
  • $gameVariables.value()是【读取变量】的函数。中间的"x"指的是读取第x个变量
  • parseInt()是取整变量,它不管小数的情况,通过直接舍弃小数点后面的数字的方式进行取整。(感觉跟向下取整好像)
  • "n"指的是当前的位数,比如个位为"1",十位为"2",百位为"3",以此类推


这里我们暂且只设一个三位数字,读取的是第18个变量【combo】的值,所以具体写法如下
个位:$gameVariables.value(18)%10
十位:parseInt($gameVariables.value(18)/10)%10
百位:parseInt($gameVariables.value(18)/100)

这里我们仅用【连击数(十位)】作为例子,来看看连击数的显示事件该如何写,其他的写法一模一样




【连击数(十位)】事件页和【设置移动路线】

  • 用【分歧条件】判断当前位数是什么数字
  • 用【设置移动路线】更改图像
  • 【设置移动路线】要选择【本事件】
  • 记得【设置移动路线】要同时勾上【无法移动时跳过指令】和【等待完成】。如果不勾上的话,连击失败了,图像不会消失;甚至游戏结束了,部分图像也不会消失。这很可能是RMMV的bug,不过也可能是我思维上哪里出了错误。但即使是这么做了,大多数情况还是能正常地消去图片,少数情况图片还是会残留,尤其是长按音_prefect_interrupt的情况(全连也有概率会出现bug)



正常。连击数大于2时,combo出现;音游结束,combo消失


正常。连击中途失败,combo消失


出错。全连,音游结束,连击数部分数字没有正常消失(比较奇怪的是,只有百位会出现这种情况。但是三个位数设定其实是几乎一样的)


出错。连击中途失败,combo无法正常消失;音游结束,combo正常消失

后来我突然想到,我其实没必要在显示【combo】事件的判断页预设图像为“0”,设成无图像会不会比较好一点。实际尝试后,发现并没有什么区别

为了修正“音游结束,连击数部分数字没有正常消失”的bug,可以将原事件的最后一个空白页(音游结束)后面再加一个空白页,进行多一次图像刷新。这可以极大地避免该bug的出现


通过最后再增加一个无图像空白事件页来避免bug的出现

至于“连击中途失败,连击数部分数字没有正常消失”的bug,我尝试在显示【combo】的事件里在开头加一个无图像空白页。经测试,这个bug出现概率大幅度降低了,但还是偶尔会出现,尤其随着音游重置(后面会讲)次数增多,bug出现的概率也相应增大


显示【combo】事件的首页添加一个无图像空白页降低出现bug概率

或许可以学习前面的“增加空白页,多一次图像刷新”的方法。第一页的出现条件改为“【音游阶段】>=1”(音游开始),自动执行打开独立开关A;第二页出现条件是“独立开关A = on”,空白页;第三页就是判断页,在原有基础上增加一个关闭独立开关A

由于前面显示【combo】事件经过了多次修改,我这里再全部重新展示一次,以免混淆:






显示【combo】事件(以【连击数(百位)】为例)

经测试,在目前最新方案下,本章节前面提到的两个bug都不会再出现了。明明不出bug的话,只需要两个事件页,现在为了修复bug,不得不做成五个事件页



校准
校准一般在音游里指的是:“声音发声”与“音符到达prefect位置”这两个东西,做到画音同步。做这个的目的,一是不同设备可能会有些许画面和音效上的误差;二是不同玩家的反应时间不一样,玩家可以通过校准来获得最适合自己的设定

在我们的RM里,我们需要再新建一个地图,单独制作校准环节


校准地图示意图(蓝色为音符运动路线)

我的设计思路是这样的:首先设定一个默认的变量【校准】。然后如果玩家对预设的变量【校准】不满意的话,就去启动【校准启动器】,【校准启动器】会打开【音符驱动器】来驱动音符,每一轮(音符从右运动到左)结束后,【音符驱动器】会打开【音效播放器】来每一轮播放一次音效。(【校准启动器】(启动)→【音符驱动器】(驱动)→【音效播放器】(每一轮播放))

【音符驱动器】是里面非常重要的一零部件,我们先看这个


【音符驱动器】的事件页展示


示意图,其中蓝色为音符的移动路径

【音符驱动器】事件页里的变量【miss_after】并不是指的是【miss_after】那个位置上的事件ID,而是指的是音符运动路径的终点。我不想再增加一个变量,所以才借用。“如果:miss_after = 1”,这里的“1”就是音符的事件ID

我原本还把“音符经过判定点(prefect)颜色变绿,不在判定点时颜色恢复红色”的任务一并交给【音符驱动器】,但出现太多bug了。最后找到了一个简单的方法,根据情况更变事件页,让【音符】自己干这个任务了



【音符】的事件页展示

接着是【校准启动器】。我计划在【校准启动器】里设定变量【校准】的大小,然后在【音效播放器】前面插入等待“变量【校准】的值”的帧数,从而达到校准的目的

按理来说,这种调整是可以向前向后调整的,因为说不定对于一些玩家来说“声音响了,音符却还没到达判定点”;而另一些玩家可能发现“音符早就判定玩了,声音还没响”,所以变量【校准】是可以相对默认值上下调的。但是在RM里,如果你从未对一个变量进行过赋值,那么它的默认值是“0”;另外,RM的【数值输入处理】只支持正整数,所以变量【校准】的默认值一定要大于“0”才行。所以我最好是在校准前就先将变量【校准】改为正整数作为默认值(这样就算玩家不去碰【校准启动器】,一开始也是制作者设定的默认值),而且就改一次,之后就算重新打开游戏也不再次设定默认值,而是保存玩家的设定。据此,我的【校准启动器】设定如下:




【校准启动器】事件页展示

但实际测试的时候,发现虽然一般来说确实目前的状态是满足了我们的设想,但是偶尔还是会出bug,校准完后反而被改为了默认值


校准完后错误地被再次设为默认值

玩过RMMV的朋友应该知道,如果出现条件一样,优先度更高的是靠后的事件页。但是我猜测,它的运行逻辑还是从前到后地读取事件页,只是如果后面的事件页的出现条件达到了的话,就优先运行后面的。所以在我们上面的情况里,我们完成校准后退出了【校准启动器】的第三页。因为第一页是自动执行,所以它直接就把玩家校准完后的变量【校准】再次改为默认值。但问题是,我们已经打开过【校准启动器】的独立开关A,按理已经直接到第二页,不会再次执行第一面的内容才对。实际上也确实如我们所设想的一样,不应该执行第一个事件页,正常情况下校准完了还是玩家所设定的值,上面的情况出现概率比较小。虽然概率比较小,但终究还是bug,我们还是应该去修复它,所以简单地把赋予变量【校准】默认值的任务交给另一个事件,然后永远再也不触发这个事件。【校准启动器】只负责校准



进入校准地图首先自动执行的【设定默认值】

所以我的推荐是,设定默认值都独立出来,这样可以减少很多bug。


修改后的【校准启动器】

在【校准启动器】里,当我结束校准的时候,我重置了【音符】的位置,将它放在路径终点的前一格


示意图

一开始将【音符】设定在路径终点就是为了一开始就能打开开关【校准(一个回合)】,从而启动【音效播放器】。这个设定是没有问题的,开始校准后,【音符驱动器】立刻把【音符】移到了路径起点,同时打开开关【校准(一个回合)】。但是一旦我们校准完毕,【校准启动器】如果将【音符】重置在我们一开始设定的路径终点的位置的话,再次启动【校准启动器】的时候,【音符】直接向左驶去,而不再像第一次一样被【音符驱动器】搬到路径起点,开关【校准(一个回合)】也没有打开,一起都乱套了,即使设定上和一开始并没什么不同,这应该也是RM的bug。但是我们在校准完毕的时候,如果【校准启动器】将【音符】放在路径终点前一格的话,bug就被修复了,一切照常进行


错误的重启

最后是【音效播放器】


【音效播放器】事件页展示

为了让音效在每一轮(音符从右运动到左为一轮),(变量【校准】不变的情况下)同一个时间发出声音,我特意再设了一个开关【校准(一个回合)】。在【音符】到达运动路径终点然后被【音符驱动器】移动到运动路径的起点的同时打开开关【校准(一个回合)】,这样就能保证音效都是在每一轮的同一个时间点播放。另外,建议制作或者选择这个音效的时候,最好使用那种比较短促但不刺耳的音效,可以让玩家更加精确地把握音效发生的时刻

在【音效播放器】事件页里你可以看到我预设了24帧。这个24帧我叫它“预设等待值”,它加上变量【校准】的默认值(这个例子里是5帧),共29帧,这是制作者根据自己测试的情况,加在播放音效前的预设等待时长。因为【音符】从【准备区】运动到【判定点】需要时间,而歌曲的播放有可能是立刻播放;或者音频文件自身就有预留前置的没有任何声音的部分;也可能是音乐前面一部分你并不想设置任何音符,所以调整“开始播放的时间”和“等待【音符】运动到【判定点】的时间”之间的平衡很重要。这里我们就是在将它们开始时间调整为我们想要的样子

另外你也要记得,音游的每一个歌曲前面你也要加“预设等待值”


音游歌曲里的预设等待值

这样一来,音游的校准就做好了



音游重置
当我们玩完一次音游某一个曲目的时候,我们常常还是想再挑战一次的,这个时候就需要将这个曲目所有东西重置一遍,包括游戏的变量(除了变量【校准】),开关,音符的位置。音符的位置无需担心,你玩完音游移动到别的地图,然后再回到音游歌曲这个地图,因为是重新加载这个地图,所以所有事件的位置都会重新读取,事件就都回到一开始设定的位置。变量和大部分开关也不用多想,只要都设置为“0”,或者全部关闭就行。比较难解决的是独立开关,RM的事件编辑器并没有一个地方可以直接控制所有的独立开关。还好我们有合适的脚本可以解决。

全部独立开关关闭
$gameSelfSwitches.clear();
全部独立开关打开
$gameSelfSwitches.onChange();

不过比较可惜的是,这个脚本是针对所有的独立开关,意味着如果你执行这个脚本关闭所有独立开关之后,再次进入校准地图,变量【校准】将会被重置为默认值。所以我们最好还是再多加一个开关代替独立开关,专门来控制设定默认值(做游戏就是一步步让步和调整)


音游歌曲地图里,将玩家移动到校准地图的事件



校准地图里,更改后的设定默认值的事件




全过程预览



后记
其实经过这次开发尝试,做到最后最直观的感受还是 RMMV ,单纯事件的方式制作的话,并不是一个适合制作音游的引擎。虽然插件还是有不错的音游插件,就是自由度实在太小了。

另外现在使用的这个 MV 版本的 RM,它的帧数虽然说起来是根据秒计算(1/60 秒一帧),但实际上跟刷新频率有关,这既不方便制作者计算帧数;又因为不同机子的刷新频率不同而导致玩家游玩时和制作者制作时的情况大为不同,进而导致玩家游玩的画面和音乐有可能会有非常大的差异,非常影响游戏体验。最近新出的 MZ 版本据说更新了引擎内核的 pixi(pixi 由 V4 升级到 V5。游戏刷新机制由 V4 版本的 DOM API: requestAnimationFrame,改用为 PIXI.Application),应该能解决这样的问题。

码这篇文章的过程中发生了许多我意想不到的事情,也算是增加了一些经验值。



全文完



评分

参与人数 10+10 收起 理由
无渊林 + 1 精品文章
时间的旅人 + 1 精品文章
轉枝亞衣_rinn + 1 精品文章
beiduo + 1
秋水客 + 1 精品文章
1215498520 + 1 精品文章
开关关 + 1 这也太强了吧!
灯笼菜刀王 + 1 图文并茂赞一个
百万HP + 1 精品文章
白嫩白嫩的 + 1 666666

查看全部评分

"明るい夜"のために

Lv3.寻梦者

梦石
0
星屑
1502
在线时间
115 小时
注册时间
2020-5-10
帖子
82
2
 楼主| 发表于 2020-10-23 10:47:56 | 只看该作者
今天来补个后记,算是正式完结这篇文章
另外感谢在我想弃坑懒癌不想码字的时候
激励我的友人和读者
"明るい夜"のために
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
165
在线时间
66 小时
注册时间
2020-10-18
帖子
56
3
发表于 2020-10-24 23:44:11 | 只看该作者
好牛…太复杂了太多事情我看到头都大了
有接MZ的画师吗,需要古风的UI,行走图,图块,有的话论坛私信我。
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
953
在线时间
191 小时
注册时间
2017-10-30
帖子
29
4
发表于 2021-2-15 03:24:47 | 只看该作者
过于厉害
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
21
在线时间
2 小时
注册时间
2020-7-11
帖子
8
5
发表于 2021-7-12 19:58:14 | 只看该作者
好家伙,楼主NB(
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-4-27 02:09

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表