nightshade-api 0.43.0

Procedural high level API for the nightshade game engine
Documentation
use nightshade_api::prelude::*;

struct Game {
    player: Entity,
    hud: Entity,
    banner: Entity,
    rings: Vec<Entity>,
    popups: Vec<(Entity, f32)>,
    won: bool,
}

fn main() {
    run(
        |world| {
            set_background(world, Background::Sunset);
            set_bloom(world, true);
            let floor = spawn_floor(world, 25.0);
            set_texture(world, floor, "checkerboard");
            set_texture_tiling(world, floor, 6.0);

            let mut rings = Vec::new();
            for index in 0..12 {
                let angle = index as f32 / 12.0 * std::f32::consts::TAU;
                let radius = 6.0 + (index % 3) as f32 * 4.0;
                let ring = spawn_object(
                    world,
                    Object {
                        shape: Shape::Torus,
                        position: vec3(angle.cos() * radius, 0.8, angle.sin() * radius),
                        scale: vec3(0.5, 0.5, 0.5),
                        color: GOLD,
                        ..Object::default()
                    },
                );
                set_emissive(world, ring, [1.0, 0.7, 0.1], 6.0);
                rings.push(ring);
            }

            let player = first_person(world, vec3(0.0, 1.2, 18.0));
            let hud = spawn_text(world, "rings left: 12", ScreenAnchor::TopLeft);
            set_text_color(world, hud, GOLD);
            set_text_size(world, hud, 30.0);
            let banner = spawn_text(world, "", ScreenAnchor::Center);
            set_text_color(world, banner, GREEN);
            set_text_size(world, banner, 64.0);

            Game {
                player,
                hud,
                banner,
                rings,
                popups: Vec::new(),
                won: false,
            }
        },
        |world, game| {
            let here = position(world, game.player);
            let step = delta_time(world);
            let popups = &mut game.popups;
            game.rings.retain(|&ring| {
                rotate(world, ring, Vec3::y(), step * 2.0);
                let spot = position(world, ring);
                let offset = spot - here;
                if vec3(offset.x, 0.0, offset.z).magnitude() > 1.6 {
                    return true;
                }
                emit_burst(world, spot, GOLD, 60);
                shake_camera(world, 0.05, 0.15);
                let popup = spawn_label(world, "+1 RING", spot + vec3(0.0, 1.0, 0.0));
                set_text_color(world, popup, GOLD);
                set_text_size(world, popup, 30.0);
                popups.push((popup, 0.0));
                despawn(world, ring);
                false
            });
            game.popups.retain_mut(|(label, age)| {
                *age += step;
                if *age > 1.4 {
                    despawn(world, *label);
                    return false;
                }
                let at = position(world, *label);
                set_position(world, *label, vec3(at.x, at.y + step * 1.3, at.z));
                let fade = 1.0 - *age / 1.4;
                set_text_color(world, *label, [GOLD[0], GOLD[1], GOLD[2], fade]);
                true
            });
            set_text(
                world,
                game.hud,
                &format!("rings left: {}", game.rings.len()),
            );
            if game.rings.is_empty() && !game.won {
                game.won = true;
                set_text(world, game.banner, "YOU WIN");
            }
        },
    )
    .unwrap();
}