Extra2D/.trae/documents/Extra2D 脚本引擎架构升级计划.md

12 KiB
Raw Blame History

Extra2D 模块化脚本系统融合方案

结合 Yosin 的配置驱动脚本加载Kiwano 的模块系统,为 Extra2D 实现一个强大的模块化 Squirrel 脚本架构。

融合架构设计

┌─────────────────────────────────────────────────────────────────────────┐
│                         Extra2D.exe (C++ 引擎)                           │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │                    Application (单例)                            │   │
│  │  ┌─────────────────────────────────────────────────────────┐   │   │
│  │  │              ModuleList (模块列表)                       │   │   │
│  │  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────────┐ │   │   │
│  │  │  │ ScriptModule│  │ AudioModule │  │ PhysicsModule   │ │   │   │
│  │  │  │ (脚本系统)   │  │ (音频系统)   │  │ (物理系统)       │ │   │   │
│  │  │  └─────────────┘  └─────────────┘  └─────────────────┘ │   │   │
│  │  └─────────────────────────────────────────────────────────┘   │   │
│  │                                                                  │   │
│  │  - Run()          - 运行应用                                    │   │
│  │  - Use(Module&)   - 注册模块                                    │   │
│  │  - Update(dt)     - 更新所有模块                                │   │
│  │  - Render()       - 渲染所有模块                                │   │
│  └─────────────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                        ScriptModule (脚本模块)                           │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │                    Squirrel VM                                   │   │
│  │  ┌─────────────────────────────────────────────────────────┐   │   │
│  │  │              ScriptConfig.cfg (配置驱动)                  │   │   │
│  │  │  - 定义脚本加载顺序                                       │   │   │
│  │  │  - 定义模块依赖关系                                       │   │   │
│  │  └─────────────────────────────────────────────────────────┘   │   │
│  │                                                                  │   │
│  │  加载流程:                                                        │   │
│  │  1. 加载 Core 层 (基础工具类)                                    │   │
│  │  2. 加载 Engine 层 (引擎封装类)                                  │   │
│  │  3. 执行 User/main.nut (用户入口)                                │   │
│  │                                                                  │   │
│  │  每帧调用:                                                        │   │
│  │  - OnUpdate(dt) -> 调用脚本的 update 函数                        │   │
│  │  - OnRender()   -> 调用脚本的 render 函数                        │   │
│  └─────────────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                        Squirrel 脚本层                                  │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐    │
│  │   Core/     │  │  Engine/    │  │   User/     │  │  Modules/   │    │
│  │             │  │             │  │             │  │             │    │
│  │ _init.nut   │  │ _init.nut   │  │ main.nut    │  │ ui.nut      │    │
│  │ class.nut   │  │ app.nut     │  │ stages/     │  │ network.nut │    │
│  │ array.nut   │  │ director.nut│  │ objects/    │  │ ...         │    │
│  │ math.nut    │  │ stage.nut   │  │ ui/         │  │             │    │
│  └─────────────┘  └─────────────┘  └─────────────┘  └─────────────┘    │
└─────────────────────────────────────────────────────────────────────────┘

核心组件设计

