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, resources::ResourceManager};
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/// Resource management
17pub mod resources;
18/// Tests
19mod tests;
20
21unsafe impl Send for Game {}
22unsafe impl Sync for Game {}
23
24/// Main game struct
25///
26/// Holds basic metadata and a reference to the graphics subsystem.
27/// User must create a [`Game`] in order to feed it to the EventHandler
28pub struct Game {
29    /// Human-readable game title.
30    pub name: String,
31    /// Author or owner of the game.
32    pub author: String,
33    /// Graphics subsystem used to render frames.
34    pub graphics: Graphics,
35    /// Audio subsystem
36    pub audio: Audio,
37    /// Resource management
38    pub resource_manager: ResourceManager,
39}
40
41impl Game {
42    /// Create a new [`Game`] instance.
43    ///
44    /// # Parameters
45    /// - `name`: title of the game
46    /// - `author`: author/owner name
47    /// - `graphics`: initialized graphics subsystem
48    ///
49    /// # Returns
50    /// A [`Game`] instance ready to be used by an [`EventHandler`].
51    pub fn new(name: String, author: String, graphics: Graphics) -> Game {
52        let audio = Audio::new();
53        Game {
54            name,
55            author,
56            graphics,
57            audio,
58            resource_manager: ResourceManager::new(),
59        }
60    }
61}
62
63/// Trait that must be implemented by user's game state struct
64/// - `update` is called to advance game state (physics, AI, input processing).
65/// - `draw` is called to render the current state using `game.graphics`.
66///
67/// Both return `anyhow::Result<()>`
68#[async_trait::async_trait]
69pub trait EventHandler {
70    /// Updates the game state.
71    ///
72    /// This method should contain the logic for updating the game state.
73    ///
74    /// # Arguments
75    ///
76    /// * `game` - A mutable reference to the game state.
77    ///
78    /// # Returns
79    ///
80    /// * `Result<()>` - `()` if everythings fine, otherwise you should return an error if
81    /// something failed in your logics
82    async fn update(&self, game: &mut Game) -> anyhow::Result<()>;
83
84    async fn draw(&self, game: &mut Game) -> anyhow::Result<()>;
85
86    fn key_down_event(
87        &self,
88        _game: &mut Game,
89        _timestamp: u64,
90        _window_id: u32,
91        _keycode: Option<Keycode>,
92        _scancode: Option<Scancode>,
93        _keymod: Mod,
94        _repeat: bool,
95        _which: u32,
96        _raw: u16,
97    ) -> anyhow::Result<()> {
98        Ok(())
99    }
100
101    fn key_up_event(
102        &self,
103        _game: &mut Game,
104        _timestamp: u64,
105        _window_id: u32,
106        _keycode: Option<Keycode>,
107        _scancode: Option<Scancode>,
108        _keymod: Mod,
109        _repeat: bool,
110        _which: u32,
111        _raw: u16,
112    ) -> anyhow::Result<()> {
113        Ok(())
114    }
115
116    fn mouse_motion_event(
117        &self,
118        _game: &mut Game,
119        _timestamp: u64,
120        _window_id: u32,
121        _which: u32,
122        _mousestate: MouseState,
123        _x: f32,
124        _y: f32,
125        _xrel: f32,
126        _yrel: f32,
127    ) -> anyhow::Result<()> {
128        Ok(())
129    }
130
131    fn mouse_button_down_event(
132        &self,
133        _game: &mut Game,
134        _timestamp: u64,
135        _window_id: u32,
136        _which: u32,
137        _mouse_btn: MouseButton,
138        _clicks: u8,
139        _x: f32,
140        _y: f32,
141    ) -> anyhow::Result<()> {
142        Ok(())
143    }
144
145    fn mouse_button_up_event(
146        &self,
147        _game: &mut Game,
148        _timestamp: u64,
149        _window_id: u32,
150        _which: u32,
151        _mouse_btn: MouseButton,
152        _clicks: u8,
153        _x: f32,
154        _y: f32,
155    ) -> anyhow::Result<()> {
156        Ok(())
157    }
158
159    fn mouse_wheel_event(
160        &self,
161        _game: &mut Game,
162        _timestamp: u64,
163        _window_id: u32,
164        _which: u32,
165        _x: f32,
166        _y: f32,
167        _direction: MouseWheelDirection,
168        _mouse_x: f32,
169        _mouse_y: f32,
170    ) -> anyhow::Result<()> {
171        Ok(())
172    }
173}