28个版本

新增 0.3.10 2024年8月17日
0.3.9 2024年2月25日
0.3.7 2023年11月6日
0.3.4 2023年7月29日
0.1.7 2022年11月27日

#152 in 游戏开发

Download history 2/week @ 2024-05-01 6/week @ 2024-05-08 3/week @ 2024-05-15 7/week @ 2024-05-22 4/week @ 2024-05-29 13/week @ 2024-06-05 6/week @ 2024-06-12 5/week @ 2024-06-19 8/week @ 2024-06-26 2/week @ 2024-07-10 11/week @ 2024-07-17 143/week @ 2024-07-24 10/week @ 2024-07-31 10/week @ 2024-08-07 149/week @ 2024-08-14

每月 319 次下载
用于 5 crates

MIT/ApacheGPL-3.0-or-later

140KB
3K SLoC

geese

Crates.io Docs.rs

Geese是一个Rust游戏事件系统,旨在允许模块化游戏引擎设计。

在Geese中,系统是一个具有内部状态和相关事件处理器的struct。系统可以引发事件并对其他系统引发的事件做出反应。系统还可以声明对其他系统的依赖,允许它们在事件处理期间借用这些系统。Geese会自动加载所有系统依赖。任何struct都可以作为事件类型,任何实现了GeeseSystem的struct都可以作为系统类型。

以下是如何使用Geese加载多个依赖系统并在它们之间传播事件的示例。该示例创建了一个Geese上下文,并请求加载系统B。当调用flush_events时,首先加载系统A(因为它是B的依赖项),然后加载系统BB接收到类型化事件,并通过查询系统A以获取某些信息来做出响应。

struct A;

impl A {
    pub fn answer(&self) -> bool {
        true
    }
}

impl GeeseSystem for A {
    fn new(_: GeeseContextHandle<Self>) -> Self {
        Self
    }
}

struct B {
    ctx: GeeseContextHandle<Self>
}

impl B {
    fn test_answer(&mut self, event: &Arc<AtomicBool>) {
        event.store(self.ctx.get::<A>().answer(), Ordering::Relaxed);
    }
}

impl GeeseSystem for B {
    const DEPENDENCIES: Dependencies = dependencies()
        .with::<A>();

    const EVENT_HANDLERS: EventHandlers<Self> = event_handlers()
        .with(Self::test_answer);

    fn new(ctx: GeeseContextHandle<Self>) -> Self {
        Self { ctx }
    }
}

let ab = Arc::new(AtomicBool::new(false));
let mut ctx = GeeseContext::default();
ctx.flush()
    .with(notify::add_system::<B>())
    .with(ab.clone());
assert!(ab.load(Ordering::Relaxed));

可以在示例文件夹中找到使用geese实现的Pong游戏。

事件处理

在事件处理期间始终遵守以下不变性,这使得推理执行顺序变得容易

  • 如果引发多个事件,它们将按先进先出(FIFO)顺序处理。可以使用notify::flush命令通过启动嵌入式事件周期来实现对排序的精细控制。
  • 同一系统上的同一事件的多重处理程序将按照它们在处理程序列表中出现的顺序调用。
  • 在处理单个事件时,依赖项的事件处理程序总是先于依赖项的事件处理程序调用。

并发

鹅可以采用多线程并行处理工作,允许独立系统协同执行事件处理器。即使在多线程的情况下,事件处理的所有不变性仍然得到保持 - 从单个系统的角度来看,事件仍然按顺序执行。定义的系统越多,并行度就越高。

要使用鹅与多线程结合,可以使用内置的 HardwareThreadPool 或者使用 GeeseThreadPool 特性实现自定义线程池。

依赖项

~1.1–2.8MB
~58K SLoC