High-res tile textures: floor, claimed floor, earth, rock, gold, churning water and lava

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:26:22 +01:00
1 parent 69a6b13006
commit 8197b07ac5
33 files changed
+256 -7

No files matched your search

+86 -1
View File
@@ -99,6 +99,7 @@ pub struct Gfx {
pub atlas: Texture2D,
pub sprites: Texture2D,
pub hd_sprites: Texture2D, // detailed sprites (see HD_SPRITES, hd_cell_view)
pub atlas_hd: Texture2D, // the tile atlas of the high-res style (see HD_TILES)
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
@@ -325,6 +326,55 @@ fn earth_px(x: i32, y: i32, v: u32) -> Color {
shade(base, (big + fine) as i32)
}
// ---- high-res tiles
// The high-res style's atlas: the same cells as the 16x16 atlas, HD_TILE x HD_TILE texels each.
// Cells without an own texture are the 16x16 ones scaled up. HD_TILES: generated textures (see
// art/generated/textures/), each a seamless 2x2 block of tiles for the four variants of a kind
// (variant k = quarter k % 2, k / 2); the world lays the quarters out by the tiles' positions
// (see hd_tile), so a floor repeats only every two tiles and has no seams.
pub const HD_TILE: u32 = 64;
pub const ATLAS_HD_W: f32 = (ATLAS_COLS * HD_TILE) as f32;
pub const ATLAS_HD_H: f32 = (ATLAS_ROWS * HD_TILE) as f32;
const HD_TILES: [(u32, &[u8]); 7] = [
(T_FLOOR, include_bytes!("../assets/textures/floor.png")),
(T_CLAIM, include_bytes!("../assets/textures/claimed.png")),
(T_EARTH, include_bytes!("../assets/textures/earth.png")),
(T_ROCK, include_bytes!("../assets/textures/rock.png")),
(T_GOLD, include_bytes!("../assets/textures/gold.png")),
(T_WATER, include_bytes!("../assets/textures/water.png")),
(T_LAVA, include_bytes!("../assets/textures/lava.png")),
];
// whether a cell has a generated high-res texture (its variants are laid out by position)
pub fn hd_tile(id: u32) -> bool {
HD_TILES.iter().any(|&(base, _)| id / 4 * 4 == base)
}
fn gen_hd_atlas() -> Image {
let small = gen_atlas();
let k = HD_TILE / 16;
let mut img = Image::gen_image_color(ATLAS_HD_W as u16, ATLAS_HD_H as u16, Color::new(0.0, 0.0, 0.0, 0.0));
for y in 0..ATLAS_HD_H as u32 {
for x in 0..ATLAS_HD_W as u32 {
img.set_pixel(x, y, small.get_pixel(x / k, y / k));
}
}
for &(base, png) in HD_TILES.iter() {
let src = Image::from_file_with_format(png, Some(ImageFormat::Png)).expect("hd tile");
for v in 0..4 {
let (sx, sy) = ((v % 2) * HD_TILE, (v / 2) * HD_TILE);
let id = base + v;
let (ox, oy) = ((id % ATLAS_COLS) * HD_TILE, (id / ATLAS_COLS) * HD_TILE);
for y in 0..HD_TILE {
for x in 0..HD_TILE {
img.set_pixel(ox + x, oy + y, src.get_pixel(sx + x, sy + y));
}
}
}
}
img
}
fn gen_atlas() -> Image {
let mut cv = Canvas { img: Image::gen_image_color((ATLAS_COLS * 16) as u16, (ATLAS_ROWS * 16) as u16, Color::new(0.0, 0.0, 0.0, 0.0)) };
for v in 0..4u32 {
@@ -2360,9 +2410,11 @@ impl Gfx {
cursors.set_filter(FilterMode::Nearest);
let badges = Texture2D::from_image(&crate::badges::gen_badges());
badges.set_filter(FilterMode::Nearest);
let atlas_hd = Texture2D::from_image(&gen_hd_atlas());
atlas_hd.set_filter(FilterMode::Nearest);
let hd_sprites = Texture2D::from_image(&gen_hd_sprites());
hd_sprites.set_filter(FilterMode::Nearest);
Gfx { atlas, sprites, hd_sprites, cursors, badges, font, font_map }
Gfx { atlas, sprites, hd_sprites, atlas_hd, cursors, badges, font, font_map }
}
pub fn cell(id: u32) -> Rect {
@@ -2632,6 +2684,39 @@ impl Gfx {
}
}
#[cfg(test)]
mod hd_atlas_tests {
use super::*;
#[test]
fn high_res_atlas() {
let small = gen_atlas();
let hd = gen_hd_atlas();
assert_eq!((hd.width as f32, hd.height as f32), (ATLAS_HD_W, ATLAS_HD_H));
let px = |img: &Image, x: u32, y: u32| {
let p = img.get_pixel(x, y);
(p.r, p.g, p.b, p.a)
};
// a cell without an own texture: the 16x16 one scaled up
let (cx, cy) = ((T_TREASURY % ATLAS_COLS) * 16, (T_TREASURY / ATLAS_COLS) * 16);
for (x, y) in [(0, 0), (5, 9), (15, 15)] {
assert_eq!(px(&hd, (cx + x) * 4 + 2, (cy + y) * 4 + 1), px(&small, cx + x, cy + y));
}
// the generated ones: the quarters of their 2x2 sheet
for &(base, png) in HD_TILES.iter() {
let src = Image::from_file_with_format(png, Some(ImageFormat::Png)).unwrap();
assert_eq!((src.width, src.height), (2 * HD_TILE as u16, 2 * HD_TILE as u16));
for v in 0..4 {
let id = base + v;
assert!(hd_tile(id));
let (ox, oy) = ((id % ATLAS_COLS) * HD_TILE, (id / ATLAS_COLS) * HD_TILE);
assert_eq!(px(&hd, ox + 7, oy + 40), px(&src, (v % 2) * HD_TILE + 7, (v / 2) * HD_TILE + 40));
}
}
assert!(!hd_tile(T_TREASURY));
}
}
#[cfg(test)]
mod sprite_tests {
use super::*;