SonolusHaniwa
  • 1. 概述
  • 2. ハニプレ
  • 3. ユメステ
  • 4. Stellarity
  • 5. Phigros
  • 首页

    • 1. 概述
  • 玩家

    • 2. 安装服务
    • 3. 配置文件标准
    • 4. 服务使用方法
  • 开发者

    • 5. 自定义搜索函数
    • 6. 自定义资源创建接口
    • 7. 插件开发标准
  • 其他

    • 8. 更新日志
    • 9. 关于 srp 资源包
  • 1. 搭建开发环境
  • 2. Sonolus 基础
  • 3. 配置项目信息
  • 4. 基本数据类型
  • 5. 函数与语句块
  • 6. 注意事项
  • 1. 游玩模式基础
  • 1. 概述
  • 2. ハニプレ
  • 3. ユメステ
  • 4. Stellarity
  • 5. Phigros
  • 首页

    • 1. 概述
  • 玩家

    • 2. 安装服务
    • 3. 配置文件标准
    • 4. 服务使用方法
  • 开发者

    • 5. 自定义搜索函数
    • 6. 自定义资源创建接口
    • 7. 插件开发标准
  • 其他

    • 8. 更新日志
    • 9. 关于 srp 资源包
  • 1. 搭建开发环境
  • 2. Sonolus 基础
  • 3. 配置项目信息
  • 4. 基本数据类型
  • 5. 函数与语句块
  • 6. 注意事项
  • 1. 游玩模式基础
  • 基础知识

    • 1. 搭建开发环境
    • 2. Sonolus 基础
    • 3. 配置项目信息
    • 4. 基本数据类型
    • 5. 函数与语句块
    • 6. 注意事项
  • 游玩模式

    • 1. 游玩模式基础

游玩模式基础

相关概念

游玩模式,顾名思义,就是可供玩家游玩的模式。

您可以使用以下指令来编译引擎的游玩模式:

./sonolus buildcpp play <name>

原型回调函数

原型定义

名为 *Order 的 double 型变量和返回值类型为 SonolusApi 的函数已在 Sonolus 基础 章节中讲解。以下代码中尾部含有注释的行以及 *Order 变量和 SonolusApi 函数是您需要特别注意的,除此之外的行您不需要了解,Sonolus.h 会自动处理他们。

class Archetype {
    public:
    int id = 0;

    VariablesArray<EntityMemoryId> &memory = EntityMemory;                      // 实体内存区块,使用 memory[i] 获取偏移为 i 的值。
    VariablesArray<EntitySharedMemoryId> &sharedMemory = EntitySharedMemory;    // 共享实体内存区块,使用 sharedMemory[i] 获取偏移为 i 的值。
    EntityInfoGroup &info = EntityInfo;                                         // 实体信息区块。
    EntityDespawnGroup &despawn = EntityDespawn;                                // 销毁实体区块,使用 despawn.despawn = 1 销毁实体。
    EntityInputGroup &input = EntityInput;                                      // 实体结果区块。

    public:
    ArchetypeLifeGroup life = ArchetypeLife[id];                                // 原型生命值区块,只能在 preprocess 函数中修改。

    string name = "Default Archetype";                                          // 原型名。
    bool hasInput = false;                                                      // 是否计入 combo。
    vector<pair<string, int> > imports;
    vector<string> exports;

    double preprocessOrder = 0;
    SonolusApi preprocess() { return 0; }

    double spawnOrderOrder = 0;
    SonolusApi spawnOrder() { return 0; }

    double shouldSpawnOrder = 0;
    SonolusApi shouldSpawn() { return 0; }

    double initializeOrder = 0;
    SonolusApi initialize() { return 0; }

    double updateSequentialOrder = 0;
    SonolusApi updateSequential() { return 0; }

    double touchOrder = 0;
    SonolusApi touch() { return 0; }

    double updateParallelOrder = 0;
    SonolusApi updateParallel() { return 0; }

    double terminateOrder = 0;
    SonolusApi terminate() { return 0; }
};

