5 个不稳定版本
0.3.2 | 2023 年 3 月 28 日 |
---|---|
0.3.1 | 2023 年 2 月 2 日 |
0.3.0 | 2023 年 1 月 30 日 |
0.2.0 | 2023 年 1 月 29 日 |
0.1.0 | 2023 年 1 月 28 日 |
449 在 游戏开发
每月 28 次下载
30KB
219 行
索堆栈
索堆栈 是一个库,通过 状态堆栈机 管理应用程序的控制流。
Stack
struct
存储任意数量的 State
。当该 Stack
被触发时,它执行最顶层 State
的主要方法。这意味着只有 Stack
顶部的 State
被执行,而下面的则实际上 暂停。例外的是 State
的 on_shadow_tick
方法,在 v0.3.0
中引入,它总是独立于 State
在 Stack
上的位置执行。
项目处于早期开发阶段,可能会有所变化!在更新之前请查看变更日志。有些文本可能暗示某些事情已经完成,但实际上并没有,比如《索堆栈手册》。尽管如此,可能会有一些错误,但测试应该保证错误数量很少。
概述
State
拥有您需要的所有方法。以下是一个概述
on_start
— 当此State
首次推入Stack
时执行。on_stop
— 当此State
从Stack
中弹出时执行。on_pause
— 当另一个State
被推入Stack
并在顶部覆盖此State
时执行。on_resume
—— 当此之上的所有State
从Stack
中弹出时执行。on_tick
—— 每次调用持有此State
的Stack
的tick
方法时执行。on_shadow_tick
—— 与on_tick
相同,但总是独立于此State
在Stack
中的位置运行。
要在 State
之间跳转,您需要在 on_tick
或类似方法中返回一个 Trans
选项枚举,请求 Stack
在下一个时钟周期执行此类转换。以下是一个概述
Trans::None
—— 请求Stack
不做任何事情。Trans::Quit
—— 请求Stack
弹出它持有的所有State
。Trans::Push(Box::new(State))
—— 请求Stack
在顶部Push
提供的State
。Trans::Pop
—— 请求Stack
弹出它持有的最顶层的State
,并删除它。Trans::Replace(Box::new(State))
—— 请求Stack
弹出一次,然后Push
提供的State
。Trans::Isolate(Box::new(State))
—— 请求Stack
弹出所有内容,然后Push
提供的State
。
可以直接请求
Stack
或通过返回一个Trans
来请求转换,从State
的on_tick
或on_shadow_tick
方法中返回。
特性
-
易于实现的
State
trait
。 -
易于使用的 State
Stack
Machinestruct
。 -
易于使用的
Trans
itions betweenStates
集合。 -
在
v0.3.0
中新增on_shadow_tick
在State
中提供;类似于on_tick
,但 始终独立于State
在Stack
中的位置 执行。
用例
假设您正在编写一个游戏。您需要一种控制程序流程的方法。从主菜单到游戏本身;从游戏到暂停菜单;或者从暂停菜单到退出程序。
Solstack 将帮助您构建这些 State
和它们之间的 Trans
itions.
让我们来模拟一些东西。以下是我们的 State
(以 S
开头)
SMainMenu
:玩家在初始化游戏时着陆的地方。SGame
:实际游戏逻辑所在的地方。SPauseMenu
:玩家可以保存、继续游戏或退出的地方。
由于 SMainMenu
是用户将首先遇到的东西,因此当程序开始时,我们将手动将那个 State
推送到我们的 Stack
上。然后我们在主循环中检查 Stack
,直到它里面不再有任何 State
。
您可以通过在本地实例上使用其方法来手动在
Stack
上执行转换。可以使用
Stack
的is_running
方法来实现循环。
在程序开始时,Stack
将看起来像这样
SMainMenu
只有一个状态在 Stack
上,它位于顶部;因此它将调用其方法。 SMainMenu
的逻辑很简单:当玩家按下 START 时,它请求 Stack
Push
一个 SGame
。如果发生这种情况,Stack
将看起来像这样
SGame
SMainMenu
由于只有最顶部的状态由 Stack
的 tick
执行,所以 SMainMenu
只在那里坐着。现在玩家正在享受他们的游戏;但他们希望暂停!好吧,在 SGame
中,我们只需要请求堆栈在玩家按下 ESC 时 Push
一个 SPauseMenu
。很简单!让我们再次看看 Stack
SPauseMenu
SGame
SMainMenu
现在 SPauseMenu
在顶部。 SGame
将被 暂停;它还在那里,但正在执行。在 SPauseMenu
中应该有逻辑说,如果玩家再次按下 ESC,则 Stack
应该 Pop
。 Pop
的意思是删除或完全删除 Stack
顶部的最顶层 State
。在这种情况下,SPauseMenu
本身。然后,Stack
将再次看起来像这样
SGame
SMainMenu
最终,SGame
再次位于顶部!因此,它将重新开始 精确 到它离开的地方!如果玩家选择 退出游戏,您只需请求 Stack
Quit
,这将 Pop
它拥有的每个 State
,使主循环结束。
这个概念可以扩展到更大的模式;希望您在使用 solstack
结构化应用程序时找到乐趣!
开始吧
这只是一个 非常简单 的代码示例。请查看此页面的开头链接,特别是项目存储库中的示例。测试也是了解库内部工作方式的好方法。
use solstack::prelude::*;
use solstack::macros::*; // easy abstractions over boilerplate-y code.
// data available to `State`s for writing and reading
#[derive(Default)]
struct GameData {
value: i32
}
// a `State` that does what it says
struct AddOneAndPrintState;
impl State<GameData> for AddOneAndPrintState {
// run when this `State` is first pushed onto a `Stack`
fn on_start(&mut self, data: &mut GameData) {
data.value = 41;
println!("on_start `make data be 41` > GameData({})", data.value);
}
// run every time the `Stack` is ticked.
fn on_tick(&mut self, data: &mut GameData) -> Trans<GameData> {
data.value += 1;
println!("on_tick `add one to data` > GameData({})", data.value);
Trans::None
}
}
fn main() {
// initializing
let mut data = GameData::default();
let mut stack = Stack::<GameData>::new();
assert_eq!(data.value, 0);
// manually pushing and ticking the `Stack`
stack_push!(stack, data, AddOneAndPrintState);
assert_eq!(data.value, 41);
stack_tick!(stack, data);
assert_eq!(data.value, 42);
stack_tick!(stack, data);
assert_eq!(data.value, 43);
}
谢谢
文档将始终是最新的。
感谢您使用 solstack
!
由 Sol [email protected]