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

bevy_lights

Practical lights for Bevy 0.20: the fires a scene’s props actually carry. A world can hold thousands of torches and afford a dozen real lights, so this crate ranks the candidates by the light they put on you, hands the budget out without a pop, modulates each light the way a fire’s light moves, and draws the flame that motivates it — with sparks, smoke, tongues for a wide fire and a bed of coals that goes on glowing after the fire is put out.

Add it

cargo add bevy_lights
use bevy::prelude::*;
use bevy_lights::*;

#[derive(Component)]
struct MyFocus;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_plugins((FlickerPlugin, LightPoolPlugin::<MyFocus>::default(), FlamePlugin, FirePlugin))
        .add_systems(Startup, |mut commands: Commands| {
            let fire = Fire::lit(FireKind::Campfire, 250.0, 0.35);
            commands.spawn((fire, Transform::from_xyz(4.0, 0.0, 2.0)));
            commands.spawn((MyFocus, Transform::default()));
        })
        .run();
}

Fire::lit(kind, lux, over) is a whole fire in one component: the kind’s flame, the light the pool hands it, its sparks, smoke, tongues and bed of coals. Or run it first: cargo run --release --example courtyard.

What it gives you

  • Fires that flicker, flare and go out (fires): Flicker dips a light below its base at the rate its fuel bed sets, Kindle flares it up over 0.6 s, Snuff puts it out over 1.2 s with the linked flame.
  • A budget of real lights for a town of thousands (the light pool): ranked by the light each candidate puts on you, held with hysteresis, cross-faded on a hand-off, with a shadow budget of its own and one template that reaches every light live.
  • The flame drawn where the fire is (shader flames): one additive billboard per fire, breathing on its light’s clock, in a hue of its own, shedding sparks, smoking, leaning in a wind and streaming behind a torch you carry — and going out when a wall hides its source.
  • Coals that outlive the flame (the fuel bed): a temperature field that breathes with the flicker, warms as the fire catches and cools over a minute once it is put out.
  • A cinematographer’s numbers (the lighting look): fire_lumens, fill_for, blackbody_colour and white_balanced turn “1000 lx at 4 m” and “1900 K” into a sized, coloured light.
  • Every curve outside the engine (engine-free maths): the same maths as plain f32 functions with no bevy in them, for a host that drives its own lights.
  • What a host touches, and what it saves (host API): the components and resources a game spawns, marks and reads, and the serde feature that makes a placed fire one line of a scene file.

Use it in the Cauldron

The Cauldron, the Coven’s level editor, takes bevy_lights as an optional cargo feature (bevy_lights) and a project lists it in its family.ron. Two things it does with the crate today:

  • A placement’s fire is the crate’s own settings type. family_set writes a field of the fire’s Flicker — base, phase, depth, diameter — in <project>/family/bevy_lights.ron, and the placed prop reads back as the crate’s Flicker, so the editor has no schema of its own for it. placement_set_family puts that value on one placement, or takes it off.
  • Two read-only operations answer “which of my torches are real, and how lit is this tile?” — light_pool runs the crate’s own LightPoolPlugin over the map’s fixtures and reads its PoolBudget for where the viewer stands, and light_map bakes a bevy_light_grid illuminance field from the same fixtures.

There is no panel for the fire kinds yet. One would edit Fire { kind, lumens, phase, color, embers, smoke, tongues, bed } — the whole fire as one serde value — and read Fire::problems() beside the fields, which is what every settings type in the crate returns: a list of Problem { field, kind } naming what cannot work, before the value reaches a light.