一个实体在整个生命周期中有且仅有三种状态: 未激活,已激活和已销毁。

preprocess

preprocess 回调函数将在关卡初始化时执行,其目的是为了修改部分区块数据(故 preprocess 回调函数拥有几乎最高的读写权限)。

spawnOrder

spawnOrder 回调函数将在关卡初始化时执行,其返回值将作为实体激活顺序。该值越小,意味着实体将会被更早激活,反之则会更晚激活。

实体激活顺序可在游戏暂停时的 Spawn Queue 中查看(需要在设置中开启调试模式)。

shouldSpawn

shouldSpawn 回调函数将在实体未激活前的每一更新周期执行,其返回值将作为是否激活实体的依据。该值为 true 时,意味着实体将在该更新周期被激活,并且后续更新周期中将不再调用该回调函数,反之实体将不会在该更新周期中激活。

实体激活状态可在游戏暂停时的 Spawn Queue 中查看(需要在设置中开启调试模式)。

当前已激活实体可在游戏暂停时的 Active Entities 中查看(需要在设置中开启调试模式)。

initialize

initialize 回调函数将在 shouldSpawn 返回值为 true 的更新周期执行,并且只会被调用一次,其目的是为了在实体激活前初始化相关变量。

updateSequential

updateSequential 回调函数将在实体激活时的每一更新周期执行,其目的是为了顺序更新实体变量或执行相关函数。

touch

touch 回调函数将在实体激活时有用户触摸的更新周期中执行,其目的是为了处理用户触摸信息。

用户触摸可在游戏暂停时的 Runtime Touch Array 中查看(需要在设置中开启调试模式)。

updateParallel

updateParallel 回调函数将在实体激活时的每一更新周期执行,其目的是为了平行更新实体变量或执行相关函数。

对于引擎开发者,您应该将大量非必要代码置于该回调函数而不是 updateSequential 回调函数以加快 Sonolus 的运行速度,从而提高运行帧率,提升用户体验。

terminate

terminate 回调函数将在 despawn.despawn 被设置为 true 的更新周期中执行,并且只会被调用一次,其目的是为了销毁或更新部分变量或执行部分操作。该回调函数运行完后,该实体将会被标记为已销毁。

调用顺序

除去 preprocess, spawnOrder 回调函数,剩余回调函数将按照本文介绍的顺序先后进行调用。

回调函数执行的伪代码如下(实际这并不是 Sonolus 的源代码):

int state = 0; // 0 为未激活, 1 为已激活, 2 为已销毁
void run() {
    switch (state) {
        case 0: {
            if (shouldSpawn()) {
                initialize();
                state = 1;
            }
        } break;
        case 1: {
            updateSequential();
            if (touchCount) touch();
            updateParallel();
        } break;
        case 2: {
            terminate();
        } break;
    }
}

样例

以下代码展示了原型的基本定义及使用方法。

class Test: public Archetype {
    public:

    string name = "Test Archetype"; // 原型名定义。
    bool hasInput = true;           // 是否计入 combo

    // 定义实体数据
    defineImportDetailed(beat, EngineArchetypeDataName.Beat);
    defineImport(lane);
    // 定义导出数据
    defineExport(result);
    defineExportDetailed(accuracy, EngineArchetypeDataName.Accuracy);
    // 定义原型内全局变量
    var a, b, c;
    // 定义实体共享变量
    var d = var(EntitySharedMemoryId, 0);
    var e = var(EntitySharedMemoryId, 1);

    double preprocessOrder = 0; // 定义回调函数顺序
    SonolusApi preprocess() {   // 回调函数
        // 使用实体数据
        var f = beat * lane;
        var g = beat / lane;
    }

    // ...

    // 当然也可以不指定回调函数顺序,其值默认为 0
    SonolusApi updateSequential() { // 回调函数
        // 导出实体数据
        var f = beat * lane;
        var g = beat / lane;
        ExportValue(result, f);
        ExportValue(accuracy, g);
    }
};

