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}