0.2.0 |
|
---|
#51 in #directed-graph
52KB
753 代码行
Bevy Screenplay
此 Bevy 插件提供了一种在游戏中通过 剧本 创建对话和对话的方式。一个 剧本 是一个有向图,其中每个节点都是一个可以发生的 动作。动作通常是演员可以做的事情,例如说台词、进入/退出场景,甚至是玩家可以做出的选择等。
由于最常见的动作是在屏幕上显示文本,最基本的 剧本 是由演员之间对话组成的文本序列,形成一个动作的线性图。
剧本是一个可以附加到实体的 Bevy 组件。这样,您可以拥有多个具有自己剧本的实体,因此每个实体都有自己的对话。或者,如果您想制作类似视觉小说的游戏,您可以在游戏中使用一个单一的剧本。
剧本的核心是一个有向图,其中每个节点都是一个 ActionNode
struct ActionNode {
/// The kind of action.
kind: ActionKind,
/// The text of the action.
text: Option<String>,
/// The actors involved in the action.
actors: Vec<Actor>,
/// The choices available after the action.
choices: Option<Vec<Choice>>,
/// The sound effect associated with the action.
sound_effect: Option<String>,
}
此结构定义了可以发生的动作。
kind
字段定义了动作的类型(说话、进入、退出、选择)。text
字段是要在屏幕上显示的文本。actors
字段是参与动作的演员列表。choices
字段是提供给玩家的可选列表。sound_effect
字段是一个额外的字段,用于指定在动作达到时播放的声音效果。
Actor
结构是一个简单的结构,其中包含演员的名称和在屏幕上显示的资产。
struct Actor {
/// The name of the character that the actor plays.
name: String,
/// An optional asset that represents the actor's appearance or voice.
asset: Option<String>,
}
如果一个动作定义了一个或多个演员,则可以访问它们以获取要显示的名称(以及资产)和文本。
从 screenplay.ron 文件构建剧本
此插件可以解析 ron 文件以创建 RawScreenplay
资产,然后可以使用这些资产构建 Screenplay
组件。文件必须具有扩展名:screenplay.ron
。
以下是一个示例
(
actors: [
( id: "bob", name: "Bob", asset: Some("bob.png") ),
( id: "alice", name: "Alice", asset: Some("alice.png") )
],
script: [
( id: 1, action: Talk, text: Some("Bob and Alice enter the room.") ),
( id: 2, action: Enter, actors: [ "bob", "alice" ] ),
( id: 3, actors: ["bob"], text: Some("Hello, Alice!") ), // with missing action field, it defaults to Talk
(
id: 4,
choices: Some([
( text: "Alice says hello back.", next: 5 ),
( text: "Alice ignores Bob.", next: 6 ),
])
),
( id: 5, text: Some("Bob smiles.") ), // with missing actors field, it defaults to an empty vector
( id: 6, text: Some("Bob starts crying.") ),
( id: 7, text: Some("The end.") )
]
)
此插件为这些 ron 文件添加了一个 AssetLoader
,因此它非常简单
let handle: Handle<RawScreenplay> = server.load("simple.screenplay.ron");
然后,您可以使用 ScreenplayBuilder
从 RawScreenplay
资产构建一个 Screenplay
组件。您可以从资产集合 raws: Res<Assets<RawScreenplay>>
中检索 RawScreenplay
。
let raw_sp = raws.get(&simple_sp_asset.handle).unwrap();
ScreenplayBuilder::new().build(&raw_sp);
用法
一旦将 Screenplay
组件附加到一个实体上,您就可以使用常规的 Bevy Query
来访问它,以检索有关当前动作(文本、选择、涉及的演员、动作类型)的信息。
要移动到下一个动作(或跳转到特定的动作),您可以发送两个不同的事件,并利用变更检测系统在 Screenplay
组件发生更改后做出反应。
跳转到下一个动作的事件
NextActionRequest(pub Entity);
跳转到特定动作的事件
JumpToActionRequest(pub Entity, pub ActionId);
对于前者事件,您传递具有 Screenplay
组件的实体,而对于后者事件,您传递具有 Screenplay
组件和要跳转到的动作 ID 的实体。
插件将内部调用 Screenplay
组件的 next_action
和 jump_to
方法。
在您的一侧,您可以使用 Changed API 在发送这些事件后对这些更改做出反应。例如
fn print_text(screenplays: Query<&Screenplay, Changed<Screenplay>>) {
for sp in screenplays.iter() {
println!("{}", sp.text());
}
}
该组件提供公共 API 以从图中检索信息
actors
返回当前动作中涉及的演员列表。choices
返回当前动作中可用的选择列表。text
返回当前动作的文本。action_kind
返回当前动作的类型。
查看 examples
文件夹中的示例,了解如何使用此插件。
- simple.rs 展示了如何使用插件创建简单的、线性的对话。
- choices.rs 展示了如何使用插件创建具有选择的对话。
- full.rs 展示了一个使用所有动作类型的剧本。
其他事项
未来的工作是拥有一个图形编辑器来创建这些文件,但到目前为止,我们必须手动编写它们。欢迎任何贡献!
bevy_screenplay
版本的兼容性
bevy_screenplay |
bevy |
---|---|
main |
0.11 |
0.2.0 | 0.11 |
0.1.1 |
0.11 |
许可证
双重许可以下任一项
- Apache License, Version 2.0, (LICENSE-APACHE 或 https://www.apache.org/licenses/LICENSE-2.0)
- MIT 许可证 (LICENSE-MIT 或 https://opensource.org/licenses/MIT)
任选其一。
贡献
除非您明确声明,否则您有意提交以包含在作品中并由您定义的任何贡献,根据 Apache-2.0 许可证,应按上述方式双重许可,无需任何附加条款或条件。
依赖项
~21–52MB
~841K SLoC