这只是一个最简单的原型样例,之后您将会逐步学习多个复杂原型及一个完整引擎的编写过程。

区块

区块相关知识已于前序章节讲解,在此不多赘述。

有链接指向的区块表明为之前介绍过的较重要的区块,您可以点击链接快速跳转到对应界面;没有链接指向的区块表明为不太重要的区块,您可以不用了解。

注意

由于 Sonolus 版本更新,本页读写权限表未必为最新版本。如果本页内容与官网内容有所出入,请以官网为准。

读取权限表

区块名preprocessspawnOrdershouldSpawninitializeupdateSequentialtouchupdateParallelterminate
RuntimeEnvironment✔✔✔✔✔✔✔✔
RuntimeUpdate✔✔✔✔✔✔✔✔
RuntimeTouchArray✔✔✔✔✔✔✔✔
RuntimeSkinTransform✔✔✔✔✔✔✔✔
RuntimeParticleTransform✔✔✔✔✔✔✔✔
RuntimeBackground✔✔✔✔✔✔✔✔
RuntimeUI✔✔✔✔✔✔✔✔
RuntimeUIConfiguration✔✔✔✔✔✔✔✔
LevelMemory✔✔✔✔✔✔✔✔
LevelData✔✔✔✔✔✔✔✔
LevelOption✔✔✔✔✔✔✔✔
LevelBucket✔✔✔✔✔✔✔✔
LevelScore✔✔✔✔✔✔✔✔
LevelLife✔✔✔✔✔✔✔✔
EngineRom✔✔✔✔✔✔✔✔
EntityMemory✔✔✔✔✔✔✔✔
EntityData✔✔✔✔✔✔✔✔
EntitySharedMemory✔✔✔✔✔✔✔✔
EntityInfo✔✔✔✔✔✔✔✔
EntityDespawn✔✔✔✔✔✔✔✔
EntityInput✔✔✔✔✔✔✔✔
EntityDataArray✔✔✔✔✔✔✔✔
EntitySharedMemoryArray✔✔✔✔✔✔✔✔
EntityInfoArray✔✔✔✔✔✔✔✔
ArchetypeLife✔✔✔✔✔✔✔✔
TemporaryMemory✔✔✔✔✔✔✔✔

修改权限表

区块名preprocessspawnOrdershouldSpawninitializeupdateSequentialtouchupdateParallelterminate
RuntimeEnvironment✔❌❌❌❌❌❌❌
RuntimeUpdate❌❌❌❌❌❌❌❌
RuntimeTouchArray❌❌❌❌❌❌❌❌
RuntimeSkinTransform✔❌❌❌✔✔❌❌
RuntimeParticleTransform✔❌❌❌✔✔❌❌
RuntimeBackground✔❌❌❌✔✔❌❌
RuntimeUI✔❌❌❌❌❌❌❌
RuntimeUIConfiguration✔❌❌❌❌❌❌❌
LevelMemory✔❌❌❌✔✔❌❌
LevelData✔❌❌❌❌❌❌❌
LevelOption❌❌❌❌❌❌❌❌
LevelBucket✔❌❌❌❌❌❌❌
LevelScore✔❌❌❌❌❌❌❌
LevelLife✔❌❌❌❌❌❌❌
EngineRom❌❌❌❌❌❌❌❌
EntityMemory✔✔✔✔✔✔✔✔
EntityData✔❌❌❌❌❌❌❌
EntitySharedMemory✔❌❌❌✔✔❌❌
EntityInfo❌❌❌❌❌❌❌❌
EntityDespawn✔✔✔✔✔✔✔✔
EntityInput✔✔✔✔✔✔✔✔
EntityDataArray✔❌❌❌❌❌❌❌
EntitySharedMemoryArray✔❌❌❌✔✔❌❌
EntityInfoArray❌❌❌❌❌❌❌❌
ArchetypeLife✔❌❌❌❌❌❌❌
TemporaryMemory✔✔✔✔✔✔✔✔
最近更新:: 2025/5/4 07:56
Contributors: LittleYang0531