codecraft 0.1.1

A minimalist 3D game engine built on parts of Bevy (ECS, color) with wgpu and winit: OpenPBR materials, clustered lighting, an immediate-mode UI, audio and gamepad haptics
Documentation

codecraft

A minimalist 3D game engine in Rust, built on parts of Bevy (bevy_ecs, bevy_color) with wgpu and winit.

Experimental. This is an early, in-progress engine. The API will change between releases without notice, and there are no stability promises yet. It is published so it can be used and looked at, not because it is done.

Where it is at

Today codecraft is the renderer and app shell that grew inside a couple of small games, pulled out into a crate of its own. What is in it:

  • Rendering — physically based shading with OpenPBR materials, clustered lighting, a shadow-casting sun plus a second directional light, tonemapping to the display, and a wireframe/gizmo pass.
  • Scenes — an App runs one Scene at a time; a scene owns what it spawns and a scene change takes it all down. glTF meshes and code-built primitives (boxes, spheres, extrusions).
  • UI — an immediate-feeling, entity-backed UI: panels, buttons, headings, text, progress bars, an outliner, a frame profiler. Icons are Phosphor, the font is Monaspace; both are compiled in.
  • Input and feel — keyboard and mouse, an orbit camera rig, DualSense controllers over HID with haptics, trigger feedback, the lightbar and the pad's own speaker.
  • Audio — sound sets and looping voices through rodio.
  • Dev mode — F12 puts up a DEV badge with a menu, F11 an outliner of everything in the scene, F9 a profiler. A loopback control port can drive the app from a script and take screenshots of the actual frame.

The longer-term aim is a 3D, structure-first code editor. None of that exists yet; what is here is the engine underneath it.

A first scene

use codecraft::glam::Vec3;
use codecraft::prelude::*;
use codecraft::sceneobjects::lights::default_lights;
use codecraft::{Light, OrbitCamera, gizmos, primitives};

struct Hello;

impl Scene for Hello {
    fn setup(&mut self, app: &mut AppState) {
        app.spawn(gizmos::grid());

        // Lights are entities; a scene that spawns none has none.
        let [key, rim] = default_lights();
        app.spawn_entity((key, Light::item("Key Light")));
        app.spawn_entity((rim, Light::item("Rim Light")));

        app.spawn_primitive(
            primitives::Box::cube(1.0)
                .at(0.0, 0.5, 0.0)
                .color(Color::srgb(0.9, 0.45, 0.2)),
        );

        // Right-drag orbits, WASD walks, the wheel dollies.
        app.spawn_entity(OrbitCamera::new(Vec3::new(0.0, 0.5, 0.0), 5.0));
    }
}

fn main() {
    App::new("hello").scene(Hello).run();
}

Examples

Small ones ship with the crate:

cargo run --example cube    # a lit cube turning on a grid
cargo run --example menu    # two scenes and the buttons between them

Two games live in this repository as workspace members and are the real test of the engine:

cargo run -p tanks          # two-player tank battle, pads and haptics
cargo run -p chess          # 3D chess, playable on lichess

And cargo run on its own opens a blank scene with a grid, in dev mode.

Any app takes --headless to run without a window, and honours RENDERER_CONTROL_PORT=<port> to accept commands (screenshot <path>, key F12, quit, …) over loopback.

License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.

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.