Skip to main content

engine/
lib.rs

1/**----------------------------------------------------------------------------
2*!  A cross-platform 2D game engine built with Rust and wGPU.
3*?  Provides a trait-based game loop architecture where games implement
4*?  `GameApp` to define their logic, while the engine handles rendering,
5*?  input, and window management.
6
7**  Modules for different engine subsystems. These are kept private to
8**  encapsulate implementation details, but their public types are re-exported
9**  for convenience.
10*----------------------------------------------------------------------------**/
11pub mod animation;
12pub mod audio;
13pub mod camera;
14pub mod context;
15pub mod input;
16pub mod math;
17pub mod noise;
18pub mod physics;
19mod runtime;
20pub mod sprite;
21pub mod texture;
22pub mod texture_manager;
23pub mod time;
24
25//* Re-export commonly used types
26pub use animation::{AnimationDef, AnimationState};
27pub use audio::{AudioManager, AudioResponse, AudioTrack, UiAudioEvent, load_sound_data};
28pub use camera::ScreenShake;
29pub use context::Context;
30pub use glam::{Vec2, Vec3, Vec4};
31pub use input::{GameAction, InputMap, InputState, Key, MouseBinding};
32pub use kira::sound::static_sound::StaticSoundData;
33pub use math::move_towards;
34pub use physics::{AABB, BoxVolume, CollisionLayer, SweepResult};
35pub use sprite::BlendMode;
36pub use sprite::Rect;
37
38pub use egui;
39#[cfg(not(target_arch = "wasm32"))]
40pub use gilrs;
41pub use texture::Texture;
42pub use texture_manager::TextureHandle;
43pub use time::FixedTime;
44
45#[derive(Debug, Clone, PartialEq)]
46pub struct SceneParams {
47    pub background_color: [f32; 3],
48    pub seed: u32,
49    pub fog_enabled: bool,
50    pub fog_density: f32,
51    pub fog_opacity: f32,
52    pub fog_color: [f32; 3],
53    pub fog_anim_speed: f32,
54    pub time: f32,
55}
56
57//? Default parameters for the scene, which can be overridden by the debug UI.
58impl Default for SceneParams {
59    fn default() -> Self {
60        Self {
61            background_color: [0.67, 0.42, 0.85], //* #AC6CDA
62            seed: 42,
63            fog_enabled: true,
64            fog_density: 10.0,
65            fog_opacity: 1.0,
66            fog_color: [0.41, 0.36, 0.81], //* #685DCE
67            fog_anim_speed: 0.5,
68            time: 0.0,
69        }
70    }
71}
72
73pub trait GameApp: 'static {
74    //? The game's action enum
75    type Action: GameAction;
76
77    fn window_title() -> &'static str {
78        "Journey Engine"
79    }
80
81    fn window_icon() -> Option<&'static [u8]> {
82        None
83    }
84
85    fn wasm_ready_event() -> Option<&'static str> {
86        None
87    }
88
89    fn internal_resolution() -> (u32, u32) {
90        (640, 360)
91    }
92
93    //* Initialize the game state. Called once when the engine starts.
94    //? Use `ctx` to access screen dimensions and other initial state.
95    fn init(ctx: &mut Context<Self::Action>) -> Self;
96
97    //* Fixed-rate update for deterministic game logic (physics, combat).
98    //? Called at exactly `fixed_time.fixed_dt` intervals (default 60 Hz).
99    //? `ctx.delta_time` equals `fixed_time.fixed_dt`. Use `fixed_time.tick`
100    //? for frame-data combat windows instead of float accumulators.
101    fn fixed_update(&mut self, _ctx: &mut Context<Self::Action>, _fixed_time: &time::FixedTime) {}
102
103    //? Use for camera smoothing, interpolation, and non-gameplay-critical updates.
104    fn update(&mut self, ctx: &mut Context<Self::Action>);
105
106    //* Render the game. Called every frame after `update`.
107    //? Use `ctx.draw_sprite()` to submit draw calls. Sprites are rendered after the background but before the UI overlay.
108    fn render(&mut self, ctx: &mut Context<Self::Action>);
109    fn ui(
110        &mut self,
111        _egui_ctx: &egui::Context,
112        _ctx: &mut Context<Self::Action>,
113        _scene_params: &mut SceneParams,
114    ) {
115    }
116}
117
118fn init_logging() {
119    #[cfg(not(target_arch = "wasm32"))]
120    {
121        env_logger::try_init().ok();
122    }
123
124    #[cfg(target_arch = "wasm32")]
125    {
126        console_error_panic_hook::set_once();
127        console_log::init_with_level(log::Level::Info).ok();
128    }
129}
130
131pub fn run<G: GameApp>() {
132    init_logging();
133    runtime::start::<G>();
134}
135
136/**----------------------------------------------------------------------------
137*!  WASM entry point {requires a default game type at compile time.}
138*?  Note: WASM builds must specify a concrete game type since we can't
139*?  use generics in the #[wasm_bindgen(start)] entry point. Games should
140*?  export their own wasm_main that calls a type-specific run function.
141*----------------------------------------------------------------------------**/
142#[cfg(target_arch = "wasm32")]
143pub fn run_wasm<G: GameApp>() {
144    init_logging();
145    runtime::start::<G>();
146}