- World: 250x250 grid with 14 materials (sand, water, lava, stone, wood, etc.) - Physics: cellular automaton for materials + Verlet solver for entities - Entity: multi-cell humanoid (7 sub-bodies with distance constraints) - Render: terminal renderer with ANSI colors and diff-based updates - Game loop: fixed 60Hz timestep with accumulator pattern - Input: WASD movement, number keys for material painting
287 lines
9.6 KiB
Rust
287 lines
9.6 KiB
Rust
use crate::world::cell::MaterialId;
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
pub struct Material {
|
|
pub id: MaterialId,
|
|
pub name: &'static str,
|
|
pub density: f32,
|
|
pub solid: bool,
|
|
pub liquid: bool,
|
|
pub gas: bool,
|
|
pub static_: bool,
|
|
pub flammable: bool,
|
|
pub ignition_temp: f32,
|
|
pub melt_temp: f32,
|
|
pub heat_conductivity: f32,
|
|
pub color_fg: (u8, u8, u8),
|
|
pub color_bg: (u8, u8, u8),
|
|
pub display_char: char,
|
|
}
|
|
|
|
impl Material {
|
|
pub const fn empty() -> Self {
|
|
Self {
|
|
id: MaterialId::Empty,
|
|
name: "empty",
|
|
density: 0.0,
|
|
solid: false,
|
|
liquid: false,
|
|
gas: false,
|
|
static_: true,
|
|
flammable: false,
|
|
ignition_temp: f32::INFINITY,
|
|
melt_temp: f32::INFINITY,
|
|
heat_conductivity: 0.0,
|
|
color_fg: (0, 0, 0),
|
|
color_bg: (0, 0, 0),
|
|
display_char: ' ',
|
|
}
|
|
}
|
|
}
|
|
|
|
pub struct MaterialRegistry {
|
|
materials: [Material; 14],
|
|
}
|
|
|
|
impl MaterialRegistry {
|
|
fn new() -> Self {
|
|
Self {
|
|
materials: [
|
|
Material {
|
|
id: MaterialId::Empty,
|
|
name: "empty",
|
|
density: 0.0,
|
|
solid: false,
|
|
liquid: false,
|
|
gas: false,
|
|
static_: true,
|
|
flammable: false,
|
|
ignition_temp: f32::INFINITY,
|
|
melt_temp: f32::INFINITY,
|
|
heat_conductivity: 0.0,
|
|
color_fg: (15, 15, 20),
|
|
color_bg: (10, 10, 15),
|
|
display_char: ' ',
|
|
},
|
|
Material {
|
|
id: MaterialId::Sand,
|
|
name: "sand",
|
|
density: 1.5,
|
|
solid: true,
|
|
liquid: false,
|
|
gas: false,
|
|
static_: false,
|
|
flammable: false,
|
|
ignition_temp: f32::INFINITY,
|
|
melt_temp: 1700.0,
|
|
heat_conductivity: 0.2,
|
|
color_fg: (218, 178, 90),
|
|
color_bg: (60, 50, 30),
|
|
display_char: '.',
|
|
},
|
|
Material {
|
|
id: MaterialId::Water,
|
|
name: "water",
|
|
density: 1.0,
|
|
solid: false,
|
|
liquid: true,
|
|
gas: false,
|
|
static_: false,
|
|
flammable: false,
|
|
ignition_temp: f32::INFINITY,
|
|
melt_temp: 0.0,
|
|
heat_conductivity: 0.4,
|
|
color_fg: (64, 128, 220),
|
|
color_bg: (20, 40, 80),
|
|
display_char: '~',
|
|
},
|
|
Material {
|
|
id: MaterialId::Stone,
|
|
name: "stone",
|
|
density: 3.0,
|
|
solid: true,
|
|
liquid: false,
|
|
gas: false,
|
|
static_: true,
|
|
flammable: false,
|
|
ignition_temp: f32::INFINITY,
|
|
melt_temp: 1200.0,
|
|
heat_conductivity: 0.3,
|
|
color_fg: (120, 120, 130),
|
|
color_bg: (40, 40, 50),
|
|
display_char: '#',
|
|
},
|
|
Material {
|
|
id: MaterialId::Lava,
|
|
name: "lava",
|
|
density: 2.5,
|
|
solid: false,
|
|
liquid: true,
|
|
gas: false,
|
|
static_: false,
|
|
flammable: false,
|
|
ignition_temp: f32::INFINITY,
|
|
melt_temp: f32::INFINITY,
|
|
heat_conductivity: 0.5,
|
|
color_fg: (255, 80, 20),
|
|
color_bg: (120, 20, 0),
|
|
display_char: '#',
|
|
},
|
|
Material {
|
|
id: MaterialId::Wood,
|
|
name: "wood",
|
|
density: 0.8,
|
|
solid: true,
|
|
liquid: false,
|
|
gas: false,
|
|
static_: true,
|
|
flammable: true,
|
|
ignition_temp: 300.0,
|
|
melt_temp: f32::INFINITY,
|
|
heat_conductivity: 0.1,
|
|
color_fg: (140, 90, 50),
|
|
color_bg: (50, 30, 20),
|
|
display_char: 'T',
|
|
},
|
|
Material {
|
|
id: MaterialId::Flesh,
|
|
name: "flesh",
|
|
density: 1.06,
|
|
solid: true,
|
|
liquid: false,
|
|
gas: false,
|
|
static_: false,
|
|
flammable: true,
|
|
ignition_temp: 200.0,
|
|
melt_temp: f32::INFINITY,
|
|
heat_conductivity: 0.15,
|
|
color_fg: (180, 50, 50),
|
|
color_bg: (60, 15, 15),
|
|
display_char: '%',
|
|
},
|
|
Material {
|
|
id: MaterialId::Bone,
|
|
name: "bone",
|
|
density: 1.8,
|
|
solid: true,
|
|
liquid: false,
|
|
gas: false,
|
|
static_: true,
|
|
flammable: false,
|
|
ignition_temp: f32::INFINITY,
|
|
melt_temp: f32::INFINITY,
|
|
heat_conductivity: 0.1,
|
|
color_fg: (220, 210, 190),
|
|
color_bg: (60, 55, 50),
|
|
display_char: '`',
|
|
},
|
|
Material {
|
|
id: MaterialId::Steam,
|
|
name: "steam",
|
|
density: 0.3,
|
|
solid: false,
|
|
liquid: false,
|
|
gas: true,
|
|
static_: false,
|
|
flammable: false,
|
|
ignition_temp: f32::INFINITY,
|
|
melt_temp: f32::INFINITY,
|
|
heat_conductivity: 0.2,
|
|
color_fg: (200, 200, 220),
|
|
color_bg: (30, 30, 40),
|
|
display_char: '~',
|
|
},
|
|
Material {
|
|
id: MaterialId::Fire,
|
|
name: "fire",
|
|
density: 0.1,
|
|
solid: false,
|
|
liquid: false,
|
|
gas: true,
|
|
static_: false,
|
|
flammable: false,
|
|
ignition_temp: f32::INFINITY,
|
|
melt_temp: f32::INFINITY,
|
|
heat_conductivity: 0.6,
|
|
color_fg: (255, 160, 40),
|
|
color_bg: (100, 30, 0),
|
|
display_char: '^',
|
|
},
|
|
Material {
|
|
id: MaterialId::Acid,
|
|
name: "acid",
|
|
density: 1.2,
|
|
solid: false,
|
|
liquid: true,
|
|
gas: false,
|
|
static_: false,
|
|
flammable: false,
|
|
ignition_temp: f32::INFINITY,
|
|
melt_temp: f32::INFINITY,
|
|
heat_conductivity: 0.3,
|
|
color_fg: (100, 255, 60),
|
|
color_bg: (20, 60, 10),
|
|
display_char: '~',
|
|
},
|
|
Material {
|
|
id: MaterialId::Smoke,
|
|
name: "smoke",
|
|
density: 0.2,
|
|
solid: false,
|
|
liquid: false,
|
|
gas: true,
|
|
static_: false,
|
|
flammable: false,
|
|
ignition_temp: f32::INFINITY,
|
|
melt_temp: f32::INFINITY,
|
|
heat_conductivity: 0.1,
|
|
color_fg: (100, 100, 100),
|
|
color_bg: (20, 20, 20),
|
|
display_char: '*',
|
|
},
|
|
Material {
|
|
id: MaterialId::Grass,
|
|
name: "grass",
|
|
density: 1.0,
|
|
solid: true,
|
|
liquid: false,
|
|
gas: false,
|
|
static_: true,
|
|
flammable: true,
|
|
ignition_temp: 250.0,
|
|
melt_temp: f32::INFINITY,
|
|
heat_conductivity: 0.1,
|
|
color_fg: (80, 200, 60),
|
|
color_bg: (20, 50, 15),
|
|
display_char: '"',
|
|
},
|
|
Material {
|
|
id: MaterialId::Dirt,
|
|
name: "dirt",
|
|
density: 1.3,
|
|
solid: true,
|
|
liquid: false,
|
|
gas: false,
|
|
static_: true,
|
|
flammable: false,
|
|
ignition_temp: f32::INFINITY,
|
|
melt_temp: f32::INFINITY,
|
|
heat_conductivity: 0.2,
|
|
color_fg: (100, 70, 50),
|
|
color_bg: (40, 30, 20),
|
|
display_char: ':',
|
|
},
|
|
],
|
|
}
|
|
}
|
|
|
|
pub fn get(&self, id: MaterialId) -> &Material {
|
|
&self.materials[id as usize]
|
|
}
|
|
|
|
pub fn instance() -> &'static MaterialRegistry {
|
|
static REGISTRY: std::sync::OnceLock<MaterialRegistry> = std::sync::OnceLock::new();
|
|
REGISTRY.get_or_init(MaterialRegistry::new)
|
|
}
|
|
}
|