1. Module 基类(来自 Kiwano

// base/module.h
class Module {
public:
    virtual void setupModule();      // 初始化
    virtual void destroyModule();    // 销毁
    virtual void onUpdate(float dt); // 更新
    virtual void onRender();         // 渲染
    virtual void handleEvent(Event* evt); // 事件
};

2. ScriptModule脚本模块

// script/script_module.h
class ScriptModule : public Module {
public:
    void setupModule() override {
        // 1. 初始化 Squirrel VM
        vm_ = sq_open(1024);
        
        // 2. 注册 C++ 绑定
        registerBindings(vm_);
        
        // 3. 读取 ScriptConfig.cfg
        auto config = loadConfig("scripts/ScriptConfig.cfg");
        
        // 4. 按顺序加载脚本
        for (auto& path : config.preload) {
            executeFile(path);
        }
        
        // 5. 调用 main 函数
        callMainFunction();
    }
    
    void onUpdate(float dt) override {
        // 调用脚本的全局 update 函数
        callScriptFunction("onUpdate", dt);
    }
};

3. 脚本配置系统(来自 Yosin

# scripts/ScriptConfig.cfg
# 定义脚本加载顺序

# ========== Core 层(基础工具)==========
scripts/core/_init.nut
scripts/core/class.nut
scripts/core/array.nut
scripts/core/table.nut
scripts/core/math.nut
scripts/core/string.nut

# ========== Engine 层(引擎封装)==========
scripts/engine/_init.nut
scripts/engine/application.nut
scripts/engine/director.nut
scripts/engine/stage.nut
scripts/engine/node.nut
scripts/engine/sprite.nut
scripts/engine/action.nut
scripts/engine/audio.nut
scripts/engine/input.nut

# ========== User 层(用户逻辑)==========
scripts/user/stages/start_stage.nut
scripts/user/objects/player.nut
scripts/user/ui/main_ui.nut
scripts/user/main.nut  # 入口脚本(最后加载)

4. 脚本类层次结构(来自 Yosin

// scripts/core/class.nut
// 基础类系统

// scripts/engine/node.nut
class Node {
    C_Object = null;  // C++ 对象指针
    
    constructor() {
        C_Object = Node_Create();
        Register_Destruction(C_Object, this);
    }
    
    function setPosition(x, y) {
        Node_SetPosition(C_Object, x, y);
    }
    
    function getPosition() {
        return Node_GetPosition(C_Object);
    }
}

// scripts/engine/stage.nut
class Stage extends Node {
    constructor() {
        C_Object = Stage_Create();
    }
    
    function enter() {
        Director_EnterStage(C_Object);
    }
    
    function onUpdate(dt) {
        // 子类重写
    }
}

// scripts/engine/application.nut
class Application {
    title = "Extra2D Game";
    width = 1280;
    height = 720;
    
    function run(stageClass) {
        App_SetTitle(title);
        App_SetSize(width, height);
        App_Run(stageClass);
    }
}

5. 用户入口脚本main.nut

// scripts/user/main.nut
function main(args) {
    // 创建应用
    local app = Application();
    app.title = "My Game";
    app.width = 800;
    app.height = 600;
    
    // 运行开始舞台
    app.run(StartStage);
}

// 定义开始舞台
class StartStage extends Stage {
    function onEnter() {
        // 创建精灵
        local sprite = Sprite("assets/logo.png");
        sprite.setPosition(400, 300);
        this.addChild(sprite);
        
        // 创建 UI
        local ui = MainUI();
        this.addChild(ui);
    }
    
    function onUpdate(dt) {
        // 每帧更新
    }
}

实现步骤

阶段 1: 基础架构

  1. 创建 base/module.h/cppKiwano 风格)
  2. 修改 Application 支持模块注册
  3. 实现模块生命周期管理

阶段 2: 脚本模块

  1. 创建 script/script_module.h/cpp
  2. 实现配置解析(ScriptConfig.cfg
  3. 实现脚本加载器

阶段 3: C++ 绑定扩展

  1. 扩展 Node 绑定(添加 C_Object 指针桥接)
  2. 添加 Stage 类绑定
  3. 添加 Director 类绑定
  4. 添加 Application 配置绑定

阶段 4: 脚本类库

  1. 创建 scripts/core/ 基础工具
  2. 创建 scripts/engine/ 引擎封装
  3. 实现类继承机制

阶段 5: 入口机制

  1. 实现 main() 函数自动调用
  2. 实现 GameWindow 封装类
  3. 创建示例项目

文件变更清单

新增文件

src/extra2d/base/module.h
src/extra2d/base/module.cpp
src/extra2d/script/script_module.h
src/extra2d/script/script_module.cpp
src/extra2d/script/sq_binding_stage.cpp
src/extra2d/script/sq_binding_director.cpp
scripts/ScriptConfig.cfg
scripts/core/_init.nut
scripts/core/class.nut
scripts/engine/_init.nut
scripts/engine/application.nut
scripts/engine/director.nut
scripts/engine/stage.nut
scripts/user/main.nut

修改文件

src/extra2d/app/application.h/cpp
src/extra2d/script/script_engine.cpp
src/extra2d/script/sq_binding_node.cpp

最终效果

用户只需编写脚本即可创建完整游戏:

// 纯脚本游戏
function main() {
    local app = Application();
    app.config({
        title = "Hello World",
        width = 800,
        height = 600
    });
    
    local director = Director();
    director.enterStage(MyStage());
    
    app.run();
}

class MyStage extends Stage {
    function onEnter() {
        local label = Label("Hello Squirrel!");
        label.position = [400, 300];
        this.addChild(label);
    }
}

请确认此方案后,我将开始