pix-engine 0.5.4

A cross-platform graphics/UI engine framework for simple games, visualizations, and graphics demos.
Documentation

PixEngine

Build Status Latest Version Doc Status Downloads License

Table of Contents

Summary

pix_engine is a cross-platform graphics & UI library for simple games, visualizations, digital art, and graphics applications written in Rust, supporting SDL2 (and soon Web-Assembly!) renderers.

The primary goal of this library is to be simple to setup and use for graphics or algorithm exploration and is not meant to be as fully-featured as other, larger graphics libraries.

It is intended to be more than just a toy library, however, and can be used to drive real applications. The Tetanes NES emulator, for example uses pix_engine for rendering, window and event handling.

Some examples of things you can create with pix-engine:

  • 2D ray casting of scenes or objects.
  • 2D games like Asteroids, Tetris, Pong, or platformers including sound effects, music and UI elements.
  • User interfaces for basic applications or configuration.
  • Algorithm visualizations for sorting, searching, or particle simulations.
  • Image viewing and editing.
  • Visual art.

Minimum Supported Rust Version

The current minimum Rust version is 1.57.0.

Screenshots

        

Getting Started

Installing Dependencies

First and foremost you'll need Rust installed! Follow the latest directions at https://www.rust-lang.org/learn/get-started.

When building or running applications for a desktop target such as macOS, Linux, or Windows and not a Web-Assembly target, you must install SDL2 libraries.

There are several options for installing SDL2, but these are the most common:

  • Install via homebrew for macOS, a package management tool like apt for Linux or MSVC for Windows.
  • vcpkg which will download and install the dependencies for you.

For more details and installation options see the rust-sdl2 documentation.

macOS with homebrew

brew install sdl2 sdl2_gfx sdl2_image sdl2_mixer sdl2_ttf

Linux

Ubuntu:

sudo apt-get install libsdl2-dev libsdl2-gfx-dev libsdl2-image-dev libsdl2-mixer-dev libsdl2-ttf-dev

Fedora:

sudo dnf install SDL2-devel SDL2_gfx-devel SDL2_image-devel SDL2_mixer-devel SDL2_ttf-devel

Arch:

sudo pacman -S sdl2 sdl2_gfx sdl2_image sdl2_mixer sdl2_ttf

Windows (MSVC)

  1. Download MSVC development libraries from http://www.libsdl.org/ (SDL2-devel-2.0.XX-VC.zip).
  2. Unzip SDL2-devel-2.0.XX-VC.zip into a folder.
  3. Copy library files from SDL2-2.0.XX\lib\x64\ to C:\Users\{Username}\.rustup\toolchains\{current toolchain}\lib\rustlib\{current toolchain}\lib where current toolchain is likely stable-x86_64-pc-windows-msvc.
    • Note: If you don't use rustup, See rust-sdl2 for more info on Windows installation.
  4. Copy SDL2.dll from SDL2-2.0.XX\lib\x64\ to your cargo project next to Cargo.toml.

macOS, Linux and Windows with vcpkg

vcpkg can download and install the correct versions for you, but requires some setup.

Add the following to your Cargo.toml:

[dependencies]
pix-engine = { version = "0.5.4", features = ["vcpkg"] }

[package.metadata.vcpkg]
dependencies = ["sdl2", "sdl2-image[libjpeg-turbo,tiff,libwebp]", "sdl2-ttf", "sdl2-gfx", "sdl2-mixer"]
git = "https://github.com/microsoft/vcpkg"
rev = "261c458af6e3eed5d099144aff95d2b5035f656b"

[package.metadata.vcpkg.target]
x86_64-pc-windows-msvc = { triplet = "x64-windows-static-md" }

Then build your project like this:

cargo install cargo-vcpkg
cargo vcpkg build
cargo build

Creating Your Application

Creating a visual or interactive application using pix-engine requires implementing only a single method of the AppState trait for your application: AppState::on_update which gets executed as often as possible. Within that function you'll have access to a mutable PixState object which provides several methods for modifying settings and drawing to the screen.

AppState provides additional methods that can be implemented to respond to user events and handle application startup and teardown.

Here's an example application which simply draws a circle following the mouse and renders it white or black depending if the mouse is held down or not:

use pix_engine::prelude::*;

struct MyApp;

impl AppState for MyApp {
    // Set up application state and initial settings. `PixState` contains
    // engine specific state and utility methods for actions like getting mouse
    // coordinates, drawing shapes, etc. (Optional)
    fn on_start(&mut self, s: &mut PixState) -> PixResult<()> {
        // Set the background to GRAY and clear the screen.
        s.background(Color::GRAY);

        // Change the font family to NOTO and size to 16 instead of using the
        // defaults.
        s.font_family(Font::NOTO)?;
        s.font_size(16);

        // Returning `Err` instead of `Ok` would indicate initialization failed,
        // and that the application should terminate immediately.
        Ok(())
    }

    // Main update/render loop. Called as often as possible unless
    // `target_frame_rate` was set with a value. (Required)
    fn on_update(&mut self, s: &mut PixState) -> PixResult<()> {
        // Set fill color to black if mouse is pressed, otherwise wite.
        if s.mouse_pressed() {
            s.fill(0);
        } else {
            s.fill(255);
        }

        // Draw a circle with fill color at the mouse position with a radius of
        // 80.
        let m = s.mouse_pos();
        s.circle([m.x(), m.y(), 80])?;

        Ok(())
    }

    // Clean up any state or resources before exiting such as deleting temporary
    // files or saving game state. (Optional)
    fn on_stop(&mut self, s: &mut PixState) -> PixResult<()> {
        Ok(())
    }
}

fn main() -> PixResult<()> {
    let mut engine = PixEngine::builder()
      .with_dimensions(800, 600)
      .with_title("MyApp")
      .with_frame_rate()
      .resizable()
      .build()?;
    let mut app = MyApp;
    engine.run(&mut app)
}

Crate Features

Logging

This library uses the log crate. To leverage logging in your application, choose one of the supported logger implementations and initialize it in your main function.

Example using env_logger:

fn main() -> PixResult<()> {
    env_logger::init();

    let mut engine = PixEngine::builder()
      .with_dimensions(800, 600)
      .with_title("MyApp")
      .build()?;
    let mut app = MyApp;
    engine.run(&mut app)
}

Utility Features

  • serde - Adds serde Serialize/Deserialize implementations for all enums/structs.

  • backtrace - Enables the backtrace feature for anyhow, which allows printing backtraces based on environment variables outlined in std::backtrace. Useful for debugging.

  • vcpkg - Enables static linking of the SDL2 libraries which are dependencies for macOS, Linux, and Windows targets. Using this feature is the easiest way to get up and running unless you already have SDL2 installed on your system.

Renderer Features

  • opengl - Forces sdl2 to use opengl as its renderer. This feature is disabled by default, allowing sdl2 to use whichever renderer it defaults to on the target system. For example, macOS defaults to metal.

Known Issues

See the github issue tracker.

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Contact

For issue reporting, please use the github issue tracker. You can also contact me directly at https://lukeworks.tech/contact/.

Credits

This has been a true passion project for several years and I can't thank the open source community enough for the all the amazing content and support.

A special shout out to the following projects which heavily inspired the implementation and evolution of this crate: