diff --git a/art/generated/textures/materials/PROMPTS.md b/art/generated/textures/materials/PROMPTS.md index 4c48d8c..bc24a50 100644 --- a/art/generated/textures/materials/PROMPTS.md +++ b/art/generated/textures/materials/PROMPTS.md @@ -58,6 +58,15 @@ The spine of one old leather-bound book standing upright, filling the whole imag An open page of an old spellbook filling the whole image: yellowed parchment with many lines of dark handwritten script, a small drawn magic circle and a red initial letter, in light neutral tones. ``` +## crystal + +```text +A cut gemstone surface seen close: many sharp triangular and kite-shaped facets with bright edges and darker faces, a few internal glints, in light neutral grey tones. +``` + +The soul core's heart (its lobes) and the buildings use the materials too: `props::auto_cube` +picks one for every box of the buildings by its colour and shape. + ## Processing `tools/make_material.py` crops (stone and the book lay on white), turns the picture into grey @@ -74,6 +83,7 @@ python3 $T straw-raw.png straw --crop 0.05,0.05,0.95,0.95 python3 $T fur-raw.png fur python3 $T book-raw.png book --trim --mean 0.75 python3 $T paper-raw.png paper --color --crop 0.04,0.04,0.96,0.96 --mean 0.8 +python3 $T crystal-raw.png crystal --crop 0.1,0.1,0.9,0.9 --mean 0.75 ``` Copied to `assets/textures/mat/`. diff --git a/art/generated/textures/materials/batch.py b/art/generated/textures/materials/batch.py index 588c709..f90b565 100644 --- a/art/generated/textures/materials/batch.py +++ b/art/generated/textures/materials/batch.py @@ -11,6 +11,7 @@ MATS = { "fur": "Thick shaggy animal fur with tufts and strands, in light neutral beige-grey tones.", "book": "The spine of one old leather-bound book standing upright, filling the whole image: two raised bands near the top and the bottom, " "a gilded frame and a short line of golden title letters in the middle, worn leather, in light neutral tones.", + "crystal": "A cut gemstone surface seen close: many sharp triangular and kite-shaped facets with bright edges and darker faces, a few internal glints, in light neutral grey tones.", "paper": "An open page of an old spellbook filling the whole image: yellowed parchment with many lines of dark handwritten script, " "a small drawn magic circle and a red initial letter, in light neutral tones.", } diff --git a/art/generated/textures/materials/crystal-16.png b/art/generated/textures/materials/crystal-16.png new file mode 100644 index 0000000..2a4b09b Binary files /dev/null and b/art/generated/textures/materials/crystal-16.png differ diff --git a/art/generated/textures/materials/crystal-64.png b/art/generated/textures/materials/crystal-64.png new file mode 100644 index 0000000..68ddd41 Binary files /dev/null and b/art/generated/textures/materials/crystal-64.png differ diff --git a/art/generated/textures/materials/crystal-raw.png b/art/generated/textures/materials/crystal-raw.png new file mode 100644 index 0000000..ee46147 Binary files /dev/null and b/art/generated/textures/materials/crystal-raw.png differ diff --git a/assets/textures/mat/crystal-16.png b/assets/textures/mat/crystal-16.png new file mode 100644 index 0000000..2a4b09b Binary files /dev/null and b/assets/textures/mat/crystal-16.png differ diff --git a/assets/textures/mat/crystal-64.png b/assets/textures/mat/crystal-64.png new file mode 100644 index 0000000..68ddd41 Binary files /dev/null and b/assets/textures/mat/crystal-64.png differ diff --git a/src/gfx.rs b/src/gfx.rs index c92bebd..7db9ae2 100644 --- a/src/gfx.rs +++ b/src/gfx.rs @@ -106,8 +106,8 @@ pub struct Gfx { pub gear: Texture2D, // their gear parts (see GEAR_HELMET etc.) pub atlas_hd: Texture2D, // the tile atlas of the high-res style, 64x64 tiles (see HD_TILES) pub atlas_hd2: Texture2D, // the same with 128x128 tiles (close up) - pub materials: [Texture2D; 8], // furniture materials, high-res (see crate::props::Mat) - pub materials_px: [Texture2D; 8], // the same for the pixel-art style (16x16) + pub materials: [Texture2D; 9], // furniture materials, high-res (see crate::props::Mat) + pub materials_px: [Texture2D; 9], // the same for the pixel-art style (16x16) pub cursors: Texture2D, // mouse pointer frames, 16x16 each (see CURSOR_*) pub badges: Texture2D, // achievement badges, 32x32 each (see badges.rs) pub font: Texture2D, // Dinowyde (glyphs of 6x8 px ordered by Unicode, see font_slot) and DINOBYTE @@ -354,7 +354,7 @@ macro_rules! material { (include_bytes!(concat!("../assets/textures/mat/", $name, "-64.png")) as &[u8], include_bytes!(concat!("../assets/textures/mat/", $name, "-16.png")) as &[u8]) }; } -const MATERIALS: [(&[u8], &[u8]); 8] = [ +const MATERIALS: [(&[u8], &[u8]); 9] = [ material!("wood"), material!("stone"), material!("iron"), @@ -363,6 +363,7 @@ const MATERIALS: [(&[u8], &[u8]); 8] = [ material!("fur"), material!("book"), material!("paper"), + material!("crystal"), ]; // ---- high-res tiles diff --git a/src/props.rs b/src/props.rs index d92c060..dbb5aac 100644 --- a/src/props.rs +++ b/src/props.rs @@ -49,17 +49,57 @@ pub enum Mat { Fur, Book, Paper, + Crystal, } thread_local! { // the material textures of the current graphics style (set every frame, see set_materials) - static MATS: std::cell::RefCell> = std::cell::RefCell::new(None); + static MATS: std::cell::RefCell> = std::cell::RefCell::new(None); } -pub fn set_materials(m: &[Texture2D; 8]) { +pub fn set_materials(m: &[Texture2D; 9]) { MATS.with(|t| *t.borrow_mut() = Some(m.clone())); } +// the texture of a material in the current style +pub fn material(m: Mat) -> Option { + MATS.with(|t| t.borrow().as_ref().map(|a| a[m as usize].clone())) +} + +// the material of a box of the buildings (render3d: towers, the soul core's throne, gates, +// portals, traps) by its colour and shape: dark and grey blocks are stone (thin ones iron), +// brown is wood, gold and brass are metal, strong colours are cloth; translucent and bright +// glowing parts stay plain +fn auto_mat(s: Vec3, c: Color) -> Option { + if c.a < 0.99 { + return None; + } + let (mx, mn) = (c.r.max(c.g).max(c.b), c.r.min(c.g).min(c.b)); + let sat = if mx > 0.0 { (mx - mn) / mx } else { 0.0 }; + let thin = s.x.min(s.y).min(s.z) < 0.07; + if mx > 0.85 && sat > 0.45 { + return None; + } + if mx < 0.22 || sat < 0.2 { + return Some(if thin { Mat::Iron } else { Mat::Stone }); + } + if c.r > 0.6 && c.g > 0.45 && c.b < c.g * 0.6 { + return Some(Mat::Iron); + } + if c.r >= c.g && c.g >= c.b && mx < 0.8 { + return Some(Mat::Wood); + } + Some(Mat::Cloth) +} + +// a box of a building, textured by its material (see auto_mat) +pub fn auto_cube(p: Vec3, s: Vec3, c: Color) { + match auto_mat(s, c) { + Some(m) => mc(m, p, s, c), + None => draw_cube(p, s, None, c), + } +} + // a box of a material; the detail is a little darker than white, the colour makes up for it fn mc(m: Mat, p: Vec3, s: Vec3, c: Color) { let k = GROW.with(|g| g.get()).map_or(1.0, |g| g.1); diff --git a/src/render3d.rs b/src/render3d.rs index 0f74caa..b5be230 100644 --- a/src/render3d.rs +++ b/src/render3d.rs @@ -2167,7 +2167,7 @@ fn draw_dark_tower(tw: &Tower) { let iron = shade_c(58, 56, 64, f); let bone = shade_c(214, 204, 178, f); let blood = shade_c(128, 18, 26, f); - let bx = |p: Vec3, s: Vec3, cl: Color| draw_cube(c + p, s, None, cl); + let bx = |p: Vec3, s: Vec3, cl: Color| crate::props::auto_cube(c + p, s, cl); let skull = |p: Vec3, dir: Vec3| { bx(p, vec3(0.15, 0.14, 0.15), bone); let side = vec3(dir.z, 0.0, -dir.x); @@ -2240,11 +2240,11 @@ fn draw_dark_tower(tw: &Tower) { let (ax, az) = (tw.aim.cos(), tw.aim.sin()); let along = |d: f32, y: f32| c + vec3(ax * d, h + y, az * d); // the demon head: a heavy block with horns, its open jaw is the muzzle - draw_cube(along(0.0, 0.24), Vec3::splat(0.34), None, iron); + crate::props::auto_cube(along(0.0, 0.24), Vec3::splat(0.34), iron); for k in 1..4 { - draw_cube(along(k as f32 * 0.14, 0.24), Vec3::splat(0.3 - k as f32 * 0.02), None, shade_c(44, 42, 50, f)); + crate::props::auto_cube(along(k as f32 * 0.14, 0.24), Vec3::splat(0.3 - k as f32 * 0.02), shade_c(44, 42, 50, f)); } - draw_cube(along(0.56, 0.24), Vec3::splat(0.26), None, obs(20)); + crate::props::auto_cube(along(0.56, 0.24), Vec3::splat(0.26), obs(20)); for sgn in [-1.0f32, 1.0] { let side = vec3(-az * sgn, 0.0, ax * sgn); line3(along(0.05, 0.4) + side * 0.14, along(-0.1, 0.72) + side * 0.26, 0.07, bone); @@ -2309,7 +2309,7 @@ fn draw_towers_solid(g: &Game) { let f = 0.75 + tw.flash * 1.5; // brightens briefly when firing // knight towers: bright limestone with dark blue shadows, wood and fittings in royal blue let col = |r: u8, g: u8, b: u8| if tw.hero { knight_c(r, g, b, f) } else { shade_c(r, g, b, f) }; - let bx = |p: Vec3, s: Vec3, cl: Color| draw_cube(c + p, s, None, cl); + let bx = |p: Vec3, s: Vec3, cl: Color| crate::props::auto_cube(c + p, s, cl); match tw.kind { TowerKind::Arrow => { // stone plinth, masonry body with courses and arrow slits @@ -2414,7 +2414,7 @@ fn draw_towers_solid(g: &Game) { } // level pips on the plinth for k in 0..tw.level { - draw_cube(vec3(x - 0.2 + k as f32 * 0.2, 0.25, z + 0.46), Vec3::splat(0.09), None, Color::from_rgba(240, 200, 70, 255)); + crate::props::auto_cube(vec3(x - 0.2 + k as f32 * 0.2, 0.25, z + 0.46), Vec3::splat(0.09), Color::from_rgba(240, 200, 70, 255)); } } } @@ -2571,15 +2571,15 @@ fn ring(c: Vec3, r: f32, color: Color) { // the obsidian throne of a soul core (centre c on the floor) fn draw_throne(c: Vec3, t: f32) { let obs = |k: u8| Color::from_rgba(28 + k, 14 + k / 2, 20 + k / 2, 255); - draw_cube(c + vec3(0.0, 0.08, 0.0), vec3(2.9, 0.16, 2.9), None, obs(6)); - draw_cube(c + vec3(0.0, 0.22, 0.0), vec3(2.3, 0.14, 2.3), None, obs(14)); - draw_cube(c + vec3(0.0, 0.36, 0.0), vec3(1.5, 0.14, 1.5), None, obs(24)); - draw_cube(c + vec3(0.0, 0.48, 0.0), vec3(0.8, 0.1, 0.8), None, obs(32)); + crate::props::auto_cube(c + vec3(0.0, 0.08, 0.0), vec3(2.9, 0.16, 2.9), obs(6)); + crate::props::auto_cube(c + vec3(0.0, 0.22, 0.0), vec3(2.3, 0.14, 2.3), obs(14)); + crate::props::auto_cube(c + vec3(0.0, 0.36, 0.0), vec3(1.5, 0.14, 1.5), obs(24)); + crate::props::auto_cube(c + vec3(0.0, 0.48, 0.0), vec3(0.8, 0.1, 0.8), obs(32)); let heart = c + vec3(0.0, 1.55, 0.0); let iron = Color::from_rgba(70, 64, 72, 255); for (k, (dx, dz)) in [(-1.2f32, -1.2f32), (1.2, -1.2), (1.2, 1.2), (-1.2, 1.2)].iter().enumerate() { let b = c + vec3(*dx, 0.0, *dz); - draw_cube(b + vec3(0.0, 0.3, 0.0), vec3(0.36, 0.6, 0.36), None, obs(4)); + crate::props::auto_cube(b + vec3(0.0, 0.3, 0.0), vec3(0.36, 0.6, 0.36), obs(4)); // a curved spike leaning towards the heart let mut prev = b + vec3(0.0, 0.55, 0.0); for q in 1..=5 { @@ -2614,11 +2614,11 @@ fn draw_landmarks_solid(g: &Game, t: f32) { let h = (m.name % 7) as f32 * 0.02; let c = vec3(x as f32 + 0.5 + ((m.name >> 3) % 5) as f32 * 0.04 - 0.08, 0.0, y as f32 + 0.5); let stone = Color::from_rgba(118, 114, 124, 255); - draw_cube(c + vec3(0.0, 0.04, 0.0), vec3(0.42, 0.08, 0.26), None, Color::from_rgba(70, 66, 74, 255)); - draw_cube(c + vec3(0.0, 0.3 + h * 0.5, 0.0), vec3(0.3, 0.46 + h, 0.1), None, stone); - draw_cube(c + vec3(0.0, 0.56 + h, 0.0), vec3(0.2, 0.06, 0.1), None, stone); + crate::props::auto_cube(c + vec3(0.0, 0.04, 0.0), vec3(0.42, 0.08, 0.26), Color::from_rgba(70, 66, 74, 255)); + crate::props::auto_cube(c + vec3(0.0, 0.3 + h * 0.5, 0.0), vec3(0.3, 0.46 + h, 0.1), stone); + crate::props::auto_cube(c + vec3(0.0, 0.56 + h, 0.0), vec3(0.2, 0.06, 0.1), stone); let glow = if m.level >= 8 { Color::from_rgba(255, 210, 90, 255) } else { Color::from_rgba(150, 120, 255, 255) }; - draw_cube(c + vec3(0.0, 0.34 + h * 0.5, 0.052), vec3(0.06, 0.14, 0.01), None, glow); + crate::props::auto_cube(c + vec3(0.0, 0.34 + h * 0.5, 0.052), vec3(0.06, 0.14, 0.01), glow); } // a ranger's snares: iron jaws on the floor, open and waiting for &i in &g.snares { @@ -2629,12 +2629,12 @@ fn draw_landmarks_solid(g: &Game, t: f32) { let c = vec3(x as f32 + 0.5, 0.0, y as f32 + 0.5); let iron = Color::from_rgba(96, 92, 100, 255); let dark = Color::from_rgba(40, 36, 42, 255); - draw_cube(c + vec3(0.0, 0.02, 0.0), vec3(0.34, 0.03, 0.34), None, dark); + crate::props::auto_cube(c + vec3(0.0, 0.02, 0.0), vec3(0.34, 0.03, 0.34), dark); for side in [-1.0f32, 1.0] { - draw_cube(c + vec3(side * 0.16, 0.06, 0.0), vec3(0.04, 0.08, 0.36), None, iron); + crate::props::auto_cube(c + vec3(side * 0.16, 0.06, 0.0), vec3(0.04, 0.08, 0.36), iron); for k in 0..3 { let z = -0.12 + k as f32 * 0.12; - draw_cube(c + vec3(side * 0.12, 0.11, z), vec3(0.03, 0.05, 0.03), None, Color::from_rgba(200, 200, 210, 255)); + crate::props::auto_cube(c + vec3(side * 0.12, 0.11, z), vec3(0.03, 0.05, 0.03), Color::from_rgba(200, 200, 210, 255)); } } } @@ -2654,14 +2654,14 @@ fn draw_landmarks_solid(g: &Game, t: f32) { let pc = vec3(px as f32 + 1.5, 0.0, py as f32 + 1.5); let stone = |k: u8| if owned { hue_to(tint, Color::from_rgba(46 + k, 30 + k / 2, 58 + k, 255)) } else { Color::from_rgba(56 + k, 54 + k, 60 + k, 255) }; let bone = if owned { Color::from_rgba(212, 200, 176, 255) } else { Color::from_rgba(150, 146, 140, 255) }; - draw_cube(pc + vec3(0.0, 0.05, 0.0), vec3(2.9, 0.1, 2.9), None, stone(0)); - draw_cube(pc + vec3(0.0, 0.14, 0.0), vec3(2.4, 0.08, 1.4), None, stone(8)); + crate::props::auto_cube(pc + vec3(0.0, 0.05, 0.0), vec3(2.9, 0.1, 2.9), stone(0)); + crate::props::auto_cube(pc + vec3(0.0, 0.14, 0.0), vec3(2.4, 0.08, 1.4), stone(8)); let r = 1.25; for side in [-1.0f32, 1.0] { // pillars of stacked, slightly offset blocks for k in 0..5 { let off = if k % 2 == 0 { 0.03 } else { -0.03 }; - draw_cube(pc + vec3(side * (r + off), 0.32 + k as f32 * 0.36, 0.0), vec3(0.42, 0.34, 0.5), None, stone((k * 5) as u8 + 6)); + crate::props::auto_cube(pc + vec3(side * (r + off), 0.32 + k as f32 * 0.36, 0.0), vec3(0.42, 0.34, 0.5), stone((k * 5) as u8 + 6)); } // a bone rib along the inner edge line3(pc + vec3(side * (r - 0.27), 0.2, 0.26), pc + vec3(side * (r - 0.27), 1.95, 0.26), 0.06, bone); @@ -2671,13 +2671,13 @@ fn draw_landmarks_solid(g: &Game, t: f32) { for k in 0..=8 { let a = k as f32 / 8.0 * std::f32::consts::PI; let p = pc + vec3(a.cos() * r, 2.0 + a.sin() * r * 0.9, 0.0); - draw_cube(p, vec3(0.4, 0.34, 0.52), None, stone(16 + (k % 3) as u8 * 4)); + crate::props::auto_cube(p, vec3(0.4, 0.34, 0.52), stone(16 + (k % 3) as u8 * 4)); } // keystone skull and horns let top = pc + vec3(0.0, 2.0 + r * 0.9 + 0.12, 0.0); - draw_cube(top, vec3(0.3, 0.28, 0.3), None, bone); + crate::props::auto_cube(top, vec3(0.3, 0.28, 0.3), bone); for sgn in [-1.0f32, 1.0] { - draw_cube(top + vec3(sgn * 0.07, 0.03, 0.155), vec3(0.07, 0.07, 0.02), None, Color::from_rgba(20, 8, 16, 255)); + crate::props::auto_cube(top + vec3(sgn * 0.07, 0.03, 0.155), vec3(0.07, 0.07, 0.02), Color::from_rgba(20, 8, 16, 255)); let mut prev = top + vec3(sgn * 0.15, 0.08, 0.0); for q in 1..=4 { let f = q as f32 / 4.0; @@ -2697,33 +2697,33 @@ fn draw_landmarks_solid(g: &Game, t: f32) { let gold = Color::from_rgba(230, 200, 100, 255); let iron = Color::from_rgba(56, 58, 66, 255); for side in [-1.1f32, 1.1] { - draw_cube(vec3(gx + side, 0.12, gz), vec3(0.6, 0.24, 0.6), None, dark); // plinth - draw_cube(vec3(gx + side, 1.0, gz), vec3(0.45, 1.8, 0.45), None, stone); + crate::props::auto_cube(vec3(gx + side, 0.12, gz), vec3(0.6, 0.24, 0.6), dark); // plinth + crate::props::auto_cube(vec3(gx + side, 1.0, gz), vec3(0.45, 1.8, 0.45), stone); for y in [0.6f32, 1.2] { - draw_cube(vec3(gx + side, y, gz), vec3(0.48, 0.05, 0.48), None, dark); // bands + crate::props::auto_cube(vec3(gx + side, y, gz), vec3(0.48, 0.05, 0.48), dark); // bands } - draw_cube(vec3(gx + side, 1.92, gz), vec3(0.56, 0.12, 0.56), None, dark); // capital + crate::props::auto_cube(vec3(gx + side, 1.92, gz), vec3(0.56, 0.12, 0.56), dark); // capital // banner of the order: white with a golden sun - draw_cube(vec3(gx + side, 1.35, gz + 0.25), vec3(0.32, 0.7, 0.02), None, Color::from_rgba(232, 234, 242, 255)); - draw_cube(vec3(gx + side, 1.45, gz + 0.265), vec3(0.14, 0.14, 0.01), None, gold); - draw_cube(vec3(gx + side, 1.02, gz + 0.26), vec3(0.32, 0.05, 0.02), None, Color::from_rgba(60, 90, 170, 255)); + crate::props::auto_cube(vec3(gx + side, 1.35, gz + 0.25), vec3(0.32, 0.7, 0.02), Color::from_rgba(232, 234, 242, 255)); + crate::props::auto_cube(vec3(gx + side, 1.45, gz + 0.265), vec3(0.14, 0.14, 0.01), gold); + crate::props::auto_cube(vec3(gx + side, 1.02, gz + 0.26), vec3(0.32, 0.05, 0.02), Color::from_rgba(60, 90, 170, 255)); } // stepped arch with a keystone - draw_cube(vec3(gx, 2.1, gz), vec3(2.8, 0.3, 0.55), None, stone); - draw_cube(vec3(gx, 1.88, gz), vec3(1.7, 0.14, 0.5), None, dark); - draw_cube(vec3(gx, 2.32, gz), vec3(2.2, 0.14, 0.5), None, dark); - draw_cube(vec3(gx, 2.2, gz), vec3(0.34, 0.5, 0.58), None, gold); + crate::props::auto_cube(vec3(gx, 2.1, gz), vec3(2.8, 0.3, 0.55), stone); + crate::props::auto_cube(vec3(gx, 1.88, gz), vec3(1.7, 0.14, 0.5), dark); + crate::props::auto_cube(vec3(gx, 2.32, gz), vec3(2.2, 0.14, 0.5), dark); + crate::props::auto_cube(vec3(gx, 2.2, gz), vec3(0.34, 0.5, 0.58), gold); // portcullis (iron bars) in the opening, half raised for k in 0..5 { - draw_cube(vec3(gx - 0.6 + k as f32 * 0.3, 1.45, gz), vec3(0.05, 0.85, 0.05), None, iron); + crate::props::auto_cube(vec3(gx - 0.6 + k as f32 * 0.3, 1.45, gz), vec3(0.05, 0.85, 0.05), iron); } for y in [1.15f32, 1.5, 1.8] { - draw_cube(vec3(gx, y, gz), vec3(1.7, 0.05, 0.05), None, iron); + crate::props::auto_cube(vec3(gx, y, gz), vec3(1.7, 0.05, 0.05), iron); } } else { for k in 0..10 { let a = k as f32 * 1.7; - draw_cube(vec3(gx + a.cos() * 1.0, 0.15, gz + a.sin() * 0.8), vec3(0.35, 0.3, 0.3), None, Color::from_rgba(150, 150, 160, 255)); + crate::props::auto_cube(vec3(gx + a.cos() * 1.0, 0.15, gz + a.sin() * 0.8), vec3(0.35, 0.3, 0.3), Color::from_rgba(150, 150, 160, 255)); } } let _ = t; @@ -2844,11 +2844,14 @@ fn draw_heart(base: Vec3, hp: f32, t: f32, cam_r: Vec3, tint: Option) { let hot = tc(1.0, 0.35 + 0.25 * beat, 0.3, 0.7); // two lobes and the point below, then the facets as bright chips let s0 = 0.36 * pulse; + // the crystal's facets (the furniture material; the colour tints it) + let crystal = crate::props::material(crate::props::Mat::Crystal); + let red = if crystal.is_some() { Color::new((red.r * 1.35).min(1.0), red.g * 1.35, red.b * 1.35, red.a) } else { red }; for sgn in [-1.0f32, 1.0] { - draw_sphere(hc + right * (sgn * 0.21 * pulse) + up * (0.12 * pulse), s0 * 0.85, None, red); + draw_sphere(hc + right * (sgn * 0.21 * pulse) + up * (0.12 * pulse), s0 * 0.85, crystal.as_ref(), red); } for (k, (y, r)) in [(-0.05f32, 0.36f32), (-0.22, 0.28), (-0.36, 0.18), (-0.46, 0.09)].iter().enumerate() { - draw_sphere(hc + up * (y * pulse), r * pulse, None, if k == 0 { red } else { tc(red.r * 0.9, red.g, red.b, 1.0) }); + draw_sphere(hc + up * (y * pulse), r * pulse, crystal.as_ref(), if k == 0 { red } else { tc(red.r * 0.9, red.g, red.b, 1.0) }); } draw_sphere(hc + right * (-0.12 * pulse) + up * (0.2 * pulse), 0.1 * pulse, None, tc(1.0, 0.75, 0.7, 0.75)); for k in 0..7 { @@ -3201,7 +3204,7 @@ fn draw_traps_solid(g: &Game, t: f32) { let fresh = (1.0 - tr.fired / 0.6).clamp(0.0, 1.0); match tr.kind { TrapKind::Spikes => { - draw_cube(c + vec3(0.0, 0.02, 0.0), vec3(0.8, 0.04, 0.8), None, iron); + crate::props::auto_cube(c + vec3(0.0, 0.02, 0.0), vec3(0.8, 0.04, 0.8), iron); let up = 0.06 + 0.3 * fresh; for q in 0..9 { let (dx, dz) = ((q % 3) as f32 * 0.24 - 0.24, (q / 3) as f32 * 0.24 - 0.24); @@ -3209,17 +3212,17 @@ fn draw_traps_solid(g: &Game, t: f32) { } } TrapKind::Poison => { - draw_cube(c + vec3(0.0, 0.03, 0.0), vec3(0.6, 0.06, 0.6), None, iron); + crate::props::auto_cube(c + vec3(0.0, 0.03, 0.0), vec3(0.6, 0.06, 0.6), iron); for q in 0..3 { - draw_cube(c + vec3(q as f32 * 0.16 - 0.16, 0.065, 0.0), vec3(0.06, 0.02, 0.5), None, Color::from_rgba(30, 40, 26, 255)); + crate::props::auto_cube(c + vec3(q as f32 * 0.16 - 0.16, 0.065, 0.0), vec3(0.06, 0.02, 0.5), Color::from_rgba(30, 40, 26, 255)); } } TrapKind::Fire => { // a demon head on a pedestal, its mouth towards the last target - draw_cube(c + vec3(0.0, 0.15, 0.0), vec3(0.36, 0.3, 0.36), None, Color::from_rgba(50, 40, 44, 255)); + crate::props::auto_cube(c + vec3(0.0, 0.15, 0.0), vec3(0.36, 0.3, 0.36), Color::from_rgba(50, 40, 44, 255)); let (ax, az) = (tr.aim.cos(), tr.aim.sin()); - draw_cube(c + vec3(0.0, 0.4, 0.0), vec3(0.3, 0.22, 0.3), None, Color::from_rgba(70, 56, 52, 255)); - draw_cube(c + vec3(ax * 0.16, 0.38, az * 0.16), vec3(0.14, 0.1, 0.14), None, Color::from_rgba(30, 20, 20, 255)); + crate::props::auto_cube(c + vec3(0.0, 0.4, 0.0), vec3(0.3, 0.22, 0.3), Color::from_rgba(70, 56, 52, 255)); + crate::props::auto_cube(c + vec3(ax * 0.16, 0.38, az * 0.16), vec3(0.14, 0.1, 0.14), Color::from_rgba(30, 20, 20, 255)); for sgn in [-1.0f32, 1.0] { line3(c + vec3(-az * 0.12 * sgn, 0.5, ax * 0.12 * sgn), c + vec3(-az * 0.2 * sgn - ax * 0.08, 0.68, ax * 0.2 * sgn - az * 0.08), 0.04, Color::from_rgba(214, 204, 178, 255)); } @@ -3229,19 +3232,19 @@ fn draw_traps_solid(g: &Game, t: f32) { if tr.fired > 18.0 || tr.cd <= 0.0 { draw_sphere(c + vec3(0.0, 0.3, 0.0), 0.3, None, Color::from_rgba(120, 112, 104, 255)); } - draw_cube(c + vec3(0.0, 0.03, 0.0), vec3(0.8, 0.06, 0.8), None, Color::from_rgba(60, 56, 52, 255)); + crate::props::auto_cube(c + vec3(0.0, 0.03, 0.0), vec3(0.8, 0.06, 0.8), Color::from_rgba(60, 56, 52, 255)); } TrapKind::Alarm => { - draw_cube(c + vec3(0.0, 0.35, 0.0), vec3(0.06, 0.7, 0.06), None, Color::from_rgba(90, 64, 40, 255)); - draw_cube(c + vec3(0.0, 0.7, 0.0), vec3(0.34, 0.05, 0.06), None, Color::from_rgba(90, 64, 40, 255)); + crate::props::auto_cube(c + vec3(0.0, 0.35, 0.0), vec3(0.06, 0.7, 0.06), Color::from_rgba(90, 64, 40, 255)); + crate::props::auto_cube(c + vec3(0.0, 0.7, 0.0), vec3(0.34, 0.05, 0.06), Color::from_rgba(90, 64, 40, 255)); let swing = (t * 18.0).sin() * 0.06 * fresh.max(((tr.fired < 3.0) as u8) as f32); - draw_cube(c + vec3(swing, 0.58, 0.0), vec3(0.18, 0.18, 0.18), None, Color::from_rgba(220, 180, 70, 255)); + crate::props::auto_cube(c + vec3(swing, 0.58, 0.0), vec3(0.18, 0.18, 0.18), Color::from_rgba(220, 180, 70, 255)); } TrapKind::Mine => { - draw_cube(c + vec3(0.0, 0.015, 0.0), vec3(0.4, 0.03, 0.4), None, Color::from_rgba(50, 54, 66, 255)); + crate::props::auto_cube(c + vec3(0.0, 0.015, 0.0), vec3(0.4, 0.03, 0.4), Color::from_rgba(50, 54, 66, 255)); } TrapKind::Frost => { - draw_cube(c + vec3(0.0, 0.06, 0.0), vec3(0.4, 0.12, 0.4), None, Color::from_rgba(80, 90, 110, 255)); + crate::props::auto_cube(c + vec3(0.0, 0.06, 0.0), vec3(0.4, 0.12, 0.4), Color::from_rgba(80, 90, 110, 255)); } _ => { // doors: posts, lintel and the leaf across the corridor @@ -3254,17 +3257,17 @@ fn draw_traps_solid(g: &Game, t: f32) { _ => (Color::from_rgba(70, 36, 100, 255), Color::from_rgba(30, 20, 40, 255)), }; for sgn in [-1.0f32, 1.0] { - draw_cube(c + len * (0.44 * sgn) + Vec3::Y * 0.6, size(0.12, 1.2, 0.3), None, Color::from_rgba(40, 32, 36, 255)); + crate::props::auto_cube(c + len * (0.44 * sgn) + Vec3::Y * 0.6, size(0.12, 1.2, 0.3), Color::from_rgba(40, 32, 36, 255)); } - draw_cube(c + Vec3::Y * 1.22, size(1.0, 0.14, 0.32), None, Color::from_rgba(40, 32, 36, 255)); + crate::props::auto_cube(c + Vec3::Y * 1.22, size(1.0, 0.14, 0.32), Color::from_rgba(40, 32, 36, 255)); let shake = if tr.fired < 0.2 { (t * 60.0).sin() * 0.02 } else { 0.0 }; - draw_cube(c + Vec3::Y * 0.56 + thin * shake, size(0.76, 1.1, 0.1), None, leaf); + crate::props::auto_cube(c + Vec3::Y * 0.56 + thin * shake, size(0.76, 1.1, 0.1), leaf); for y in [0.25f32, 0.85] { - draw_cube(c + Vec3::Y * y, size(0.78, 0.06, 0.12), None, trim); + crate::props::auto_cube(c + Vec3::Y * y, size(0.78, 0.06, 0.12), trim); } if tr.locked { - draw_cube(c + Vec3::Y * 0.6, size(0.86, 0.08, 0.16), None, Color::from_rgba(60, 60, 66, 255)); - draw_cube(c + Vec3::Y * 0.6 + thin * 0.09, vec3(0.1, 0.12, 0.1), None, Color::from_rgba(230, 190, 70, 255)); + crate::props::auto_cube(c + Vec3::Y * 0.6, size(0.86, 0.08, 0.16), Color::from_rgba(60, 60, 66, 255)); + crate::props::auto_cube(c + Vec3::Y * 0.6 + thin * 0.09, vec3(0.1, 0.12, 0.1), Color::from_rgba(230, 190, 70, 255)); } // damage: darker the more it is beaten let _ = tr.hp / tr.kind.hp(); @@ -3278,7 +3281,7 @@ fn draw_traps_solid(g: &Game, t: f32) { let spin = r.t * 9.0; let at = vec3(r.x, 0.3, r.y); draw_sphere(at, 0.3, None, Color::from_rgba(120, 112, 104, 255)); - draw_cube(at + vec3(spin.cos() * 0.22 * r.dy.abs(), spin.sin() * 0.22, spin.cos() * 0.22 * r.dx.abs()), Vec3::splat(0.1), None, Color::from_rgba(80, 74, 70, 255)); + crate::props::auto_cube(at + vec3(spin.cos() * 0.22 * r.dy.abs(), spin.sin() * 0.22, spin.cos() * 0.22 * r.dx.abs()), Vec3::splat(0.1), Color::from_rgba(80, 74, 70, 255)); } }