Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Installation

Nightshade requires Rust 1.90 or newer with the 2024 edition, and a graphics driver supporting Vulkan 1.2, Metal, or DirectX 12.

Starting from the template

The fastest path is the template repository. It is a working project with the build scripts, CI, and WASM configuration already in place.

git clone https://github.com/matthewjberger/nightshade-template my-game
cd my-game
just run

The window opens onto a 3D scene with a nebula skybox, a ground grid, and a pan-orbit camera. That is the starting point. Edit src/main.rs to make it your game.

What the template contains

The template ships with the following files:

  • src/main.rs is a minimal State implementation with a camera and a sun.
  • Cargo.toml has the Nightshade dependency with default features enabled.
  • justfile defines run, lint, test, and deployment commands for native, WASM, and Steam Deck.
  • index.html and Trunk.toml configure the WASM web build.
  • .github/workflows/ runs clippy, tests, and the WASM build on CI, and deploys to GitHub Pages.
  • rust-toolchain pins the Rust version and adds the WASM target.

The starter src/main.rs looks like this:

use nightshade::prelude::*;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    launch(Template)?;
    Ok(())
}

#[derive(Default)]
struct Template;

impl State for Template {
    fn initialize(&mut self, world: &mut World) {
        world.resources.window.title = "Template".to_string();
        world.resources.user_interface.enabled = true;
        world.resources.graphics.show_grid = true;
        world.resources.graphics.atmosphere = Atmosphere::Nebula;
        spawn_sun(world);
        let camera_entity = spawn_pan_orbit_camera(
            world,
            Vec3::new(0.0, 0.0, 0.0),
            15.0,
            0.0,
            std::f32::consts::FRAC_PI_4,
            "Main Camera".to_string(),
        );
        world.resources.active_camera = Some(camera_entity);
    }

    fn run_systems(&mut self, world: &mut World) {
        pan_orbit_camera_system(world);
    }

    fn on_keyboard_input(
        &mut self,
        world: &mut World,
        key_code: KeyCode,
        key_state: ElementState,
    ) {
        if matches!((key_code, key_state), (KeyCode::KeyQ, ElementState::Pressed)) {
            world.resources.window.should_exit = true;
        }
    }
}

Justfile commands

CommandDescription
just runBuild and run in release mode
just run-wasmBuild for the web and open the browser
just lintRun clippy with warnings as errors
just testRun the test suite
just build-wasmBuild the WASM release without serving

Use just run rather than cargo run directly. The justfile carries the flags the build needs.

Feature flags

Subsystems are opt-in through Cargo features. Add them in Cargo.toml:

[dependencies]
nightshade = { version = "0.13", features = ["physics", "audio"] }
FeatureDescription
physicsRapier3D physics simulation
audioKira audio playback
gamepadGamepad input via gilrs
navmeshRecast navigation mesh
grassGPU grass rendering
steamSteamworks integration

The full list is in the Feature Flags appendix.

Platform notes

On Windows, DirectX 12 is the default backend. Update the graphics drivers if shaders fail to compile.

On macOS, Metal is selected automatically. Nothing else is required.

On Linux, Vulkan is required. Install the runtime and headers through the system package manager:

# Ubuntu/Debian
sudo apt install vulkan-tools libvulkan-dev

# Fedora
sudo dnf install vulkan-tools vulkan-loader-devel

# Arch
sudo pacman -S vulkan-tools vulkan-icd-loader

On the web, WebGPU support is required. Chrome 113+, Edge 113+, and Firefox 121+ work out of the box. The template's just run-wasm uses Trunk to compile and serve the page.