simple_game_engine/
lib.rs

1//! A minimal game engine that's really easy to get started with.
2//!
3//!  This project aims to create a minimal, yet usable, game engine. It is heavily inspired by [the Pixel Game Engine](https://github.com/OneLoneCoder/olcPixelGameEngine),
4//! with the goal of creating something that abstracts away the complexities of creating graphical, interactive apps and
5//! games. Right now, it's a thin wrapper around [SDL2](https://www.libsdl.org) (using the [sdl2
6//! crate](https://crates.io/crates/sdl2)) for visuals.
7//! # Features
8//! * **Very simple to use:** Just implement the [`Application` trait][Application] on a type of your choice, then pass an instance of this type to [`Engine::new`].
9//! * **Powerful:** Anything you can do with sdl2 from Rust, you can do with this library, and we provide thin abstractions over some of the more convoluted sdl2 interfaces.
10//! * **Built-in text rendering:** No need to find a TTF font and distribute it with your application, just call the [`Canvas::draw_text`][canvas::Canvas::draw_text] method. ([see below](#caveats-with-text-rendering))
11//! ## Caveats With Text Rendering
12//! This crate uses the [GNU Unifont][unifont] for built-in text rendering. As such, if you wish to use this feature, you
13//! must distribute your project under the [GPL][gpl]. As this is not desirable for many projects, this feature is only
14//! enabled if this crate is built with the "unifont" cargo feature.
15//! ```toml
16//! [dependencies.simple-game-engine]
17//! version = "0.8.2"
18//! features = ["unifont"]
19//! ```
20//! If you'd like to render text without using this font, consider checking out the [SDL2 TTF module][sdl2-ttf].
21//!
22//! [unifont]: <http://unifoundry.com/unifont/index.html>
23//! [gpl]: <https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html>
24//! [sdl2-ttf]: <https://docs.rs/sdl2/latest/sdl2/ttf/index.html>
25//! # Example
26//! The simplest SGE program looks like this:
27//! ```no_run
28//! use simple_game_engine::{self as sge, prelude::*};
29//! use std::error::Error;
30//!
31//! struct App {}
32//!
33//! impl sge::Application for App {
34//!     fn on_create(
35//!         &mut self,
36//!         canvas: &mut WindowCanvas,
37//!         input: &InputState,
38//!     ) -> sge::ApplicationResult {
39//!         // Do one-time initialisation here
40//!         Ok(true) // `true` indicates to continue running the application
41//!     }
42//!
43//!     fn on_update(
44//!         &mut self,
45//!         canvas: &mut WindowCanvas,
46//!         input: &InputState,
47//!         elapsed_time: f64,
48//!     ) -> sge::ApplicationResult {
49//!         // Handle user input, update the canvas, and perform any other tasks to be ran on each frame
50//!         Ok(true) // `true` indicates to continue running the application
51//!     }
52//! }
53//!
54//! fn main() -> Result<(), Box<dyn Error>> {
55//!     let mut app = App {};
56//!     let mut engine = sge::Engine::new(
57//!         &mut app,   // Application instance
58//!         "Test App", // Window title
59//!         640,        // Window width
60//!         480,        // Window height
61//!     )?;
62//!     engine.start(true) // `true` starts the app with vsync enabled
63//! }
64//! ```
65//! `on_create` and `on_update` are optional, but their default implementation does nothing, so
66//! you'll probably want to define some logic for at least `on_update`, which is called for every
67//! frame.
68
69#![warn(missing_docs)]
70
71mod engine;
72pub use engine::Engine;
73pub mod canvas;
74pub use canvas::WindowCanvas;
75pub mod input;
76
77use std::error::Error;
78
79pub use sdl2::{
80    pixels::Color,
81    rect::{Point, Rect},
82};
83
84/// The return type of [`Application::on_create`] and [`Application::on_update`].
85pub type ApplicationResult = Result<bool, Box<dyn Error>>;
86
87/// An application using this framework.
88pub trait Application<Canvas = WindowCanvas> {
89    /// Called once at the start of the program.
90    /// # Parameters
91    /// * `canvas`: A draw target representing the visible window.
92    /// * `input`: a struct containing info about the state of input devices, such as the keyboard
93    ///   and mouse.
94    fn on_create(&mut self, _canvas: &mut Canvas, _input: &input::InputState) -> ApplicationResult {
95        Ok(true)
96    }
97    /// Called once per frame.
98    /// # Parameters
99    /// * `canvas`: A draw target representing the visible window.
100    /// * `input`: a struct containing info about the state of input devices, such as the keyboard
101    ///   and mouse.
102    /// * `elapsed_time`: Duration (in seconds) since the last frame. This can be used to keep
103    ///   time-sensative routines, such as animation, running at a constant speed.
104    fn on_update(
105        &mut self,
106        _canvas: &mut Canvas,
107        _input: &input::InputState,
108        _elapsed_time: f64,
109    ) -> ApplicationResult {
110        Ok(true)
111    }
112    /// Called when the window's close button is clicked.
113    /// Be aware that this isn't called on `std::process::exit`, so do any essential
114    /// cleanup in a `Drop` implementation instead.
115    /// Does nothing by default.
116    fn on_quit(&mut self) -> Result<(), Box<dyn Error>> {
117        Ok(())
118    }
119}
120
121pub mod prelude {
122    //! Commonly used types.
123    pub use crate::{
124        input::{InputState, MouseButton, Scancode},
125        Color, Point, Rect, WindowCanvas,
126    };
127}