fennel_engine/
lib.rs

1//! A small 2D game framework I'm building just-for-fun and to learn Rust a little bit deeper
2
3use sdl3::{
4    keyboard::{Keycode, Mod, Scancode},
5    mouse::{MouseButton, MouseState, MouseWheelDirection},
6};
7
8use crate::{audio::Audio, graphics::Graphics};
9
10/// Audio playback
11pub mod audio;
12/// Handling keyboard, window, mouse and other events
13pub mod events;
14/// Rendering layer and all the related things
15pub mod graphics;
16
17unsafe impl Send for Game {}
18unsafe impl Sync for Game {}
19
20/// Main game struct
21///
22/// Holds basic metadata and a reference to the graphics subsystem.
23/// User must create a [`Game`] in order to feed it to the EventHandler
24pub struct Game {
25    /// Human-readable game title.
26    pub name: String,
27    /// Author or owner of the game.
28    pub author: String,
29    /// Graphics subsystem used to render frames.
30    pub graphics: Graphics,
31    /// Audio subsystem
32    pub audio: Audio,
33}
34
35impl Game {
36    /// Create a new [`Game`] instance.
37    ///
38    /// # Parameters
39    /// - `name`: title of the game
40    /// - `author`: author/owner name
41    /// - `graphics`: initialized graphics subsystem
42    ///
43    /// # Returns
44    /// A [`Game`] instance ready to be used by an [`EventHandler`].
45    pub fn new(name: String, author: String, graphics: Graphics) -> Game {
46        let audio = Audio::new();
47        Game {
48            name,
49            author,
50            graphics,
51            audio,
52        }
53    }
54}
55
56/// Trait that must be implemented by user's game state struct
57/// - `update` is called to advance game state (physics, AI, input processing).
58/// - `draw` is called to render the current state using `game.graphics`.
59///
60/// Both return `anyhow::Result<()>`
61#[async_trait::async_trait]
62pub trait EventHandler {
63    async fn update(&self, game: &mut Game) -> anyhow::Result<()>;
64    async fn draw(&self, game: &mut Game) -> anyhow::Result<()>;
65    fn key_down_event(
66        &self,
67        _game: &mut Game,
68        _timestamp: u64,
69        _window_id: u32,
70        _keycode: Option<Keycode>,
71        _scancode: Option<Scancode>,
72        _keymod: Mod,
73        _repeat: bool,
74        _which: u32,
75        _raw: u16,
76    ) -> anyhow::Result<()> {
77        Ok(())
78    }
79
80    fn key_up_event(
81        &self,
82        _game: &mut Game,
83        _timestamp: u64,
84        _window_id: u32,
85        _keycode: Option<Keycode>,
86        _scancode: Option<Scancode>,
87        _keymod: Mod,
88        _repeat: bool,
89        _which: u32,
90        _raw: u16,
91    ) -> anyhow::Result<()> {
92        Ok(())
93    }
94
95    fn mouse_motion_event(
96        &self,
97        _game: &mut Game,
98        _timestamp: u64,
99        _window_id: u32,
100        _which: u32,
101        _mousestate: MouseState,
102        _x: f32,
103        _y: f32,
104        _xrel: f32,
105        _yrel: f32,
106    ) -> anyhow::Result<()> {
107        Ok(())
108    }
109
110    fn mouse_button_down_event(
111        &self,
112        _game: &mut Game,
113        _timestamp: u64,
114        _window_id: u32,
115        _which: u32,
116        _mouse_btn: MouseButton,
117        _clicks: u8,
118        _x: f32,
119        _y: f32,
120    ) -> anyhow::Result<()> {
121        Ok(())
122    }
123
124    fn mouse_button_up_event(
125        &self,
126        _game: &mut Game,
127        _timestamp: u64,
128        _window_id: u32,
129        _which: u32,
130        _mouse_btn: MouseButton,
131        _clicks: u8,
132        _x: f32,
133        _y: f32,
134    ) -> anyhow::Result<()> {
135        Ok(())
136    }
137
138    fn mouse_wheel_event(
139        &self,
140        _game: &mut Game,
141        _timestamp: u64,
142        _window_id: u32,
143        _which: u32,
144        _x: f32,
145        _y: f32,
146        _direction: MouseWheelDirection,
147        _mouse_x: f32,
148        _mouse_y: f32,
149    ) -> anyhow::Result<()> {
150        Ok(())
151    }
152}