nightshade-api
A procedural high level API over the nightshade engine. Write full 3d scenes and small games as straight-line code: free functions, plain data, no trait to implement, no callbacks to wire up.
The engine's own hello world is a State impl with a camera, a sun, and dirty-flagged transform math. Here it is through this crate:
use *;
open() gives you a lit, navigable scene before your first line runs: procedural sky, sun with shadows, reference grid, orbit camera focused on the origin, prototype textures, and escape to exit. Every knob is one call to change.
Getting Started
[]
= "0.43.0"
Two ways to run
Own the loop. Setup is code before the loop, game state is locals across iterations. Native only:
let mut app = open;
spawn_floor;
let mut score = 0;
while frame
Or hand the engine the loop with run, which also works on wasm. Setup returns your state and the update closure receives it back every frame:
run
.unwrap;
run returns a Result, so a real main returns it rather than unwrapping. For more than one per-frame job, the run! macro takes any number of update systems, run in order over the state setup returns:
Each system is a fn(&mut World, &mut Data) or a non-capturing closure of that shape.
Vocabulary
Two verbs carry the lifetime rules. spawn_ is retained and lives until you despawn it. draw_ is immediate and visible for exactly one frame.
| Area | Calls |
|---|---|
| Scene | spawn_cube, spawn_sphere, spawn_floor, spawn_model, spawn_object, set_visible |
| Batches | spawn_objects (shared material), spawn_instanced (one draw call) |
| Tags | tag, untag, has_tag, tagged, for_each_tagged, for_each_with_position |
| Looks | set_color, set_metallic_roughness, set_emissive, set_texture, load_texture, spawn_decal |
| Placement | set_position, rotate, set_scale, set_parent, position |
| Animation | animate_position, animate_scale, animate_color, shake_camera |
| Effects | emit_fire, emit_smoke, emit_burst, spawn_cloth_sheet |
| Cameras | orbit_camera, fly_camera, first_person, fixed_camera, look_at |
| Environment | set_background, show_grid, set_fog, set_bloom, set_time_of_day, set_exposure, set_depth_of_field |
| Lights | point_light, spot_light, set_sun |
| Input | key_down, key_pressed, wasd, axis, mouse_clicked, mouse_position |
| Picking | clicked_entity, entity_under_cursor, cursor_on_ground |
| Physics | Body::Dynamic on spawn_object, push, set_velocity, raycast, collisions |
| Joints | attach_fixed, attach_hinge, attach_spring, attach_rope |
| Navigation | bake_navmesh, spawn_walker, walk_to, set_walk_speed, stop_walking |
| Immediate | draw_cube, draw_sphere, draw_line, draw_text_3d |
| Text | spawn_text, set_text, spawn_label |
| Audio | load_sound, play_sound, play_sound_at, play_sound_looping, set_volume |
spawn_object covers the loaded case in one struct literal:
let ball = spawn_object;
Examples
Short programs that do a lot, in examples/. From the repo root:
| Example | Shows |
|---|---|
spinning_cube |
The minimal program |
gallery |
Primitives, a metallic and roughness sweep, emissive, textures |
solar_system |
Orbital motion, parenting, emissive sun, bloom |
physics_playground |
A block tower, projectiles, click interaction, HUD text |
fps_walk |
First person walking with collision in fifteen lines |
collector |
A complete walk and collect game with a win condition |
juice |
Tweens, easing, particle bursts, and camera shake |
poster |
Rendering a composed scene straight to a png, no window |
model_viewer |
Animated glb loading (pass a path, defaults to the fox) |
hud |
Anchored screen text, live fps, runtime setting toggles |
day_night |
Time of day, fog, point lights, a procedural skyline |
parity |
The same workload api-spelled and longhand-spelled, timed |
Set NIGHTSHADE_API_FRAMES=120 to exit after a frame budget, which is what just test-examples uses to smoke test every example against the real renderer.
Running on the web
Every example also runs in the browser. Serve one with trunk, the same pipeline the engine's apps use:
That relies on the index.html and Trunk.toml in this crate (the canvas page plus the wasm build settings), so a project of your own needs an equivalent pair next to its Cargo.toml. Because the browser owns the loop, the examples use the portable run(setup, update) form rather than the native open()/frame() loop. poster is the one with a split: it writes a png natively and renders the same scene to the canvas on the web.
Dropping down to the engine
Every function takes the engine's World and bottoms out in normal nightshade calls. When a program outgrows the facade, replace one call site at a time. The full engine is re-exported at nightshade_api::nightshade:
use *;
Features
default = ["audio", "physics", "gamepad", "picking", "navmesh"], each forwarding to the engine features of the same names.
License
Dual-licensed under either of:
- MIT License (LICENSE-MIT or http://opensource.org/licenses/MIT)
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
at your option.