倍速
在本章中,您将会学习到:
- 倍速是什么
- 如何设置倍速变化
- 如何处理倍速变化
倍速
倍速是许多节奏游戏的一个普遍功能,其别名为 Soflan。在本章中,我们将要实现倍速功能,准确来说倍速就是让整个谱面变快/变慢。
由于倍速的流行,Sonolus 也提供了方便的函数来实现倍速。
倍速变化
就像 BPM 变化一样,Sonolus 也有一个针对倍速变化的特殊原型名以及针对倍速值的特殊原型数据名。让我们添加一系列的倍速变化到我们的测试关卡中:
class TimeScaleEntity: public LevelEntity {
public:
defineArchetypeName("#TIMESCALE_CHANGE");
defineLevelDataValueDetailed(beat, "#BEAT");
defineLevelDataValueDetailed(timeScale, "#TIMESCALE");
};
// ...
string fromTXT(string path, string timeScalePath) {
// ...
ifstream fin2(timeScalePath);
while (!fin2.eof()) {
double beat, value;
fin2 >> beat >> value; // 读取时间与倍速
TimeScaleEntity timeScale; // 定义一个 TimeScale 实体
timeScale.beat = beat;
timeScale.timeScale = value; // 修改实体数据
levelData.append(timeScale); // 插入该实体
}
fin2.close();
// ...
}
// ...
int main(int argc, char** argv) {
if (argc > 4) {
string txtPath = argv[1], dataPath = argv[2], timeScalePath = argv[4]; // 从命令行获取文件路径
string rawData = fromTXT(txtPath, timeScalePath); // 转换谱面为 json 格式
// ...
}
// ...
}
{
// ...
"level": {
// ...
"generate": "chart.txt timeScale.txt dist/LevelData"
// ...
}
}
新建 /timeScale.txt
文件,每一行两个数字,表示倍速变化的时间与倍速值。引擎编译后,Sonolus.h 会自动转换谱面并上传至服务器。
音符
为了对 Note
原型实现倍速功能,我们只需要简单地将所有渲染相关逻辑转换为使用倍速时间即可。
注意到我们并没有改变输入相关逻辑,因为倍速功能应该保持原始的视觉特征并且不应该影响到输入的处理方式。
class Note: public Archetype {
// ...
SonolusApi preprocess() {
FUNCBEGIN
// ...
maxVisualTime = TimeToScaledTime(targetTime);
// ...
return VOID;
}
// ...
SonolusApi shouldSpawn() { return times.scaled >= spawnTime; }
// ...
SonolusApi updateParallel() {
FUNCBEGIN
// ...
let y = Unlerp(minVisualTime, maxVisualTime, times.scaled);
// ...
return VOID;
}
};