输入判定
在本章中,您将会学习到:
- 什么是输入原型
- 如何设置原型输入
- 如何设置玩家输入结果
- 如何设置判定与连击 UI
输入原型
你也许已经注意到了,尽管我们的音符已经功能齐全了,但 Sonolus 仍然不会正常地处理它们: 你可以立即跳过整个关卡,并且在结果页面,所有的数据都会显示 0
。
为了让一个实体被 Sonolus 认为是可击打的音符,它的原型必须有输入。
class Note: public Archetype {
// ...
bool hasInput = true;
// ...
};
设置后:
- Sonolus 将会知道并会统计所有有输入的实体。
- 只有当所有有输入的实体全部销毁后,玩家才会被允许跳过剩下的关卡。
- 有输入的实体能够有权访问
EntityInput
区块,以告诉 Sonolus 玩家的表现情况。 - Sonolus 将会基于其输入结果自动计算例如分数,连击数,Perfect 判定数等的数据。
- 当有新的输入结果出现时,相关 UI 也会更新并播放。
- 特定桶的输入结果也会被用来在结果界面绘制判定图像。
输入结果
为了告诉 Sonolus 玩家在一个音符上的表现,我们只需要修改 EntityInput
区块即可。
对于 EntityInput
区块上的第 0
个值,表示判定结果。我们可以手动将其赋值为 0
(Miss),1
(Perfect),2
(Great) 或 3
(Good)。然而,更好的方法是直接使用 Judge
辅助函数。
对于 EntityInput
区块上的第 1
个值,表示输入偏差。我们应该直接将其赋值为以秒为单位的时间差。
class Note: public Archetype {
// ...
SonolusApi initialize() {
FUNCBEGIN
// ...
EntityInput.set(1, windows.maxGood);
return VOID;
}
SonolusApi touch() {
FUNCBEGIN
// ...
FOR (i, 0, touches.size, 1) {
// ...
EntityInput.set(0, Judge(
touches[i].st, targetTime,
windows.minPerfect, windows.maxPerfect,
windows.minGreat, windows.maxGreat,
windows.minGood, windows.maxGood
));
EntityInput.set(1, touches[i].st - targetTime);
// ...
} DONE
return VOID;
}
// ...
};
判定与连击 UI
为了玩家在游玩时有即时的反馈,有一个判定和连击 UI 也是很重要的。
我们可以在 Initialization 原型中设置它们:
class Initialization: public Archetype {
// ...
SonolusApi preprocess() {
FUNCBEGIN
// ...
// 判定指标参数
let judgmentX = 0;
let judgmentY = -0.4;
let judgmentWidth = 0 * ui.judgmentConfiguration.scale;
let judgmentHeight = 0.15 * ui.judgmentConfiguration.scale;
ui.judgment.set(
judgmentX, judgmentY,
0.5, 0,
judgmentWidth, judgmentHeight,
0,
ui.judgmentConfiguration.alpha,
HorizontalAlign.Center,
false
);
// 连击指标参数
let comboValueX = screen.r * 0.7;
let comboValueY = 0;
let comboValueWidth = 0 * ui.comboConfiguration.scale;
let comboValueHeight = 0.2 * ui.comboConfiguration.scale;
let comboTextX = screen.r * 0.7;
let comboTextY = 0;
let comboTextWidth = 0 * ui.comboConfiguration.scale;
let comboTextHeight = 0.12 * ui.comboConfiguration.scale;
ui.comboValue.set(
comboValueX, comboValueY,
0.5, 0,
comboValueWidth, comboValueHeight,
0,
ui.comboConfiguration.alpha,
HorizontalAlign.Center,
false
);
ui.comboText.set(
omboTextX, comboTextY,
0.5, 1,
comboTextWidth, comboTextHeight,
0,
ui.comboConfiguration.alpha,
HorizontalAlign.Center,
false
);
return VOID;
}
// ...
};
最后,让我们设置我们的判定与连击动画来它们变得更生动:
bool unused_configurationUI_unused = [](){
engineConfiguration.ui = {
// ...
judgmentAnimation: {
// ...
alpha: {
from: 1,
to: 0,
duration: 0.2,
ease: AnimationEase.OutCubic
}
},
comboAnimation: {
scale: {
from: 1.2,
to: 1,
duration: 0.2,
ease: AnimationEase.InCubic
},
// ...
},
// ...
};
return true;
}();
TIP
实际上,您可以不使用 Sonolus 提供的 UI,自行渲染 UI 也是可以的,并且这样做更能提升原作的还原度。
具体做法实在 Stage
原型中写入能够渲染 UI 的代码。
但是,Burrito(Sonolus 的开发者) 并不支持这种行为,因为它并不能为玩家提供高度的自定义功能,这违背了 Sonolus 设计的初衷。
因此,我们建议您在设计 UI 时,权衡 Sonolus 官方 UI 与自行渲染的利弊,根据自己的实际情况进行选择。
当然,更好的一种方案是在 /engine/configuration/options.cpp
加入是否使用 Sonolus 官方 UI 的选项,以此来达到一举两得的目的。