事件 ID
【超长章节预警,本章分分页式与一页式两节】
事件 ID(分页式)
我们想要做的音游经过多次试错,修改方案,最终终于敲定使用 “触发条件:并行处理(获取指定位置的信息)” 的形式进行制作。可喜可贺可喜可贺!让我们来看看现在的画面布置是怎么样的吧。(为了使画面简洁,我把我原本地图上表示区域的指示牌删掉了)
示意图
音符:就是音符(note);
音符驱动器:告诉每一个音符怎么运动,是要快还是慢;是要直直走还是上蹿下跳(左右横跳)。最好是一列音符放一个,(相当是一个小节?),专门只控制这一列的音符(编辑器里也不会写太多,太难找),方便制作者调整。一列音符运动完就换下一个音符驱动器;
音游启动器:玩家走到上面按下 确定键 开始音游。同时换新的事件页并行处理,玩家移动路线等待,以此来阻止玩家在音游中移动影响音游;
音符位置读取器:其实应该叫做音符 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,音符位置读取器 关闭,阻拦器 取消对玩家的移动限制;
- 玩家可以查看游戏得分。
了解完游戏进程(至少有个设计思路),我们就可以对我们的事件进行编写了。
音游启动器
用于启动音游
其实 音游启动器 只有第一个事件页有干事情,后面都在摸鱼。原本打算让它限制玩家移动,可惜它干不了这活……
注意,最后一页的 出现条件 里的变量 音游阶段 >=2,是因为我测试的时候,只做了(column=)1 列音符,所以最后要表明这个音游结束了就得是变量 音游阶段 = column+1(==2)(音符列数加一)
音符位置读取器
用于读取经过判定点前中后的事件ID
当一个读取点上的事件多于一个的时候,它只会告诉你 ID 比较大的那个。
最后一页结束的出现条件跟 音游启动器 一样,都使变量 音游阶段 = 音符列数 +1。
阻拦器
它们其实没啥工作的实质性内容,单纯只是为了阻碍玩家的移动,避免影响音游。它们的出现时候的出现条件以及消失时候的出现条件都和 音符位置读取器 一样。
音符驱动器
驱动音符运动
排号,等到变量 音游阶段 到了自己负责的序号的时候,就驱动音符运动;等自己的负责序号过了之后,就暂停工作;它的第一页里的 设置移动路线 部分就是按照你想要的意思移动每一个音符的移动路线。
注意,最好不要在移动路线里的左下角选项那里给 等待完成 打勾,否则后面的音符都得等前面的音符运动完才可以动。但是有一个特例,那就是最后一列的 音符驱动器 控制的最后一个音符,这个音符就必须加上 等待完成,否则音游会在最后一列音符开始运动的时候结束。因为其实 音符驱动器 告知音符怎么运动都是一瞬间的事情,只要前面其他音符没有 等待完成,后面的音符都是可以和前面的音符几乎是同时获得指令运动。音符获得运动指令之后就不需要 音符驱动器 了。
另外,音符驱动器 需要操控音符达到的位置可以参考这个:(这里的是否分页,指的是音符事件内,判定音符是否操作成功的指令是否在同一个事件页内)
- 如果判断为分页式:音符驱动器让音符到达第一个触发点(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 的图块时,将它们往前移动半格就行。
实际判定点所处位置
思考时曾经尝试的老方案
思考时曾经尝试的老方案
一开始的思考方向是给所有有分歧条件判断开关 长按失败 里都加了关闭开关 长按失败。
老方案
可发现不在关闭开关 长按失败 前面加比较短的等待的话,如果 长按音序列 比较长,后续几个 长按音 都会因为太快关掉开关 长按失败,没能接收到这个开关关闭过的消息,导致它们还是依旧可以继续进行判定,所以我才在前面加了等待一帧。
只要保持着长按,后续的音符会错误地判断为成功
后来我才意识到 长按音·仲 完全不需要关闭开关 长按失败 啊,完全可以交给最为最后一个的 长按音·季 来关闭,所以有了现在的你们刚刚看到的在 spoilerblock 之外的方案。
事件 ID(一页式)
正如前面在 事件 ID(分页式)里所说的一样,一页式和分页式的主要差别在 音符 的事件里,它的判定方法是否有合为一页。
其它不一样的就是,音符驱动器 控制 音符 最远路线的差别:
- 如果判断为分页式:音符驱动器让音符到达第一个触发点(miss_previous)
- 如果判断为一页式:音符驱动器让音符到达最后一个触发点(miss_after)(这里的是否分页,指的是音符事件内,判定音符是否操作成功的指令是否在同一个事件页内)
这一小节是 事件 ID(一页式),就让我们看看如何把所有判定方法合为一页吧。
P.S. 前面说了那么多,图里也有注释,我就不额外在这里打注解了。另外这里只展示 单击音 的第一页,二三页就是常规的空白结算页(失败 / 成功)。因为其他的都和 事件 ID(分页式)的差不多,所以都不再展示。剩余其他的 音符 道理也差不多,根据 事件 ID(分页式)里对应的内容,再结合 单击音(一页式)就可以做出来了。
单击音
单击音(一页式)事件编辑器
未完待续……
最后一章将介绍 音符消失、Combo、 校准、音游刷新重置所有音符 等内容。
暂无关于此日志的评论。