Implement texture atlas building

This commit is contained in:
crumblingstatue 2023-04-15 19:26:36 +02:00
parent 5ec0ad0da4
commit 45801205dc
17 changed files with 558 additions and 60 deletions

379
Cargo.lock generated
View file

@ -18,6 +18,12 @@ version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046"
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "ahash"
version = "0.8.3"
@ -146,6 +152,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bit_field"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61"
[[package]]
name = "bitflags"
version = "1.3.2"
@ -164,6 +176,12 @@ version = "3.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
[[package]]
name = "bytemuck"
version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea"
[[package]]
name = "byteorder"
version = "1.4.3"
@ -246,6 +264,12 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1"
[[package]]
name = "color_quant"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
[[package]]
name = "colorchoice"
version = "1.0.0"
@ -261,6 +285,49 @@ dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crc32fast"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
dependencies = [
"cfg-if",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
dependencies = [
"cfg-if",
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695"
dependencies = [
"autocfg",
"cfg-if",
"crossbeam-utils",
"memoffset",
"scopeguard",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.15"
@ -270,6 +337,12 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "crunchy"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
[[package]]
name = "derivative"
version = "2.2.0"
@ -354,6 +427,12 @@ dependencies = [
"sfml",
]
[[package]]
name = "either"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
[[package]]
name = "emath"
version = "0.21.0"
@ -415,6 +494,22 @@ version = "2.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
[[package]]
name = "exr"
version = "1.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bdd2162b720141a91a054640662d3edce3d50a944a50ffca5313cd951abb35b4"
dependencies = [
"bit_field",
"flume",
"half",
"lebe",
"miniz_oxide",
"rayon-core",
"smallvec",
"zune-inflate",
]
[[package]]
name = "fastrand"
version = "1.9.0"
@ -424,6 +519,29 @@ dependencies = [
"instant",
]
[[package]]
name = "flate2"
version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
dependencies = [
"crc32fast",
"miniz_oxide",
]
[[package]]
name = "flume"
version = "0.10.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577"
dependencies = [
"futures-core",
"futures-sink",
"nanorand",
"pin-project",
"spin",
]
[[package]]
name = "fnv"
version = "1.0.7"
@ -457,6 +575,12 @@ dependencies = [
"waker-fn",
]
[[package]]
name = "futures-sink"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e"
[[package]]
name = "futures-task"
version = "0.3.28"
@ -520,8 +644,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
dependencies = [
"cfg-if",
"js-sys",
"libc",
"wasi",
"wasm-bindgen",
]
[[package]]
name = "gif"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045"
dependencies = [
"color_quant",
"weezl",
]
[[package]]
@ -585,6 +721,15 @@ dependencies = [
"system-deps",
]
[[package]]
name = "half"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02b4af3693f1b705df946e9fe5631932443781d0aabb423b62fcd4d73f6d2fd0"
dependencies = [
"crunchy",
]
[[package]]
name = "hashbrown"
version = "0.12.3"
@ -616,6 +761,15 @@ dependencies = [
"spin",
]
[[package]]
name = "hermit-abi"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
dependencies = [
"libc",
]
[[package]]
name = "hermit-abi"
version = "0.3.1"
@ -628,6 +782,25 @@ version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "image"
version = "0.24.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "527909aa81e20ac3a44803521443a765550f09b5130c2c2fa1ea59c2f8f50a3a"
dependencies = [
"bytemuck",
"byteorder",
"color_quant",
"exr",
"gif",
"jpeg-decoder",
"num-rational",
"num-traits",
"png",
"qoi",
"tiff",
]
[[package]]
name = "indexmap"
version = "1.9.3"
@ -653,7 +826,7 @@ version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220"
dependencies = [
"hermit-abi",
"hermit-abi 0.3.1",
"libc",
"windows-sys 0.48.0",
]
@ -664,7 +837,7 @@ version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f"
dependencies = [
"hermit-abi",
"hermit-abi 0.3.1",
"io-lifetimes",
"rustix",
"windows-sys 0.48.0",
@ -679,6 +852,15 @@ dependencies = [
"libc",
]
[[package]]
name = "jpeg-decoder"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e"
dependencies = [
"rayon",
]
[[package]]
name = "js-sys"
version = "0.3.61"
@ -688,6 +870,12 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "lebe"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8"
[[package]]
name = "libc"
version = "0.2.141"
@ -752,6 +940,7 @@ dependencies = [
"fnv",
"gamedebug_core",
"hecs",
"image",
"log",
"num-traits",
"rand",
@ -761,6 +950,8 @@ dependencies = [
"serde",
"sfml",
"sfml-xt",
"texture_packer",
"walkdir",
"worldgen",
"zstd",
]
@ -771,12 +962,60 @@ version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "memoffset"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1"
dependencies = [
"autocfg",
]
[[package]]
name = "miniz_oxide"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
dependencies = [
"adler",
]
[[package]]
name = "nanorand"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3"
dependencies = [
"getrandom",
]
[[package]]
name = "nohash-hasher"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451"
[[package]]
name = "num-integer"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
dependencies = [
"autocfg",
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.15"
@ -786,6 +1025,16 @@ dependencies = [
"autocfg",
]
[[package]]
name = "num_cpus"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
dependencies = [
"hermit-abi 0.2.6",
"libc",
]
[[package]]
name = "objc"
version = "0.2.7"
@ -877,6 +1126,26 @@ version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79"
[[package]]
name = "pin-project"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "pin-project-lite"
version = "0.2.9"
@ -895,6 +1164,18 @@ version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
[[package]]
name = "png"
version = "0.17.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d708eaf860a19b19ce538740d2b4bdeeb8337fa53f7738455e706623ad5c638"
dependencies = [
"bitflags",
"crc32fast",
"flate2",
"miniz_oxide",
]
[[package]]
name = "polling"
version = "2.7.0"
@ -926,6 +1207,15 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "qoi"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001"
dependencies = [
"bytemuck",
]
[[package]]
name = "quote"
version = "1.0.26"
@ -971,6 +1261,28 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9"
[[package]]
name = "rayon"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
dependencies = [
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-utils",
"num_cpus",
]
[[package]]
name = "redox_syscall"
version = "0.2.16"
@ -1077,6 +1389,15 @@ dependencies = [
"serde",
]
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]]
name = "scopeguard"
version = "1.1.0"
@ -1134,6 +1455,12 @@ dependencies = [
"sfml",
]
[[package]]
name = "simd-adler32"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "238abfbb77c1915110ad968465608b68e869e0772622c9656714e73e5a1a522f"
[[package]]
name = "slab"
version = "0.4.8"
@ -1164,6 +1491,9 @@ name = "spin"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
dependencies = [
"lock_api",
]
[[package]]
name = "strsim"
@ -1215,6 +1545,15 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "texture_packer"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28afa0d0b184ff1ba02bf420a4d096e880f4566ded90198cbc4b7f32ba17fa9b"
dependencies = [
"image",
]
[[package]]
name = "thiserror"
version = "1.0.40"
@ -1235,6 +1574,17 @@ dependencies = [
"syn 2.0.15",
]
[[package]]
name = "tiff"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7449334f9ff2baf290d55d73983a7d6fa15e01198faef72af07e2a8db851e471"
dependencies = [
"flate2",
"jpeg-decoder",
"weezl",
]
[[package]]
name = "toml"
version = "0.7.3"
@ -1305,6 +1655,16 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca"
[[package]]
name = "walkdir"
version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698"
dependencies = [
"same-file",
"winapi-util",
]
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
@ -1387,6 +1747,12 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "weezl"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb"
[[package]]
name = "widestring"
version = "1.0.2"
@ -1609,3 +1975,12 @@ dependencies = [
"libc",
"pkg-config",
]
[[package]]
name = "zune-inflate"
version = "0.2.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a01728b79fb9b7e28a8c11f715e1cd8dc2cda7416a007d66cac55cebb3a8ac6b"
dependencies = [
"simd-adler32",
]

View file

@ -24,6 +24,9 @@ env_logger = "0.10.0"
zstd = "0.12.3"
clap = { version = "4.2.2", features = ["derive"] }
directories = "5.0.0"
texture_packer = "0.25.0"
walkdir = "2.3.3"
image = "0.24.6"
[dependencies.s2dc]
#git = "https://github.com/crumblingstatue/s2dc.git"

View file

Before

Width:  |  Height:  |  Size: 8.4 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

BIN
res/graphics/tiles/dirt.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 B

View file

@ -59,7 +59,7 @@ impl App {
Ok(Self {
rw,
should_quit: false,
game: GameState::new(args.world_name, path),
game: GameState::new(args.world_name, path, &res),
res,
sf_egui,
input: Input::default(),

View file

@ -50,16 +50,16 @@ impl GameState {
}
pub(crate) fn draw_world(&mut self, rt: &mut RenderTexture, res: &mut Res) {
self.light_sources.clear();
let mut s = Sprite::with_texture(&res.tile_atlas);
let mut s = Sprite::with_texture(&res.atlas.tex);
for_each_tile_on_screen(self.camera_offset, rt.size(), |tp, sp| {
let tile = self.world.tile_at_mut(tp, &self.worldgen);
s.set_position(sp.to_sf_vec());
if tile.bg != Tile::EMPTY {
s.set_texture_rect(self.tile_db[tile.bg].atlas_offset.to_sf_rect());
s.set_texture_rect(self.tile_db[tile.bg].tex_rect.to_sf());
rt.draw(&s);
}
if tile.mid != Tile::EMPTY {
s.set_texture_rect(self.tile_db[tile.mid].atlas_offset.to_sf_rect());
s.set_texture_rect(self.tile_db[tile.mid].tex_rect.to_sf());
if let Some(light) = self.tile_db[tile.mid].light {
let pos = ScreenVec {
x: sp.x + light.x,
@ -70,7 +70,7 @@ impl GameState {
rt.draw(&s);
}
if tile.fg != Tile::EMPTY {
s.set_texture_rect(self.tile_db[tile.fg].atlas_offset.to_sf_rect());
s.set_texture_rect(self.tile_db[tile.fg].tex_rect.to_sf());
rt.draw(&s);
}
});
@ -106,8 +106,9 @@ impl GameState {
self.ambient_light,
255,
));
let mut s = Sprite::with_texture(&res.atlas.tex);
s.set_texture_rect(res.atlas.rects["light/1"].to_sf());
for ls in &self.light_sources {
let mut s = Sprite::with_texture(&res.light_texture);
let flicker = smoothwave(self.world.ticks, 40) as f32 / 64.0;
s.set_scale((4. + flicker, 4. + flicker));
s.set_origin((128., 128.));
@ -116,9 +117,11 @@ impl GameState {
}
}
pub(crate) fn new(world_name: String, path: PathBuf) -> GameState {
pub(crate) fn new(world_name: String, path: PathBuf, res: &Res) -> GameState {
let mut spawn_point = WorldPos::SURFACE_CENTER;
spawn_point.y -= 1104;
let mut tile_db = TileDb::load_or_default();
tile_db.update_rects(&res.atlas.rects);
Self {
camera_offset: spawn_point,
world: World::new(spawn_point, &world_name, path),
@ -129,7 +132,7 @@ impl GameState {
worldgen: Worldgen::from_seed(0),
ambient_light: 0,
light_sources: Vec::new(),
tile_db: TileDb::load_or_default(),
tile_db,
}
}
}

View file

@ -8,6 +8,7 @@ mod math;
mod player;
mod res;
mod stringfmt;
mod texture_atlas;
mod tiles;
mod world;
mod worldgen;

View file

@ -1,5 +1,8 @@
use std::fmt::Debug;
use egui_inspect::derive::Inspect;
use num_traits::{Num, Signed};
use serde::{Deserialize, Serialize};
use crate::world::{TPosSc, TilePos};
@ -81,6 +84,24 @@ pub fn smoothwave<T: Num + From<u8> + PartialOrd + Copy>(input: T, max: T) -> T
}
}
#[derive(Serialize, Deserialize, Debug, Inspect, Default, Clone, Copy)]
pub struct IntRect {
pub x: i32,
pub y: i32,
pub w: i32,
pub h: i32,
}
impl IntRect {
pub(crate) fn to_sf(&self) -> sfml::graphics::Rect<i32> {
sfml::graphics::Rect::<i32> {
left: self.x,
top: self.y,
width: self.w,
height: self.h,
}
}
}
#[test]
fn test_smooth_wave() {
assert_eq!(smoothwave(0, 100), 0);

View file

@ -1,9 +1,10 @@
use sfml::{audio::Music, graphics::Texture, SfBox};
use sfml::audio::Music;
use crate::texture_atlas::AtlasBundle;
#[derive(Debug)]
pub struct Res {
pub tile_atlas: SfBox<Texture>,
pub light_texture: SfBox<Texture>,
pub atlas: AtlasBundle,
pub surf_music: Music<'static>,
pub und_music: Music<'static>,
}
@ -11,8 +12,7 @@ pub struct Res {
impl Res {
pub fn load() -> anyhow::Result<Self> {
Ok(Self {
tile_atlas: Texture::from_file("res/graphics/tiles.png")?,
light_texture: Texture::from_file("res/graphics/light2.png")?,
atlas: AtlasBundle::new()?,
surf_music: Music::from_file("res/music/music.ogg").unwrap(),
und_music: Music::from_file("res/music/cave2.ogg").unwrap(),
})

102
src/texture_atlas.rs Normal file
View file

@ -0,0 +1,102 @@
use std::{collections::HashMap, path::Path};
use crate::math::IntRect;
use sfml::{graphics::Texture, SfBox};
use texture_packer::{texture::Texture as _, TexturePacker, TexturePackerConfig};
pub type RectMap = HashMap<String, IntRect>;
#[derive(Debug)]
pub struct AtlasBundle {
pub tex: SfBox<Texture>,
// Key could be `tiles/dirt` for example, derived from folder+filename without extension
pub rects: RectMap,
}
impl AtlasBundle {
pub fn new() -> anyhow::Result<Self> {
let cfg = TexturePackerConfig {
max_width: 4096,
max_height: 4096,
allow_rotation: false,
border_padding: 0,
texture_padding: 1,
texture_extrusion: 0,
trim: true,
texture_outlines: false,
};
let mut packer = TexturePacker::new_skyline(cfg);
walk_graphics(|path| {
let img = image::open(path).unwrap();
let key = path_img_key(path);
packer.pack_own(key, img).unwrap();
dbg!(path);
});
let mut rects = HashMap::new();
let mut tex = Texture::new().unwrap();
if !tex.create(packer.width(), packer.height()) {
panic!("Failed to create texture");
}
let pixbuf = make_pix_buf(&packer);
unsafe {
tex.update_from_pixels(&pixbuf, packer.width(), packer.height(), 0, 0);
}
for (k, frame) in packer.get_frames() {
rects.insert(
k.clone(),
IntRect {
x: frame.frame.x as i32,
y: frame.frame.y as i32,
w: frame.frame.w as i32,
h: frame.frame.h as i32,
},
);
}
Ok(AtlasBundle { tex, rects })
}
}
fn make_pix_buf(packer: &TexturePacker<image::DynamicImage, String>) -> Vec<u8> {
let (w, h) = (packer.width(), packer.height());
let px_size = 4;
let mut vec = vec![0; w as usize * h as usize * px_size as usize];
dbg!(w, h);
for y in 0..h {
for x in 0..w {
let idx = ((y * w + x) * px_size) as usize;
if let Some(px) = packer.get(x, y) {
vec[idx..idx + px_size as usize].copy_from_slice(&px.0);
}
}
}
vec
}
fn path_img_key(path: &Path) -> String {
let mut rev_iter = path.components().rev();
let fname = rev_iter.next().unwrap();
let folder = rev_iter.next().unwrap();
let fname: &Path = fname.as_ref();
let folder: &Path = folder.as_ref();
folder
.join(fname.file_stem().unwrap())
.display()
.to_string()
}
#[test]
fn test_path_img_key() {
assert_eq!(
&path_img_key("/home/person/res/graphics/tiles/foo.png".as_ref()),
"tiles/foo"
);
}
fn walk_graphics(mut f: impl FnMut(&Path)) {
for en in walkdir::WalkDir::new("res/graphics") {
let en = en.unwrap();
if en.file_type().is_file() {
f(en.path());
}
}
}

View file

@ -4,11 +4,11 @@ use std::ops::Index;
use egui_inspect::derive::Inspect;
use serde::{Deserialize, Serialize};
use sfml::graphics::IntRect;
use crate::{
graphics::{ScreenSc, ScreenVec},
math::TILE_SIZE,
math::{IntRect, TILE_SIZE},
texture_atlas::RectMap,
world::TileId,
};
@ -17,9 +17,11 @@ pub struct TileDef {
pub bb: Option<TileBb>,
/// Whether the tile emits light, and the light source offset
pub light: Option<ScreenVec>,
pub atlas_offset: AtlasOffset,
/// Platform behavior: Horizontally passable, vertically passable upwards
pub platform: bool,
#[serde(default)]
pub graphic_name: String,
pub tex_rect: IntRect,
}
const DEFAULT_TILE_BB: TileBb = TileBb {
@ -44,9 +46,18 @@ pub struct TileDb {
impl Default for TileDb {
fn default() -> Self {
let unknown = TileDef {
bb: None,
light: Some(ScreenVec {
x: TILE_SIZE as ScreenSc / 2,
y: TILE_SIZE as ScreenSc / 2,
}),
platform: false,
graphic_name: String::from("tiles/unknown"),
tex_rect: IntRect::default(),
};
Self {
// Add empty/air tile
db: vec![EMPTY],
db: vec![EMPTY, unknown],
}
}
}
@ -56,52 +67,26 @@ const EMPTY: TileDef = TileDef {
light: None,
// Rendering empty tile is actually special cased, and no rendering is done.
// But just in case, put the offset to UNKNOWN
atlas_offset: UNKNOWN_ATLAS_OFF,
tex_rect: IntRect {
x: 0,
y: 0,
w: 0,
h: 0,
},
platform: false,
graphic_name: String::new(),
};
impl Index<TileId> for TileDb {
type Output = TileDef;
fn index(&self, index: TileId) -> &Self::Output {
self.db.get(index as usize).unwrap_or(&UNKNOWN_TILE)
self.db.get(index as usize).unwrap_or_else(|| {
&self.db[1] // Unknown tile def is stored at index 1
})
}
}
#[derive(Debug, Inspect, Serialize, Deserialize)]
pub struct AtlasOffset {
pub x: u16,
pub y: u16,
}
impl AtlasOffset {
pub(crate) fn to_sf_rect(&self) -> IntRect {
IntRect {
left: self.x as i32,
top: self.y as i32,
width: TILE_SIZE as i32,
height: TILE_SIZE as i32,
}
}
}
impl Default for AtlasOffset {
fn default() -> Self {
UNKNOWN_ATLAS_OFF
}
}
const UNKNOWN_ATLAS_OFF: AtlasOffset = AtlasOffset { x: 320, y: 0 };
static UNKNOWN_TILE: TileDef = TileDef {
bb: None,
light: Some(ScreenVec {
x: TILE_SIZE as ScreenSc / 2,
y: TILE_SIZE as ScreenSc / 2,
}),
atlas_offset: UNKNOWN_ATLAS_OFF,
platform: false,
};
const PATH: &str = "tiles.dat";
impl TileDb {
@ -129,4 +114,12 @@ impl TileDb {
Err(e) => log::warn!("Failed to save tile db: {e}"),
}
}
pub(crate) fn update_rects(&mut self, rects: &RectMap) {
for def in &mut self.db {
if !def.graphic_name.is_empty() {
def.tex_rect = rects[&def.graphic_name];
}
}
}
}

View file

@ -78,7 +78,7 @@ impl World {
chk.at_mut(local)
}
pub fn save(&self) {
let result = std::fs::create_dir(&self.path);
let result = std::fs::create_dir_all(&self.path);
log::info!("{result:?}");
self.save_meta();
self.player.save(&self.path);

View file

@ -34,7 +34,7 @@ impl Worldgen {
.add(
Tile::new(Tl {
bg: 9,
mid: 2,
mid: 3,
fg: 6,
})
.when(constraint!(nm.clone(), < -0.8)),
@ -43,7 +43,7 @@ impl Worldgen {
.add(
Tile::new(Tl {
bg: 9,
mid: 2,
mid: 3,
fg: 0,
})
.when(constraint!(nm.clone(), < -0.1)),
@ -52,7 +52,7 @@ impl Worldgen {
.add(
Tile::new(Tl {
bg: 7,
mid: 1,
mid: 2,
fg: 0,
})
.when(constraint!(nm, < 0.45)),

BIN
tiles.dat

Binary file not shown.