High-res claimed floors for all four masters: five slabs each with own engravings and damage

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard ZinkandClaude Opus 5.5 committed 2026-11-07 21:41:07 +01:00
1 parent 50f8af15c7
commit aab466cfbe
34 files changed
+202 -8

No files matched your search

+68 -4
View File
@@ -6,7 +6,7 @@ use macroquad::prelude::*;
pub const CELL: f32 = 16.0;
pub const ATLAS_COLS: u32 = 16;
pub const ATLAS_ROWS: u32 = 14;
pub const ATLAS_ROWS: u32 = 16; // rows 14-15: cells only the high-res atlases fill (see HD_FLOORS)
// atlas indices (4 variants each)
pub const T_ROCK: u32 = 0;
@@ -338,9 +338,8 @@ fn earth_px(x: i32, y: i32, v: u32) -> Color {
pub const HD_TILE: u32 = 64;
pub const HD_TILE2: u32 = 128;
// (first cell, variants, 64x64 level, 128x128 level)
const HD_TILES: [(u32, u32, &[u8], &[u8]); 10] = [
const HD_TILES: [(u32, u32, &[u8], &[u8]); 9] = [
(T_FLOOR, 4, include_bytes!("../assets/textures/floor.png"), include_bytes!("../assets/textures/floor-256.png")),
(T_CLAIM, 4, include_bytes!("../assets/textures/claimed.png"), include_bytes!("../assets/textures/claimed-256.png")),
(T_EARTH, 4, include_bytes!("../assets/textures/earth.png"), include_bytes!("../assets/textures/earth-256.png")),
(T_ROCK, 4, include_bytes!("../assets/textures/rock.png"), include_bytes!("../assets/textures/rock-256.png")),
(T_GOLD, 4, include_bytes!("../assets/textures/gold.png"), include_bytes!("../assets/textures/gold-256.png")),
@@ -351,9 +350,39 @@ const HD_TILES: [(u32, u32, &[u8], &[u8]); 10] = [
(T_DIAMOND, 2, include_bytes!("../assets/textures/diamond.png"), include_bytes!("../assets/textures/diamond-128.png")),
];
// The masters' claimed floors in the high-res style: five single slabs each (with a grout line
// along the edges, so they fit in any order), in the master's colour with engravings of their
// own and some of them cracked, chipped or broken. They go into cells of their own (from
// T_HDFLOOR on, five per master); a tile picks one by its position, weighted (plain slabs more
// often than the big engravings and the broken ones).
// (the claimed floor's cells, the first own cell, 64x64 slabs side by side, 128x128 ones, weights)
pub const T_HDFLOOR: u32 = 224;
const HD_FLOORS: [(u32, u32, &[u8], &[u8], [u32; 5]); 4] = [
// the player: crimson stone, demonic runes and horned skulls (plain, big engraving, cracks, broken, small engravings)
(T_CLAIM, T_HDFLOOR, include_bytes!("../assets/textures/floor-player.png"), include_bytes!("../assets/textures/floor-player-128.png"), [4, 1, 3, 1, 2]),
// Mossgrim: mossy green slabs, mushrooms and mould (plain, big engraving, cracks, chipped, broken)
(T_RIVAL1, T_HDFLOOR + 5, include_bytes!("../assets/textures/floor-mossgrim.png"), include_bytes!("../assets/textures/floor-mossgrim-128.png"), [4, 1, 3, 2, 1]),
// Lady Nightwell: blue marble, silver lilies and moons
(T_RIVAL2, T_HDFLOOR + 10, include_bytes!("../assets/textures/floor-nightwell.png"), include_bytes!("../assets/textures/floor-nightwell-128.png"), [4, 1, 3, 2, 1]),
// Saffrax: ochre sandstone, brass and alchemical sigils
(T_RIVAL3, T_HDFLOOR + 15, include_bytes!("../assets/textures/floor-saffrax.png"), include_bytes!("../assets/textures/floor-saffrax-128.png"), [4, 1, 3, 2, 1]),
];
// the cell a tile at (x, z) shows in the high-res style: generated textures with four variants
// are laid out by the position (see HD_TILES), everything else stays
// are laid out by the position (see HD_TILES), the masters' floors pick one of their five slabs
// (HD_FLOORS), everything else stays
pub fn hd_tile(id: u32, x: i32, z: i32) -> u32 {
if let Some(&(_, own, _, _, w)) = HD_FLOORS.iter().find(|f| (f.0..f.0 + 4).contains(&id)) {
let h = (x as u32).wrapping_mul(73_856_093) ^ (z as u32).wrapping_mul(19_349_663);
let h = (h ^ (h >> 13)).wrapping_mul(0x5bd1_e995);
let mut r = (h >> 8) % w.iter().sum::<u32>();
for (k, &wk) in w.iter().enumerate() {
if r < wk {
return own + k as u32;
}
r -= wk;
}
}
match HD_TILES.iter().find(|&&(base, n, _, _)| (base..base + n).contains(&id)) {
Some(&(base, 4, _, _)) => base + (x & 1) as u32 + (z & 1) as u32 * 2,
_ => id,
@@ -384,6 +413,18 @@ fn gen_hd_atlas(tile: u32) -> Image {
}
}
}
for &(_, own, png, png2, _) in HD_FLOORS.iter() {
let src = Image::from_file_with_format(if tile == HD_TILE2 { png2 } else { png }, Some(ImageFormat::Png)).expect("hd floor");
for v in 0..5 {
let id = own + v;
let (ox, oy) = ((id % ATLAS_COLS) * tile, (id / ATLAS_COLS) * tile);
for y in 0..tile {
for x in 0..tile {
img.set_pixel(ox + x, oy + y, src.get_pixel(v * tile + x, y));
}
}
}
}
img
}
@@ -2730,7 +2771,30 @@ mod hd_atlas_tests {
assert_eq!(px(&hd, ox + 7, oy + 40), px(&src, sx + 7, sy + 40));
}
}
// the masters' floors: five slabs each in their own cells (inside the atlas)
for &(_, own, png, png2, _) in HD_FLOORS.iter() {
let src = Image::from_file_with_format(if tile == HD_TILE2 { png2 } else { png }, Some(ImageFormat::Png)).unwrap();
assert_eq!((src.width as u32, src.height as u32), (5 * tile, tile));
assert!(own + 5 <= ATLAS_COLS * ATLAS_ROWS);
for v in 0..5 {
let id = own + v;
let (ox, oy) = ((id % ATLAS_COLS) * tile, (id / ATLAS_COLS) * tile);
assert_eq!(px(&hd, ox + 9, oy + 30), px(&src, v * tile + 9, 30));
}
}
}
// every slab of a floor shows up, the plain one most often
let mut n = [0u32; 5];
for z in 0..60 {
for x in 0..60 {
let id = hd_tile(T_CLAIM + (x as u32 % 4), x, z);
assert!((T_HDFLOOR..T_HDFLOOR + 5).contains(&id));
n[(id - T_HDFLOOR) as usize] += 1;
}
}
assert!(n.iter().all(|&k| k > 100), "{n:?}");
assert!(n[0] > n[1] * 2, "{n:?}");
assert!((T_HDFLOOR + 15..T_HDFLOOR + 20).contains(&hd_tile(T_RIVAL3 + 2, 3, 7)));
// four variants by position, two variants keep theirs, others stay
assert_eq!(hd_tile(T_FLOOR + 3, 0, 0), T_FLOOR);
assert_eq!(hd_tile(T_FLOOR, 1, 1), T_FLOOR + 3);