The `move` and `animation` steps previously had no dispatch point: the story always suspended as a host-presented step and the host had to switch on the step kind in its own loop, or reimplement movement per game mode. Add two optional ports to `RpgStoryBinding`: StoryMoveHandler moveActor drives `move` StoryAnimationHandler playAnimation drives `animation` Each handler returns a three-state status, so one port serves every shape of host without the dialect assuming a game mode: Arrived / Finished step completes inline, the story never suspends Travelling / Playing the story suspends until the host calls advance() Unreachable / Unavailable the step fails with a structured diagnostic A failed `Result` from a handler is reported verbatim, so causes such as "the navigation service is not loaded" are not swallowed. Both payloads stay in the host's own space. `move`'s `x`/`y` are whatever the host's movement model uses (tile indices, board cells, world units, lanes) and never interpreted or rounded here; `animation`'s `clip` is an opaque locator and is never resolved, loaded, or assumed to name a rig. The `actor` / `actor` projection is null when the id belongs to another subject space (a map prop, a camera, a squad) and the step still runs. Omitting a handler leaves behaviour byte-for-byte unchanged: the step stays host-presented and the host acknowledges it with advance(). That is the escape hatch for hosts whose movement or playback must go through their own queue or state machine, and the compatibility path for existing content. Also let `RPGStorySession.begin` take `null` for `party` / `bag` / `equipment` in scripts. They are optional collaborators -- a purely presentational story needs none of them -- and the C++ entry point already documents them as nullable, but ssq's default pointer binding rejects Squirrel `null`. Translate through ssq::Object, matching the idiom in avatar/Avatar.cpp's addLayer. `gameState` stays typed and required because it owns the completion fact. Tests: 19 new zeroerr cases. 14 in test/rpg_dialect.cpp cover the semantics of both ports -- dispatch, inline completion, unreachable/unavailable failure, verbatim controller failure, the no-controller host-presented path, subjects outside the party roster, and travelling/playing state across capture and restore. 5 in test/rpg_dnut_script.cpp drive the steps end to end from Squirrel and verify the effect, including movement the script controls itself. Docs: docs/usr/modules/rpg.md documents both ports and the recommended script-owned movement path; the L1 plan records the deliberate deviation from its own "grid movement controller" design and why a map::Pathfinder binding would weld the dialect to one game mode (and add an upward L1->map dependency).
EVEngine 开发者文档
本目录保存引擎的架构、模块设计、测试策略和实现计划,面向 EVEngine 本身的维护者与贡献者。
如果你是游戏开发者而不是引擎开发者:请从官网发布页 下载预编译 SDK 直接使用,不需要编译引擎;用户文档见用户指南与 模块使用手册。本目录及下文“从源码构建”只对需要修改引擎的人有意义。
架构与工程约定
- 发布流程(
main/dev/vX.X.X,Pre-release 发版) - 整体架构
- 模块设计与实现进度
- 模块编排与裁剪架构(实测依赖分层、协作接缝、按需裁剪;用户侧用法见按需裁剪模块)
- EveScript 语言设计(统一
.nut前端、脚本模块、类型、持久变量与异步 lowering) - 依赖项
- 命令行设计
- 测试覆盖
- AI 与 MCP 支持
- AI 场景导演(剧情 → 自动搭台 → 质检迭代 → 交付)
- 游戏开发系统与工具差距分析
功能设计
- 2D 渲染 API
- 3D 渲染管线(初始化 / VKBuilder / 异步帧、buffers、数据流、函数与 shader)
- 体积光模块
- 抗锯齿模块
- 风格化渲染模块
- GUI 框架
- Tilemap
- 寻路系统
- 动态视野系统
- 程序化生成模块
- 体积光模块
- 环境光遮蔽模块
- 风格化渲染模块
- RPG 系统
- RPG 任务系统
- 背包系统
- 建筑放置系统
- 空间索引模块
- 游戏模型
- 界面设计
- 修改思路
实施记录
阶段性设计稿与实施计划位于 superpowers/。文档使用的图示位于 img/。
构建与文档
-
生成 C++ API 文档(Doxygen):
make docs(或cmake --build <build-dir> --target docs), 产物位于docs/api/html/(已加入.gitignore)。需要先安装 doxygen: Ubuntu/WSLsudo apt install doxygen、macOSbrew install doxygen、Windowschoco install doxygen。 文档配置见docs/Doxyfile.in与docs/CMakeLists.txt,入口src/、Readme.md与docs/usr/。 在线版由 GitHub Pages 持续发布:https://evengine.github.io/EVEngine/。 -
运行时断言:引擎统一通过 zeroerr 的
ASSERT系列宏做函数参数校验与内部不变量检查, 入口见src/engine/common/Assert.h(EV_PARAM_CHECK/EV_ASSERT)。- Debug 构建默认启用;
- Release 等非 Debug 构建默认通过
ZEROERR_NO_ASSERT编译剔除,零运行时开销; - 需要手动开启时:
make build/linux CMAKE_EXTRA_ARGS=-DEVENGINE_ENABLE_ASSERTS=ON(或 CMake 配置时加-DEVENGINE_ENABLE_ASSERTS=ON)。
如果你是使用 EVEngine 制作游戏,而不是修改引擎,请从用户指南开始。