#opengl #graphics #2d-graphics #gamedev #opengl-context #mouse-event

speedy2d

Hardware-accelerated drawing of shapes, images, and text, with an easy to use API. Speedy2D aims to be the simplest Rust API for creating a window, rendering graphics, and handling input.

25 stable releases

new 2.1.0 Mar 25, 2024
2.0.0 Nov 5, 2023
1.12.0 Mar 19, 2023
1.9.0 Nov 26, 2022
1.0.7 Mar 4, 2021

#24 in Graphics APIs

Download history 61/week @ 2023-12-06 148/week @ 2023-12-13 113/week @ 2023-12-20 39/week @ 2023-12-27 64/week @ 2024-01-03 101/week @ 2024-01-10 81/week @ 2024-01-17 66/week @ 2024-01-24 43/week @ 2024-01-31 85/week @ 2024-02-07 129/week @ 2024-02-14 172/week @ 2024-02-21 273/week @ 2024-02-28 206/week @ 2024-03-06 225/week @ 2024-03-13 389/week @ 2024-03-20

1,126 downloads per month
Used in 4 crates

Apache-2.0

1MB
11K SLoC

Speedy2D

Crate Documentation CI

Hardware-accelerated drawing of shapes, images, and text, with an easy to use API.

Speedy2D aims to be:

  • The simplest Rust API for creating a window, rendering graphics/text, and handling input
  • Compatible with any device supporting OpenGL 2.0+ or WebGL 2.0. Support for OpenGL ES 2.0+ is planned
  • Very fast

Supports Windows, Mac, Linux, and WebGL. Support for Android and iOS is in development.

By default, Speedy2D contains support for setting up a window with an OpenGL context, and receiving input events. If you'd like to handle this yourself, and use Speedy2D only for rendering, you can disable the windowing feature.

Features

Windows Mac Linux Web
Draw 2D shapes ✔️ ✔️ ✔️ ✔️
Load fonts and draw text ✔️ ✔️ ✔️ ✔️
Load and draw images ✔️ ✔️ ✔️ ✔️
Mouse events ✔️ ✔️ ✔️ ✔️
Keyboard events ✔️ ✔️ ✔️ ✔️
Fullscreen ✔️ ✔️ ✔️ ✔️
Window control ✔️ ✔️ ✔️ ℹ️ Partial
DPI/scale change events ✔️ ✔️ ✔️ ✔️
System clock/timer ✔️ ✔️ ✔️ ✔️

Example code

The example projects can be run using cargo run --example=hello_world (just change hello_world to the name of the example source file).

Screenshot

Quick Start (Windows/Mac/Linux)

Step 1: Add Speedy2D to your Cargo.toml dependencies:

[dependencies]
speedy2d = "2.1.0"

Step 2: Create a window:

use speedy2d::Window;

let window = Window::new_centered("Title", (640, 480)).unwrap();

Step 3: Create a struct implementing the WindowHandler trait. Override whichever callbacks you're interested in, for example on_draw(), on_mouse_move(), or on_key_down().

use speedy2d::color::Color;
use speedy2d::window::{WindowHandler, WindowHelper};
use speedy2d::Graphics2D;

struct MyWindowHandler {}

impl WindowHandler for MyWindowHandler
{
    fn on_draw(&mut self, helper: &mut WindowHelper, graphics: &mut Graphics2D)
    {
        graphics.clear_screen(Color::from_rgb(0.8, 0.9, 1.0));
        graphics.draw_circle((100.0, 100.0), 75.0, Color::BLUE);

        // Request that we draw another frame once this one has finished
        helper.request_redraw();
    }

   // If desired, on_mouse_move(), on_key_down(), etc...
}

Step 4: Finally, start the event loop by passing your new WindowHandler to the run_loop() function.

window.run_loop(MyWindowHandler{});

That's it!

For a more detailed getting started guide, including a full list of WindowHandler callbacks, and how to render text, go to docs.rs/speedy2d.

The full code of the above example is below for your convenience:

use speedy2d::color::Color;
use speedy2d::{Graphics2D, Window};
use speedy2d::window::{WindowHandler, WindowHelper};

fn main() {
    let window = Window::new_centered("Title", (640, 480)).unwrap();
    window.run_loop(MyWindowHandler{});
}

struct MyWindowHandler {}

impl WindowHandler for MyWindowHandler
{
    fn on_draw(&mut self, helper: &mut WindowHelper, graphics: &mut Graphics2D)
    {
        graphics.clear_screen(Color::from_rgb(0.8, 0.9, 1.0));
        graphics.draw_circle((100.0, 100.0), 75.0, Color::BLUE);
        helper.request_redraw();
    }
}

Alternative: Managing the GL context yourself

If you'd rather handle the window creation and OpenGL context management yourself, simply disable Speedy2D's windowing feature in your Cargo.toml file, and create a context as follows. You will need to specify a loader function to allow Speedy2D to obtain the OpenGL function pointers.

use speedy2d::GLRenderer;

let mut renderer = unsafe {
    GLRenderer::new_for_gl_context((640, 480), |fn_name| {
        window_context.get_proc_address(fn_name) as *const _
    })
}.unwrap();

Then, draw a frame using GLRenderer::draw_frame():

renderer.draw_frame(|graphics| {
    graphics.clear_screen(Color::WHITE);
    graphics.draw_circle((100.0, 100.0), 75.0, Color::BLUE);
});

WebGL

Full tutorial for using Speedy2D with WebGL

To use Speedy2D with WebGL, your app must be compiled for WebAssembly. Speedy2D can attach itself to a canvas on the page using an ID you specify.

As with Windows/Mac/Linux targets, it's possible to use Speedy2D either in a full rendering and event handling configuation, or for rendering only.

For rendering only, use the following API:

  • GLRenderer::new_for_web_canvas_by_id()

For full keyboard/mouse/etc event handling in addition to rendering, use:

  • WebCanvas::new_for_id()
  • WebCanvas::new_for_id_with_user_events()

After initialization, the usual WindowHandler callbacks and WindowHelper/Graphics2D APIs should operate as on other platforms.

For an example, see the examples/webgl directory. To build this, first install the prerequisites:

cargo install wasm-bindgen-cli just

Then use the following command to run the build:

just build-example-webgl

License

Speedy2D is licensed under the Apache license, version 2.0. See LICENSE for more details.

Contributing

Pull requests for Speedy2D are always welcome. Please ensure the following checks pass locally before submitting.

Note: the automated tests currently only run on Linux.

cargo test
cargo test --no-default-features --lib --examples --tests
cargo clippy
cargo +nightly fmt -- --check
cargo doc
cargo build --target wasm32-unknown-unknown
cargo build --target wasm32-unknown-unknown --no-default-features

These commands can be run automatically using just:

just precommit

Some tests require the ability to create a headless OpenGL context.

Dependencies

~7–15MB
~269K SLoC