From baae917d0b75fafb3c7a970823867c7e5a1a2be0 Mon Sep 17 00:00:00 2001 From: Dominic Date: Sat, 6 Jul 2024 13:57:47 +0200 Subject: [PATCH 01/18] add empty overworld world type --- src/activities/mod.rs | 3 ++- src/activities/overworld.rs | 2 ++ src/activities/overworld/worldgen.rs | 9 +++++++++ src/main.rs | 15 ++++----------- 4 files changed, 17 insertions(+), 12 deletions(-) create mode 100644 src/activities/overworld/worldgen.rs diff --git a/src/activities/mod.rs b/src/activities/mod.rs index 5d0b11f..34a90d7 100644 --- a/src/activities/mod.rs +++ b/src/activities/mod.rs @@ -1,8 +1,9 @@ pub mod house; pub mod overworld; -#[derive(Debug)] +#[derive(Debug, Default)] pub enum Activity { + #[default] House, Overworld } diff --git a/src/activities/overworld.rs b/src/activities/overworld.rs index 2200ed6..ea12f22 100644 --- a/src/activities/overworld.rs +++ b/src/activities/overworld.rs @@ -1,5 +1,7 @@ use comfy::*; +pub mod worldgen; + pub fn draw(_state: &crate::State, _engine: &comfy::EngineContext) { draw_circle(vec2(0.0, 0.0), 0.5, GREEN, 0); } diff --git a/src/activities/overworld/worldgen.rs b/src/activities/overworld/worldgen.rs new file mode 100644 index 0000000..2a84e41 --- /dev/null +++ b/src/activities/overworld/worldgen.rs @@ -0,0 +1,9 @@ + +#[derive(Debug)] +pub struct Overworld; + +impl Default for Overworld { + fn default() -> Self { + Self + } +} diff --git a/src/main.rs b/src/main.rs index 4992bdf..a310d1e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,22 +1,15 @@ mod activities; mod game; -use activities::Activity; +use activities::{overworld::worldgen::Overworld, Activity}; use comfy::*; const GAME_NAME: &str = "Powercreep"; -#[derive(Debug)] +#[derive(Debug, Default)] struct State { - activity: Activity -} - -impl Default for State { - fn default() -> Self { - Self { - activity: Activity::House - } - } + activity: Activity, + overworld: Overworld, } impl GameLoop for State { -- 2.45.2 From 88c887a2ea226aee1eb04caed74b429a4b8112d0 Mon Sep 17 00:00:00 2001 From: Dominic Date: Sat, 6 Jul 2024 14:49:23 +0200 Subject: [PATCH 02/18] start api design --- src/activities/overworld/worldgen.rs | 89 ++++++++++++++++++++++++++-- src/main.rs | 2 +- 2 files changed, 86 insertions(+), 5 deletions(-) diff --git a/src/activities/overworld/worldgen.rs b/src/activities/overworld/worldgen.rs index 2a84e41..73dfd21 100644 --- a/src/activities/overworld/worldgen.rs +++ b/src/activities/overworld/worldgen.rs @@ -1,9 +1,90 @@ +use comfy::{IVec2, UVec2}; +use std::collections::HashMap; + +enum MovementCost { + /// No movement possible - cost infinitely high. + Infinite, + /// There is a path for this movement - movement is cheap. + Path, + /// There is no path and no obstacle. + Default, + /// There is an obstacle (i.e. fence) - movement is expensive. + Obstacle +} #[derive(Debug)] -pub struct Overworld; +struct Tile; -impl Default for Overworld { - fn default() -> Self { - Self +impl Tile { + pub fn can_stand_inside(&self) -> bool { + unimplemented!() + } + pub fn movement_cost_left(&self) -> MovementCost { + unimplemented!() + } + pub fn movement_cost_right(&self) -> MovementCost { + unimplemented!() + } + pub fn movement_cost_up(&self) -> MovementCost { + unimplemented!() + } + pub fn movement_cost_down(&self) -> MovementCost { + unimplemented!() + } + pub fn can_enter_house(&self) -> bool { + unimplemented!() + } +} + +/// The size of a chunk (both width and height). This value squared gives the amount of +/// tiles in the chunk. +const CHUNK_SIZE: u32 = 100; + +/// Chunks +#[derive(Debug)] +pub struct Chunk { + /// All tiles within this chunk. + tiles: [Tile; (CHUNK_SIZE * CHUNK_SIZE) as usize], + /// All paths that leave this chunk on the left hand side. + paths_left: Vec, + /// All paths that leave this chunk on the right hand side. + paths_right: Vec, + /// All paths that leave this chunk on the bottom side. + paths_bottom: Vec, + /// All paths that leave this chunk on the top side. + paths_top: Vec +} + +impl Chunk { + fn get_tile(&self, local_chunk_coords: UVec2) -> Option<&Tile> { + self.tiles + .get((local_chunk_coords.y * CHUNK_SIZE + local_chunk_coords.x) as usize) + } +} + +#[derive(Debug, Default)] +pub struct Overworld { + chunks: HashMap +} + +impl Overworld { + /// Return a [`Tile`] at the given world coordinates, or `None` if that tile has not + /// been generated yet. + fn get_tile(&self, world_coords: IVec2) -> Option<&Tile> { + let tile_coords = IVec2 { + x: world_coords.x.div_euclid(CHUNK_SIZE as _), + y: world_coords.y.div_euclid(CHUNK_SIZE as _) + }; + let local_coords = UVec2 { + x: world_coords.x.rem_euclid(CHUNK_SIZE as _) as _, + y: world_coords.y.rem_euclid(CHUNK_SIZE as _) as _ + }; + + let chunk = self.chunks.get(&tile_coords)?; + chunk.get_tile(local_coords) + } + + fn get_or_generate_tile(&self, world_coords: IVec2) -> &Tile { + unimplemented!() } } diff --git a/src/main.rs b/src/main.rs index a310d1e..aa9f605 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,7 +9,7 @@ const GAME_NAME: &str = "Powercreep"; #[derive(Debug, Default)] struct State { activity: Activity, - overworld: Overworld, + overworld: Overworld } impl GameLoop for State { -- 2.45.2 From 1b98dad9d09b65b0da1008689936a22a7f398cb6 Mon Sep 17 00:00:00 2001 From: luckyturtledev Date: Sat, 6 Jul 2024 16:16:38 +0200 Subject: [PATCH 03/18] add iterator to world --- src/activities/overworld/worldgen.rs | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/activities/overworld/worldgen.rs b/src/activities/overworld/worldgen.rs index 73dfd21..6b8d664 100644 --- a/src/activities/overworld/worldgen.rs +++ b/src/activities/overworld/worldgen.rs @@ -56,10 +56,18 @@ pub struct Chunk { } impl Chunk { - fn get_tile(&self, local_chunk_coords: UVec2) -> Option<&Tile> { + pub fn get_tile(&self, local_chunk_coords: UVec2) -> Option<&Tile> { self.tiles .get((local_chunk_coords.y * CHUNK_SIZE + local_chunk_coords.x) as usize) } + + /// iterate over all tiles and its local chunk coords + pub fn iter_tiles(&self) -> impl Iterator { + self.tiles.iter().enumerate().map(|(i, tile)| { + let i = i as u32; + (UVec2::new(i % CHUNK_SIZE, i / CHUNK_SIZE), tile) + }) + } } #[derive(Debug, Default)] @@ -70,7 +78,7 @@ pub struct Overworld { impl Overworld { /// Return a [`Tile`] at the given world coordinates, or `None` if that tile has not /// been generated yet. - fn get_tile(&self, world_coords: IVec2) -> Option<&Tile> { + pub fn get_tile(&self, world_coords: IVec2) -> Option<&Tile> { let tile_coords = IVec2 { x: world_coords.x.div_euclid(CHUNK_SIZE as _), y: world_coords.y.div_euclid(CHUNK_SIZE as _) @@ -87,4 +95,15 @@ impl Overworld { fn get_or_generate_tile(&self, world_coords: IVec2) -> &Tile { unimplemented!() } + + /// iterate over all tiles and its global coords + pub fn iter_tiles(&self) -> impl Iterator { + self.chunks.iter().flat_map(|(chunk_coords, chunk)| { + chunk.iter_tiles().map(|(local_coords, tile)| { + // never fail because chunksize fits alswas into i32 + let local_coords: IVec2 = local_coords.try_into().unwrap(); + (local_coords + (*chunk_coords * CHUNK_SIZE as i32), tile) + }) + }) + } } -- 2.45.2 From 39102594596ca1d14a40254ac11d8c70c7b4c033 Mon Sep 17 00:00:00 2001 From: Dominic Date: Sat, 6 Jul 2024 16:55:33 +0200 Subject: [PATCH 04/18] load assets --- build.rs | 207 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 build.rs diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..024db51 --- /dev/null +++ b/build.rs @@ -0,0 +1,207 @@ +use heck::ToSnakeCase as _; +use resvg::{tiny_skia, usvg}; +use std::{ + collections::BTreeMap, + env, + fs::{self, File}, + hash::{DefaultHasher, Hash, Hasher}, + io::{self, Write as _}, + path::{Path, PathBuf} +}; + +const TILE_SIZE: u32 = 64; + +#[derive(Default)] +struct Assets { + /// Assets directly contained within this asset group, mapping their name to the name + /// of the constant storing their png. + assets: BTreeMap, + + /// Asset groups contained within this asset group, mapping their name to the assets + /// that group contains. + groups: BTreeMap> +} + +struct AssetsWriter { + file: File, + root: Assets +} + +impl AssetsWriter { + fn new>(path: P) -> Self { + let mut file = File::create(path).expect("Failed to create assets file"); + writeln!(file, "// @generated").unwrap(); + Self { + file, + root: Assets::default() + } + } + + fn add_png>( + &mut self, + canonical_path: P, + png: tiny_skia::Pixmap + ) -> String { + let mut hasher = DefaultHasher::new(); + canonical_path.as_ref().hash(&mut hasher); + let hash = hasher.finish(); + let const_name = format!("ASSET_{hash:X}"); + + write!(self.file, "const {const_name}: &'static [u8] = &[").unwrap(); + for byte in png.encode_png().expect("Failed to encode png") { + write!(self.file, "{byte}, ").unwrap(); + } + writeln!(self.file, "];").unwrap(); + + const_name + } + + fn finish(mut self) { + fn write_assets_struct( + file: &mut File, + root: &Assets, + indent: &str + ) -> io::Result<()> { + for (group_name, group) in &root.groups { + writeln!(file, "{indent}mod {group_name} {{")?; + write_assets_struct(file, group, &format!("{indent}\t"))?; + writeln!(file, "}}")?; + } + + writeln!(file, "{indent}struct Asset {{")?; + for asset_name in root.assets.keys() { + writeln!( + file, + "{indent}\t{}: comfy::TextureHandle,", + asset_name.to_snake_case() + )?; + } + for group_name in root.groups.keys() { + writeln!( + file, + "{indent}\t{group_name}: &'static {group_name}::Assets," + )?; + } + writeln!(file, "{indent}}}")?; + + writeln!(file, "{indent}impl Assets {{")?; + writeln!( + file, + "{indent}\tpub fn load(c: &mut comfy::EngineContext) {{" + )?; + for asset_const_name in root.assets.values() { + writeln!(file, "{indent}\t\tc.load_texture_from_bytes({asset_const_name:?}, {asset_const_name});")?; + } + for group_name in root.groups.keys() { + writeln!(file, "{indent}\t\t{group_name}::Assets::load(c);")?; + } + writeln!(file, "{indent}\t}}")?; + writeln!(file, "{indent}}}")?; + + writeln!( + file, + "{indent}const ASSETS: comfy::Lazy = Lazy::new(|| Assets {{" + )?; + for (asset_name, asset_const_name) in &root.assets { + writeln!( + file, + "{indent}\t{}: comfy::texture_id({asset_const_name:?}),", + asset_name.to_snake_case() + )?; + } + for group_name in root.groups.keys() { + writeln!( + file, + "{indent}\t{group_name}: {group_name}::ASSETS.force()," + )?; + } + writeln!(file, "{indent}}});")?; + + Ok(()) + } + + write_assets_struct(&mut self.file, &self.root, "").unwrap(); + } +} + +fn main() { + println!("cargo::rerun-if-changed=build.rs"); + println!("cargo::rerun-if-changed=assets/"); + + let out_dir = env::var_os("OUT_DIR").unwrap(); + let assets = PathBuf::from(out_dir).join("assets.rs"); + println!("cargo::warning=Writing assets to {}", assets.display()); + println!("cargo::rustc-env=ASSETS_RS={}", assets.display()); + let mut writer = AssetsWriter::new(assets); + process_dir("assets", &mut writer, &mut Vec::new()); + writer.finish(); +} + +fn process_dir + Copy>( + dir: P, + writer: &mut AssetsWriter, + groups: &mut Vec +) { + for entry in fs::read_dir(dir).expect("Cannot read dir") { + let entry = entry.expect("Cannot read dir entry"); + let path = entry.path(); + if entry + .metadata() + .expect("Cannot read dir entry metadata") + .is_dir() + { + groups.push( + path.file_name() + .unwrap() + .to_str() + .expect("Non-UTF8 file names aren't allowed") + .into() + ); + process_dir(&path, writer, groups); + groups.pop(); + } else if path.extension().map(|ext| ext == "svg").unwrap_or(false) { + process_svg(&path, dir, writer, groups); + } + } +} + +fn process_svg + Copy, Q: AsRef>( + file: P, + dir: Q, + writer: &mut AssetsWriter, + groups: &[String] +) { + let bytes = fs::read(file).expect("Cannot read svg file"); + let tree = usvg::Tree::from_data(&bytes, &usvg::Options { + resources_dir: Some(dir.as_ref().to_owned()), + ..Default::default() + }) + .unwrap_or_else(|err| { + panic!("Cannot parse svg file {}: {err}", file.as_ref().display()) + }); + let mut pixmap = tiny_skia::Pixmap::new(TILE_SIZE, TILE_SIZE).unwrap(); + resvg::render(&tree, Default::default(), &mut pixmap.as_mut()); + + let const_name = writer.add_png( + file.as_ref() + .canonicalize() + .expect("Failed to canonicalize"), + pixmap + ); + let mut group = &mut writer.root; + for group_name in groups { + if !group.groups.contains_key(group_name) { + group.groups.insert(group_name.to_owned(), Box::default()); + } + group = group.groups.get_mut(group_name).unwrap(); + } + group.assets.insert( + file.as_ref() + .file_stem() + .expect("File doesn't have a stem") + .to_str() + .expect("Non-UTF8 file names aren't allowed") + .into(), + const_name + ); +} -- 2.45.2 From 4c4251288180df467965aed1804de5f4ca6f3c8e Mon Sep 17 00:00:00 2001 From: Dominic Date: Sat, 6 Jul 2024 16:57:45 +0200 Subject: [PATCH 05/18] assets to png and codegen --- Cargo.lock | 296 +++++++++++++++++++++++++++++ Cargo.toml | 4 + assets/overworld/house-example.svg | 0 build.rs | 1 + 4 files changed, 301 insertions(+) delete mode 100644 assets/overworld/house-example.svg diff --git a/Cargo.lock b/Cargo.lock index 431f36e..1981f07 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -136,6 +136,12 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33954243bd79057c2de7338850b85983a44588021f8a5fee574a8888c6de4344" +[[package]] +name = "arrayref" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" + [[package]] name = "arrayvec" version = "0.7.4" @@ -207,6 +213,12 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "bimap" version = "0.6.3" @@ -800,6 +812,12 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" +[[package]] +name = "data-url" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c297a1c74b71ae29df00c3e22dd9534821d60eb9af5a0192823fa2acea70c2a" + [[package]] name = "dispatch" version = "0.2.0" @@ -1030,6 +1048,12 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "float-cmp" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" + [[package]] name = "flume" version = "0.11.0" @@ -1039,6 +1063,29 @@ dependencies = [ "spin", ] +[[package]] +name = "fontconfig-parser" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a595cb550439a117696039dfc69830492058211b771a2a165379f2a1a53d84d" +dependencies = [ + "roxmltree 0.19.0", +] + +[[package]] +name = "fontdb" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e32eac81c1135c1df01d4e6d4233c47ba11f6a6d07f33e0bba09d18797077770" +dependencies = [ + "fontconfig-parser", + "log", + "memmap2", + "slotmap", + "tinyvec", + "ttf-parser 0.21.1", +] + [[package]] name = "fontdue" version = "0.7.3" @@ -1134,6 +1181,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "gif" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2" +dependencies = [ + "color_quant", + "weezl", +] + [[package]] name = "gimli" version = "0.28.1" @@ -1289,6 +1346,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hecs" version = "0.10.5" @@ -1381,6 +1444,12 @@ dependencies = [ "png", ] +[[package]] +name = "imagesize" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "029d73f573d8e8d63e6d5020011d3255b28c3ba85d6cf870a07184ed23de9284" + [[package]] name = "indexmap" version = "2.2.6" @@ -1548,6 +1617,16 @@ dependencies = [ "libc", ] +[[package]] +name = "kurbo" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e5aa9f0f96a938266bdb12928a67169e8d22c6a786fda8ed984b85e6ba93c3c" +dependencies = [ + "arrayvec", + "smallvec", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -1995,6 +2074,12 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "pico-args" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" + [[package]] name = "pin-project-lite" version = "0.2.14" @@ -2046,7 +2131,9 @@ name = "powercreep" version = "0.1.0" dependencies = [ "comfy", + "heck", "log", + "resvg", ] [[package]] @@ -2227,6 +2314,31 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" +[[package]] +name = "resvg" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "944d052815156ac8fa77eaac055220e95ba0b01fa8887108ca710c03805d9051" +dependencies = [ + "gif", + "jpeg-decoder", + "log", + "pico-args", + "rgb", + "svgtypes", + "tiny-skia", + "usvg", +] + +[[package]] +name = "rgb" +version = "0.8.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7439be6844e40133eda024efd85bf07f59d0dd2f59b10c00dd6cfb92cc5c741" +dependencies = [ + "bytemuck", +] + [[package]] name = "ringbuf" version = "0.3.3" @@ -2236,6 +2348,18 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "roxmltree" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cd14fd5e3b777a7422cca79358c57a8f6e3a703d9ac187448d0daf220c2407f" + +[[package]] +name = "roxmltree" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97" + [[package]] name = "rustc-demangle" version = "0.1.24" @@ -2261,6 +2385,22 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustybuzz" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfb9cf8877777222e4a3bc7eb247e398b56baba500c38c1c46842431adc8b55c" +dependencies = [ + "bitflags 2.6.0", + "bytemuck", + "smallvec", + "ttf-parser 0.21.1", + "unicode-bidi-mirroring", + "unicode-ccc", + "unicode-properties", + "unicode-script", +] + [[package]] name = "same-file" version = "1.0.6" @@ -2326,6 +2466,21 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "832ddd7df0d98d6fd93b973c330b7c8e0742d5cb8f1afc7dea89dba4d2531aa1" +[[package]] +name = "simplecss" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a11be7c62927d9427e9f40f3444d5499d868648e2edbc4e2116de69e7ec0e89d" +dependencies = [ + "log", +] + +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + [[package]] name = "slab" version = "0.4.9" @@ -2417,12 +2572,31 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "strict-num" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" +dependencies = [ + "float-cmp", +] + [[package]] name = "svg_fmt" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20e16a0f46cf5fd675563ef54f26e83e20f2366bcf027bcb3cc3ed2b98aaf2ca" +[[package]] +name = "svgtypes" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fae3064df9b89391c9a76a0425a69d124aee9c5c28455204709e72c39868a43c" +dependencies = [ + "kurbo", + "siphasher", +] + [[package]] name = "symphonia" version = "0.5.4" @@ -2575,6 +2749,47 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92e170f93360bf9ae6fe3c31116bbf27adb1d054cedd6bc3d7857e34f2d98d0b" +[[package]] +name = "tiny-skia" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" +dependencies = [ + "arrayref", + "arrayvec", + "bytemuck", + "cfg-if", + "log", + "png", + "tiny-skia-path", +] + +[[package]] +name = "tiny-skia-path" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" +dependencies = [ + "arrayref", + "bytemuck", + "strict-num", +] + +[[package]] +name = "tinyvec" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6b6a2fb3a985e99cebfaefa9faa3024743da73304ca1c683a36429613d3d22" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "toml_datetime" version = "0.6.6" @@ -2614,6 +2829,12 @@ version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b3e06c9b9d80ed6b745c7159c40b311ad2916abb34a49e9be2653b90db0d8dd" +[[package]] +name = "ttf-parser" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c591d83f69777866b9126b24c6dd9a18351f177e49d625920d19f989fd31cf8" + [[package]] name = "ttf-parser" version = "0.24.0" @@ -2629,18 +2850,54 @@ dependencies = [ "rustc-hash", ] +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-bidi-mirroring" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23cb788ffebc92c5948d0e997106233eeb1d8b9512f93f41651f52b6c5f5af86" + +[[package]] +name = "unicode-ccc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df77b101bcc4ea3d78dafc5ad7e4f58ceffe0b2b16bf446aeb50b6cb4157656" + [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "unicode-properties" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4259d9d4425d9f0661581b804cb85fe66a4c631cadd8f490d1c13a35d5d9291" + +[[package]] +name = "unicode-script" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad8d71f5726e5f285a935e9fe8edfd53f0491eb6e9a5774097fdabee7cd8c9cd" + [[package]] name = "unicode-segmentation" version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +[[package]] +name = "unicode-vo" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d386ff53b415b7fe27b50bb44679e2cc4660272694b7b6f3326d8480823a94" + [[package]] name = "unicode-width" version = "0.1.13" @@ -2653,6 +2910,33 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +[[package]] +name = "usvg" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b84ea542ae85c715f07b082438a4231c3760539d902e11d093847a0b22963032" +dependencies = [ + "base64", + "data-url", + "flate2", + "fontdb", + "imagesize", + "kurbo", + "log", + "pico-args", + "roxmltree 0.20.0", + "rustybuzz", + "simplecss", + "siphasher", + "strict-num", + "svgtypes", + "tiny-skia-path", + "unicode-bidi", + "unicode-script", + "unicode-vo", + "xmlwriter", +] + [[package]] name = "version_check" version = "0.9.4" @@ -2869,6 +3153,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "weezl" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" + [[package]] name = "wgpu" version = "0.19.4" @@ -3385,6 +3675,12 @@ version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "791978798f0597cfc70478424c2b4fdc2b7a8024aaff78497ef00f24ef674193" +[[package]] +name = "xmlwriter" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9" + [[package]] name = "zerocopy" version = "0.7.35" diff --git a/Cargo.toml b/Cargo.toml index 9585c1b..dfff8c0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,3 +17,7 @@ opt-level = 3 [dependencies] comfy = { version = "0.4.0", features = ["wayland"] } log = "0.4.22" + +[build-dependencies] +heck = "0.5" +resvg = "0.42" diff --git a/assets/overworld/house-example.svg b/assets/overworld/house-example.svg deleted file mode 100644 index e69de29..0000000 diff --git a/build.rs b/build.rs index 024db51..4539aa5 100644 --- a/build.rs +++ b/build.rs @@ -47,6 +47,7 @@ impl AssetsWriter { let hash = hasher.finish(); let const_name = format!("ASSET_{hash:X}"); + writeln!(self.file, "// {}", canonical_path.as_ref().display()).unwrap(); write!(self.file, "const {const_name}: &'static [u8] = &[").unwrap(); for byte in png.encode_png().expect("Failed to encode png") { write!(self.file, "{byte}, ").unwrap(); -- 2.45.2 From 44b257c710d067596c9caabaf39ce3a8ac73835b Mon Sep 17 00:00:00 2001 From: Dominic Date: Sat, 6 Jul 2024 17:18:28 +0200 Subject: [PATCH 06/18] loading assets "works" --- build.rs | 9 +++++---- src/activities/house.rs | 6 +++--- src/activities/overworld.rs | 6 +++--- src/game.rs | 4 ++-- src/main.rs | 26 +++++++++++++++++++++++--- 5 files changed, 36 insertions(+), 15 deletions(-) diff --git a/build.rs b/build.rs index 4539aa5..c0cee5a 100644 --- a/build.rs +++ b/build.rs @@ -65,11 +65,12 @@ impl AssetsWriter { ) -> io::Result<()> { for (group_name, group) in &root.groups { writeln!(file, "{indent}mod {group_name} {{")?; + writeln!(file, "{indent}\tuse super::*;")?; write_assets_struct(file, group, &format!("{indent}\t"))?; writeln!(file, "}}")?; } - writeln!(file, "{indent}struct Asset {{")?; + writeln!(file, "{indent}pub struct Assets {{")?; for asset_name in root.assets.keys() { writeln!( file, @@ -88,7 +89,7 @@ impl AssetsWriter { writeln!(file, "{indent}impl Assets {{")?; writeln!( file, - "{indent}\tpub fn load(c: &mut comfy::EngineContext) {{" + "{indent}\tpub fn load(c: &mut comfy::EngineContext<'_>) {{" )?; for asset_const_name in root.assets.values() { writeln!(file, "{indent}\t\tc.load_texture_from_bytes({asset_const_name:?}, {asset_const_name});")?; @@ -101,7 +102,7 @@ impl AssetsWriter { writeln!( file, - "{indent}const ASSETS: comfy::Lazy = Lazy::new(|| Assets {{" + "{indent}pub static ASSETS: comfy::Lazy = comfy::Lazy::new(|| Assets {{" )?; for (asset_name, asset_const_name) in &root.assets { writeln!( @@ -113,7 +114,7 @@ impl AssetsWriter { for group_name in root.groups.keys() { writeln!( file, - "{indent}\t{group_name}: {group_name}::ASSETS.force()," + "{indent}\t{group_name}: comfy::Lazy::force(&{group_name}::ASSETS)," )?; } writeln!(file, "{indent}}});")?; diff --git a/src/activities/house.rs b/src/activities/house.rs index 8043a2d..189ae64 100644 --- a/src/activities/house.rs +++ b/src/activities/house.rs @@ -1,7 +1,7 @@ -use comfy::*; +use comfy::{draw_circle, vec2, EngineContext, RED}; -pub fn draw(_state: &crate::State, _engine: &comfy::EngineContext) { +pub fn draw(_state: &crate::State, _engine: &EngineContext<'_>) { draw_circle(vec2(0.0, 0.0), 0.5, RED, 0); } -pub fn update(_state: &mut crate::State, _engine: &mut comfy::EngineContext) {} +pub fn update(_state: &mut crate::State, _engine: &mut EngineContext<'_>) {} diff --git a/src/activities/overworld.rs b/src/activities/overworld.rs index ea12f22..b1a6300 100644 --- a/src/activities/overworld.rs +++ b/src/activities/overworld.rs @@ -1,9 +1,9 @@ -use comfy::*; +use comfy::{draw_circle, vec2, EngineContext, GREEN}; pub mod worldgen; -pub fn draw(_state: &crate::State, _engine: &comfy::EngineContext) { +pub fn draw(_state: &crate::State, _engine: &EngineContext<'_>) { draw_circle(vec2(0.0, 0.0), 0.5, GREEN, 0); } -pub fn update(_state: &mut crate::State, _engine: &mut comfy::EngineContext) {} +pub fn update(_state: &mut crate::State, _engine: &mut EngineContext<'_>) {} diff --git a/src/game.rs b/src/game.rs index a91fe39..9e8eb7a 100644 --- a/src/game.rs +++ b/src/game.rs @@ -5,14 +5,14 @@ use crate::{ State }; -pub fn update(state: &mut State, engine: &mut EngineContext) { +pub fn update(state: &mut State, engine: &mut EngineContext<'_>) { match state.activity { Activity::House => house::update(state, engine), Activity::Overworld => overworld::update(state, engine) } } -pub fn draw(state: &State, engine: &EngineContext) { +pub fn draw(state: &State, engine: &EngineContext<'_>) { match state.activity { Activity::House => house::draw(state, engine), Activity::Overworld => overworld::draw(state, engine) diff --git a/src/main.rs b/src/main.rs index aa9f605..f231ac7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,13 +1,24 @@ +#![warn(rust_2018_idioms)] +#![forbid(clippy::wildcard_imports, elided_lifetimes_in_paths, unsafe_code)] + +mod assets { + include!(env!("ASSETS_RS")); +} + mod activities; mod game; -use activities::{overworld::worldgen::Overworld, Activity}; -use comfy::*; +use self::{ + activities::{overworld::worldgen::Overworld, Activity}, + assets::Assets +}; +use comfy::{GameLoop, EngineState, EngineContext, GameConfig, init_game_config, run_comfy_main_async, pollster}; const GAME_NAME: &str = "Powercreep"; #[derive(Debug, Default)] struct State { + setup_called: bool, activity: Activity, overworld: Overworld } @@ -17,7 +28,12 @@ impl GameLoop for State { Self::default() } - fn update(&mut self, engine: &mut EngineContext) { + fn update(&mut self, engine: &mut EngineContext<'_>) { + if !self.setup_called { + setup(engine); + self.setup_called = true; + } + game::update(self, engine); game::draw(self, engine); } @@ -27,6 +43,10 @@ fn config(config: GameConfig) -> GameConfig { config } +fn setup(ctx: &mut EngineContext<'_>) { + Assets::load(ctx); +} + async fn run() { init_game_config(GAME_NAME.to_string(), env!("CARGO_PKG_VERSION"), config); let mut engine = EngineState::new(); -- 2.45.2 From 284163b428f089561c6dc89f144274e64d44cc9a Mon Sep 17 00:00:00 2001 From: luckyturtledev Date: Sat, 6 Jul 2024 17:19:44 +0200 Subject: [PATCH 07/18] draw overworld --- src/activities/overworld.rs | 16 +++++++++++++++- src/activities/overworld/worldgen.rs | 9 ++++++--- src/game.rs | 24 ++++++++++++++++++++++++ src/main.rs | 1 + 4 files changed, 46 insertions(+), 4 deletions(-) diff --git a/src/activities/overworld.rs b/src/activities/overworld.rs index b1a6300..6f530b1 100644 --- a/src/activities/overworld.rs +++ b/src/activities/overworld.rs @@ -1,9 +1,23 @@ use comfy::{draw_circle, vec2, EngineContext, GREEN}; +use crate::game::ZLayer; + pub mod worldgen; -pub fn draw(_state: &crate::State, _engine: &EngineContext<'_>) { +pub fn draw(state: &crate::State, _engine: &comfy::EngineContext) { draw_circle(vec2(0.0, 0.0), 0.5, GREEN, 0); + for (coords, tile) in state.overworld.iter_tiles() { + for (i, texture) in tile.textures.iter().rev().enumerate() { + let i = i as i32; + draw_sprite( + *texture, + coords.as_vec2(), + Default::default(), + ZLayer::MapMax - i, + Vec2::ONE + ) + } + } } pub fn update(_state: &mut crate::State, _engine: &mut EngineContext<'_>) {} diff --git a/src/activities/overworld/worldgen.rs b/src/activities/overworld/worldgen.rs index 6b8d664..53f633a 100644 --- a/src/activities/overworld/worldgen.rs +++ b/src/activities/overworld/worldgen.rs @@ -1,7 +1,8 @@ -use comfy::{IVec2, UVec2}; +use comfy::{IVec2, TextureHandle, UVec2}; + use std::collections::HashMap; -enum MovementCost { +pub enum MovementCost { /// No movement possible - cost infinitely high. Infinite, /// There is a path for this movement - movement is cheap. @@ -13,7 +14,9 @@ enum MovementCost { } #[derive(Debug)] -struct Tile; +pub struct Tile { + pub textures: Vec +} impl Tile { pub fn can_stand_inside(&self) -> bool { diff --git a/src/game.rs b/src/game.rs index 9e8eb7a..e80c3c9 100644 --- a/src/game.rs +++ b/src/game.rs @@ -1,3 +1,5 @@ +use std::ops::Sub; + use comfy::*; use crate::{ @@ -5,6 +7,28 @@ use crate::{ State }; +#[repr(i32)] +pub enum ZLayer { + MapMax = -1, + Human = 0, + Ghost = 1 +} + +impl From for i32 { + fn from(value: ZLayer) -> Self { + // safe because #[repr(i32)] + value as i32 + } +} + +impl Sub for ZLayer { + type Output = i32; + + fn sub(self, other: i32) -> Self::Output { + i32::from(self) - other + } +} + pub fn update(state: &mut State, engine: &mut EngineContext<'_>) { match state.activity { Activity::House => house::update(state, engine), diff --git a/src/main.rs b/src/main.rs index f231ac7..b27adb0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +#[allow(dead_code, unused_variables)] #![warn(rust_2018_idioms)] #![forbid(clippy::wildcard_imports, elided_lifetimes_in_paths, unsafe_code)] -- 2.45.2 From ce45bc622dfd54e3cf333541061b54a14ef10a74 Mon Sep 17 00:00:00 2001 From: luckyturtledev Date: Sat, 6 Jul 2024 17:27:29 +0200 Subject: [PATCH 08/18] fix some merge stuff --- src/activities/overworld.rs | 4 ++-- src/main.rs | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/activities/overworld.rs b/src/activities/overworld.rs index 6f530b1..185c66e 100644 --- a/src/activities/overworld.rs +++ b/src/activities/overworld.rs @@ -1,10 +1,10 @@ -use comfy::{draw_circle, vec2, EngineContext, GREEN}; +use comfy::{draw_circle, draw_sprite, vec2, EngineContext, Vec2, GREEN}; use crate::game::ZLayer; pub mod worldgen; -pub fn draw(state: &crate::State, _engine: &comfy::EngineContext) { +pub fn draw(state: &crate::State, _engine: &comfy::EngineContext<'_>) { draw_circle(vec2(0.0, 0.0), 0.5, GREEN, 0); for (coords, tile) in state.overworld.iter_tiles() { for (i, texture) in tile.textures.iter().rev().enumerate() { diff --git a/src/main.rs b/src/main.rs index b27adb0..c8c6b6a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ -#[allow(dead_code, unused_variables)] #![warn(rust_2018_idioms)] #![forbid(clippy::wildcard_imports, elided_lifetimes_in_paths, unsafe_code)] +#[allow(dead_code, unused_variables)] mod assets { include!(env!("ASSETS_RS")); @@ -13,7 +13,10 @@ use self::{ activities::{overworld::worldgen::Overworld, Activity}, assets::Assets }; -use comfy::{GameLoop, EngineState, EngineContext, GameConfig, init_game_config, run_comfy_main_async, pollster}; +use comfy::{ + init_game_config, pollster, run_comfy_main_async, EngineContext, EngineState, + GameConfig, GameLoop +}; const GAME_NAME: &str = "Powercreep"; -- 2.45.2 From f7e65c6cbba92c29671e4d06b92edb87c6f6b5f7 Mon Sep 17 00:00:00 2001 From: Dominic Date: Sat, 6 Jul 2024 17:29:10 +0200 Subject: [PATCH 09/18] fix clippy lint breaking my code --- build.rs | 1 + src/main.rs | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/build.rs b/build.rs index c0cee5a..3615f37 100644 --- a/build.rs +++ b/build.rs @@ -65,6 +65,7 @@ impl AssetsWriter { ) -> io::Result<()> { for (group_name, group) in &root.groups { writeln!(file, "{indent}mod {group_name} {{")?; + writeln!(file, "{indent}\t#[allow(clippy::wildcard_imports)]")?; writeln!(file, "{indent}\tuse super::*;")?; write_assets_struct(file, group, &format!("{indent}\t"))?; writeln!(file, "}}")?; diff --git a/src/main.rs b/src/main.rs index c8c6b6a..9b93361 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ #![warn(rust_2018_idioms)] -#![forbid(clippy::wildcard_imports, elided_lifetimes_in_paths, unsafe_code)] -#[allow(dead_code, unused_variables)] +#![deny(clippy::wildcard_imports)] +#![forbid(elided_lifetimes_in_paths, unsafe_code)] mod assets { include!(env!("ASSETS_RS")); -- 2.45.2 From 7ac86cbc11397b9f3e9042da4fe4cc5fe647f4e4 Mon Sep 17 00:00:00 2001 From: Dominic Date: Sat, 6 Jul 2024 17:50:30 +0200 Subject: [PATCH 10/18] fix lint --- src/game.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/game.rs b/src/game.rs index e80c3c9..fbe5ab7 100644 --- a/src/game.rs +++ b/src/game.rs @@ -1,11 +1,9 @@ -use std::ops::Sub; - -use comfy::*; - use crate::{ activities::{house, overworld, Activity}, State }; +use comfy::EngineContext; +use std::ops::Sub; #[repr(i32)] pub enum ZLayer { -- 2.45.2 From f3b8d4403425b357a2eec28a389c6a956cb2d76b Mon Sep 17 00:00:00 2001 From: Dominic Date: Sat, 6 Jul 2024 18:45:54 +0200 Subject: [PATCH 11/18] very basic worldgen --- build.rs | 4 +- src/activities/overworld.rs | 2 +- src/activities/overworld/worldgen.rs | 231 +++++++++++++++++++++++++-- 3 files changed, 218 insertions(+), 19 deletions(-) diff --git a/build.rs b/build.rs index 3615f37..f0593cb 100644 --- a/build.rs +++ b/build.rs @@ -75,14 +75,14 @@ impl AssetsWriter { for asset_name in root.assets.keys() { writeln!( file, - "{indent}\t{}: comfy::TextureHandle,", + "pub {indent}\t{}: comfy::TextureHandle,", asset_name.to_snake_case() )?; } for group_name in root.groups.keys() { writeln!( file, - "{indent}\t{group_name}: &'static {group_name}::Assets," + "pub {indent}\t{group_name}: &'static {group_name}::Assets," )?; } writeln!(file, "{indent}}}")?; diff --git a/src/activities/overworld.rs b/src/activities/overworld.rs index 185c66e..32d4317 100644 --- a/src/activities/overworld.rs +++ b/src/activities/overworld.rs @@ -7,7 +7,7 @@ pub mod worldgen; pub fn draw(state: &crate::State, _engine: &comfy::EngineContext<'_>) { draw_circle(vec2(0.0, 0.0), 0.5, GREEN, 0); for (coords, tile) in state.overworld.iter_tiles() { - for (i, texture) in tile.textures.iter().rev().enumerate() { + for (i, texture) in tile.textures().iter().rev().enumerate() { let i = i as i32; draw_sprite( *texture, diff --git a/src/activities/overworld/worldgen.rs b/src/activities/overworld/worldgen.rs index 53f633a..c4aab95 100644 --- a/src/activities/overworld/worldgen.rs +++ b/src/activities/overworld/worldgen.rs @@ -1,5 +1,5 @@ +use crate::assets::ASSETS; use comfy::{IVec2, TextureHandle, UVec2}; - use std::collections::HashMap; pub enum MovementCost { @@ -13,12 +13,66 @@ pub enum MovementCost { Obstacle } -#[derive(Debug)] -pub struct Tile { - pub textures: Vec +#[derive(Clone, Copy, Debug)] +pub enum Tile { + Grass, + + Path { + left: bool, + right: bool, + top: bool, + bottom: bool + }, + + House { + texture: TextureHandle, + door: bool + } } impl Tile { + pub fn textures(&self) -> Vec { + match self { + Self::Grass => vec![ASSETS.overworld.grass], + + Self::Path { + left, + right, + top, + bottom + } => { + let path_texture = match (left, right, top, bottom) { + (true, true, false, false) => ASSETS.overworld.path_horiz, + (false, false, true, true) => ASSETS.overworld.path_vert, + + (true, false, true, false) => ASSETS.overworld.path_top_left, + (true, false, false, true) => ASSETS.overworld.path_bottom_left, + (false, true, true, false) => ASSETS.overworld.path_top_right, + (false, true, false, true) => ASSETS.overworld.path_bottom_right, + + (true, true, true, false) => ASSETS.overworld.path_top_left_right, + (true, true, false, true) => ASSETS.overworld.path_bottom_left_right, + (true, false, true, true) => ASSETS.overworld.path_top_left_bottom, + (false, true, true, true) => ASSETS.overworld.path_top_right_bottom, + + (true, true, true, true) => ASSETS.overworld.path_crossing, + + (true, false, false, false) + | (false, true, false, false) + | (false, false, true, false) + | (false, false, false, true) => panic!("We don't have no dead ends"), + (false, false, false, false) => panic!("I think you meant grass?!?") + }; + + vec![ASSETS.overworld.grass, path_texture] + }, + + Self::House { texture, .. } => { + vec![ASSETS.overworld.grass, *texture] + } + } + } + pub fn can_stand_inside(&self) -> bool { unimplemented!() } @@ -45,6 +99,7 @@ const CHUNK_SIZE: u32 = 100; /// Chunks #[derive(Debug)] +#[allow(dead_code)] pub struct Chunk { /// All tiles within this chunk. tiles: [Tile; (CHUNK_SIZE * CHUNK_SIZE) as usize], @@ -59,6 +114,137 @@ pub struct Chunk { } impl Chunk { + pub fn generate_chunk() -> Self { + // TODO real worldgen + // for the time being we just copy this pre-made house block into the chunk + + fn path(left: bool, right: bool, top: bool, bottom: bool) -> Tile { + Tile::Path { + left, + right, + top, + bottom + } + } + + fn house(texture: TextureHandle) -> Tile { + Tile::House { + texture, + door: false + } + } + + let path_horiz = path(true, true, false, false); + let path_vert = path(false, false, true, true); + let path_crossing = path(true, true, true, true); + let grass = Tile::Grass; + + let block = [ + [ + path_crossing, + path_horiz, + path_horiz, + path_horiz, + path_horiz, + path_horiz, + path_horiz, + path_horiz, + path_horiz, + path_horiz, + path_crossing + ], + [ + path_vert, + grass, + grass, + grass, + house(ASSETS.overworld.house_roof_top), + grass, + grass, + grass, + grass, + grass, + path_vert + ], + [ + path_vert, + grass, + grass, + house(ASSETS.overworld.house_roof_mid_left), + house(ASSETS.overworld.house_mid_window), + house(ASSETS.overworld.house_roof_mid_right), + grass, + grass, + grass, + grass, + path_vert + ], + [ + path_vert, + grass, + house(ASSETS.overworld.house_roof_left), + house(ASSETS.overworld.house_mid_window), + house(ASSETS.overworld.house_mid), + house(ASSETS.overworld.house_mid_window), + house(ASSETS.overworld.house_roof_right), + grass, + grass, + grass, + path_vert + ], + [ + path_vert, + grass, + house(ASSETS.overworld.house_bottom_left), + house(ASSETS.overworld.house_bottom_door), + house(ASSETS.overworld.house_bottom_window), + house(ASSETS.overworld.house_bottom_window), + house(ASSETS.overworld.house_bottom_right), + grass, + grass, + grass, + path_vert + ], + [ + path_vert, + grass, + grass, + path(false, true, true, false), + path_horiz, + path_horiz, + path_horiz, + path_horiz, + path_horiz, + path_horiz, + path(true, false, true, true) + ], + [ + path_vert, grass, grass, grass, grass, grass, grass, grass, grass, grass, + path_vert + ], + [ + path_vert, grass, grass, grass, grass, grass, grass, grass, grass, grass, + path_vert + ] + ]; + + // and then we copy this pre-made block into our chunk + let mut tiles = [Tile::Grass; (CHUNK_SIZE * CHUNK_SIZE) as usize]; + for y in 0 .. CHUNK_SIZE { + for x in 0 .. CHUNK_SIZE { + let row = block[y as usize % block.len()]; + tiles[(y * CHUNK_SIZE + x) as usize] = row[x as usize % row.len()]; + } + } + Self { + tiles, + paths_left: vec![], + paths_right: vec![], + paths_bottom: vec![], + paths_top: vec![] + } + } + pub fn get_tile(&self, local_chunk_coords: UVec2) -> Option<&Tile> { self.tiles .get((local_chunk_coords.y * CHUNK_SIZE + local_chunk_coords.x) as usize) @@ -78,25 +264,38 @@ pub struct Overworld { chunks: HashMap } +fn world_to_chunk_and_local_coords(world_coords: IVec2) -> (IVec2, UVec2) { + let chunk_coords = IVec2 { + x: world_coords.x.div_euclid(CHUNK_SIZE as _), + y: world_coords.y.div_euclid(CHUNK_SIZE as _) + }; + let local_chunk_coords = UVec2 { + x: world_coords.x.rem_euclid(CHUNK_SIZE as _) as _, + y: world_coords.y.rem_euclid(CHUNK_SIZE as _) as _ + }; + (chunk_coords, local_chunk_coords) +} + impl Overworld { /// Return a [`Tile`] at the given world coordinates, or `None` if that tile has not /// been generated yet. pub fn get_tile(&self, world_coords: IVec2) -> Option<&Tile> { - let tile_coords = IVec2 { - x: world_coords.x.div_euclid(CHUNK_SIZE as _), - y: world_coords.y.div_euclid(CHUNK_SIZE as _) - }; - let local_coords = UVec2 { - x: world_coords.x.rem_euclid(CHUNK_SIZE as _) as _, - y: world_coords.y.rem_euclid(CHUNK_SIZE as _) as _ - }; + let (chunk_coords, local_chunk_coords) = + world_to_chunk_and_local_coords(world_coords); - let chunk = self.chunks.get(&tile_coords)?; - chunk.get_tile(local_coords) + let chunk = self.chunks.get(&chunk_coords)?; + chunk.get_tile(local_chunk_coords) } - fn get_or_generate_tile(&self, world_coords: IVec2) -> &Tile { - unimplemented!() + fn get_or_generate_tile(&mut self, world_coords: IVec2) -> &Tile { + let (chunk_coords, local_chunk_coords) = + world_to_chunk_and_local_coords(world_coords); + + let chunk = self + .chunks + .entry(chunk_coords) + .or_insert_with(Chunk::generate_chunk); + chunk.get_tile(local_chunk_coords).unwrap() } /// iterate over all tiles and its global coords -- 2.45.2 From 3d5b5d37b623870b122c4fd1eae1e498ec671a0a Mon Sep 17 00:00:00 2001 From: Dominic Date: Sat, 6 Jul 2024 18:46:40 +0200 Subject: [PATCH 12/18] make fn pub --- src/activities/overworld/worldgen.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/activities/overworld/worldgen.rs b/src/activities/overworld/worldgen.rs index c4aab95..07fbd96 100644 --- a/src/activities/overworld/worldgen.rs +++ b/src/activities/overworld/worldgen.rs @@ -287,7 +287,7 @@ impl Overworld { chunk.get_tile(local_chunk_coords) } - fn get_or_generate_tile(&mut self, world_coords: IVec2) -> &Tile { + pub fn get_or_generate_tile(&mut self, world_coords: IVec2) -> &Tile { let (chunk_coords, local_chunk_coords) = world_to_chunk_and_local_coords(world_coords); -- 2.45.2 From caf17aa3e5de2258edab2b0270091c88ed0320f0 Mon Sep 17 00:00:00 2001 From: Dominic Date: Sat, 6 Jul 2024 18:50:41 +0200 Subject: [PATCH 13/18] lukas please fix --- src/activities/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/activities/mod.rs b/src/activities/mod.rs index 34a90d7..e3d04c2 100644 --- a/src/activities/mod.rs +++ b/src/activities/mod.rs @@ -3,7 +3,7 @@ pub mod overworld; #[derive(Debug, Default)] pub enum Activity { - #[default] House, + #[default] Overworld } -- 2.45.2 From fdfe1c8333b5dc44ab20acbbec92b3d47793ad7b Mon Sep 17 00:00:00 2001 From: luckyturtledev Date: Sat, 6 Jul 2024 19:32:17 +0200 Subject: [PATCH 14/18] some draw fixs --- src/activities/overworld.rs | 18 +++++++++++++----- src/activities/overworld/worldgen.rs | 2 ++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/activities/overworld.rs b/src/activities/overworld.rs index 32d4317..cc44c13 100644 --- a/src/activities/overworld.rs +++ b/src/activities/overworld.rs @@ -1,23 +1,31 @@ -use comfy::{draw_circle, draw_sprite, vec2, EngineContext, Vec2, GREEN}; +use comfy::{ + draw_circle, draw_rect_outline, draw_sprite, main_camera_mut, texture_id, vec2, + EngineContext, IVec2, Vec2, GREEN, RED, WHITE +}; use crate::game::ZLayer; pub mod worldgen; pub fn draw(state: &crate::State, _engine: &comfy::EngineContext<'_>) { - draw_circle(vec2(0.0, 0.0), 0.5, GREEN, 0); for (coords, tile) in state.overworld.iter_tiles() { for (i, texture) in tile.textures().iter().rev().enumerate() { let i = i as i32; draw_sprite( *texture, coords.as_vec2(), - Default::default(), + WHITE, ZLayer::MapMax - i, Vec2::ONE - ) + ); + draw_rect_outline(coords.as_vec2(), Vec2::ONE, 0.1, RED, 10); } } } -pub fn update(_state: &mut crate::State, _engine: &mut EngineContext<'_>) {} +pub fn update(state: &mut crate::State, _engine: &mut EngineContext<'_>) { + let mut camera = main_camera_mut(); + camera.center = Vec2::ZERO; + camera.zoom = 30.0; + state.overworld.get_or_generate_tile(IVec2::ZERO); +} diff --git a/src/activities/overworld/worldgen.rs b/src/activities/overworld/worldgen.rs index 07fbd96..e12bd0f 100644 --- a/src/activities/overworld/worldgen.rs +++ b/src/activities/overworld/worldgen.rs @@ -1,5 +1,6 @@ use crate::assets::ASSETS; use comfy::{IVec2, TextureHandle, UVec2}; +use log::info; use std::collections::HashMap; pub enum MovementCost { @@ -115,6 +116,7 @@ pub struct Chunk { impl Chunk { pub fn generate_chunk() -> Self { + info!("gen chunk"); // TODO real worldgen // for the time being we just copy this pre-made house block into the chunk -- 2.45.2 From dba691783a3e40a5156354334078c01acb6634fc Mon Sep 17 00:00:00 2001 From: Dominic Date: Sat, 6 Jul 2024 19:39:51 +0200 Subject: [PATCH 15/18] fix resvg scaling --- build.rs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/build.rs b/build.rs index f0593cb..5d82e68 100644 --- a/build.rs +++ b/build.rs @@ -47,12 +47,17 @@ impl AssetsWriter { let hash = hasher.finish(); let const_name = format!("ASSET_{hash:X}"); + let out_dir = env::var_os("OUT_DIR").unwrap(); + let out_dir: PathBuf = out_dir.into(); + png.save_png(out_dir.join(format!("{const_name}.png"))) + .expect("Failed to save png"); + writeln!(self.file, "// {}", canonical_path.as_ref().display()).unwrap(); - write!(self.file, "const {const_name}: &'static [u8] = &[").unwrap(); - for byte in png.encode_png().expect("Failed to encode png") { - write!(self.file, "{byte}, ").unwrap(); - } - writeln!(self.file, "];").unwrap(); + writeln!( + self.file, + "const {const_name}: &[u8] = include_bytes!(\"{const_name}.png\");" + ) + .unwrap(); const_name } @@ -183,7 +188,11 @@ fn process_svg + Copy, Q: AsRef>( panic!("Cannot parse svg file {}: {err}", file.as_ref().display()) }); let mut pixmap = tiny_skia::Pixmap::new(TILE_SIZE, TILE_SIZE).unwrap(); - resvg::render(&tree, Default::default(), &mut pixmap.as_mut()); + let transform = tiny_skia::Transform::from_scale( + TILE_SIZE as f32 / tree.size().width(), + TILE_SIZE as f32 / tree.size().height() + ); + resvg::render(&tree, transform, &mut pixmap.as_mut()); let const_name = writer.add_png( file.as_ref() -- 2.45.2 From 9231a8b37e97342c9e9398f7dd5cf5abc4d8e808 Mon Sep 17 00:00:00 2001 From: Dominic Date: Sat, 6 Jul 2024 22:14:48 +0200 Subject: [PATCH 16/18] fix lints --- src/activities/house/grid.rs | 2 +- src/activities/house/mod.rs | 4 ++-- src/activities/house/player.rs | 4 ++-- src/activities/{overworld.rs => overworld/mod.rs} | 4 ++-- src/activities/overworld/worldgen.rs | 3 +++ 5 files changed, 10 insertions(+), 7 deletions(-) rename src/activities/{overworld.rs => overworld/mod.rs} (84%) diff --git a/src/activities/house/grid.rs b/src/activities/house/grid.rs index 114eace..5922fd9 100644 --- a/src/activities/house/grid.rs +++ b/src/activities/house/grid.rs @@ -1,4 +1,4 @@ -use comfy::*; +use comfy::{draw_circle, draw_line, error, vec2, Vec2, BLUE}; #[derive(Debug)] pub struct Grid { diff --git a/src/activities/house/mod.rs b/src/activities/house/mod.rs index 643e666..fbcca6d 100644 --- a/src/activities/house/mod.rs +++ b/src/activities/house/mod.rs @@ -10,7 +10,7 @@ pub struct HouseState { player: Player } -pub fn draw(state: &crate::State, _engine: &comfy::EngineContext) { +pub fn draw(state: &crate::State, _engine: &comfy::EngineContext<'_>) { //Draw Grid state.house.grid.draw(); @@ -18,6 +18,6 @@ pub fn draw(state: &crate::State, _engine: &comfy::EngineContext) { state.house.player.draw(); } -pub fn update(state: &mut crate::State, _engine: &mut comfy::EngineContext) { +pub fn update(state: &mut crate::State, _engine: &mut comfy::EngineContext<'_>) { state.house.player.update(&state.house.grid); } diff --git a/src/activities/house/player.rs b/src/activities/house/player.rs index eb60107..e7bc726 100644 --- a/src/activities/house/player.rs +++ b/src/activities/house/player.rs @@ -1,6 +1,6 @@ -use comfy::*; - use super::Grid; +use comfy::{delta, draw_circle, is_key_down, vec2, KeyCode, Vec2, RED}; +use std::collections::HashSet; #[derive(Debug)] pub struct Player { diff --git a/src/activities/overworld.rs b/src/activities/overworld/mod.rs similarity index 84% rename from src/activities/overworld.rs rename to src/activities/overworld/mod.rs index cc44c13..f8bee45 100644 --- a/src/activities/overworld.rs +++ b/src/activities/overworld/mod.rs @@ -1,6 +1,6 @@ use comfy::{ - draw_circle, draw_rect_outline, draw_sprite, main_camera_mut, texture_id, vec2, - EngineContext, IVec2, Vec2, GREEN, RED, WHITE + draw_rect_outline, draw_sprite, main_camera_mut, EngineContext, IVec2, Vec2, RED, + WHITE }; use crate::game::ZLayer; diff --git a/src/activities/overworld/worldgen.rs b/src/activities/overworld/worldgen.rs index e12bd0f..427ba72 100644 --- a/src/activities/overworld/worldgen.rs +++ b/src/activities/overworld/worldgen.rs @@ -1,3 +1,6 @@ +// TODO remove this +#![allow(dead_code)] + use crate::assets::ASSETS; use comfy::{IVec2, TextureHandle, UVec2}; use log::info; -- 2.45.2 From 8f800c1e916472b3800260c33797c6c777a1436e Mon Sep 17 00:00:00 2001 From: Dominic Date: Sat, 6 Jul 2024 22:17:10 +0200 Subject: [PATCH 17/18] fix codegen'ed lints --- build.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/build.rs b/build.rs index 5d82e68..b090f5f 100644 --- a/build.rs +++ b/build.rs @@ -31,6 +31,7 @@ impl AssetsWriter { fn new>(path: P) -> Self { let mut file = File::create(path).expect("Failed to create assets file"); writeln!(file, "// @generated").unwrap(); + writeln!(file, "#![allow(dead_code)]").unwrap(); Self { file, root: Assets::default() @@ -80,14 +81,14 @@ impl AssetsWriter { for asset_name in root.assets.keys() { writeln!( file, - "pub {indent}\t{}: comfy::TextureHandle,", + "{indent}\tpub {}: comfy::TextureHandle,", asset_name.to_snake_case() )?; } for group_name in root.groups.keys() { writeln!( file, - "pub {indent}\t{group_name}: &'static {group_name}::Assets," + "{indent}\tpub {group_name}: &'static {group_name}::Assets," )?; } writeln!(file, "{indent}}}")?; -- 2.45.2 From 0f1717675f10b7567fdc4782cff47eedb88e19e5 Mon Sep 17 00:00:00 2001 From: Dominic Date: Sat, 6 Jul 2024 22:19:25 +0200 Subject: [PATCH 18/18] move the codegen'ed allow somewhere else --- build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.rs b/build.rs index b090f5f..b218bb6 100644 --- a/build.rs +++ b/build.rs @@ -31,7 +31,6 @@ impl AssetsWriter { fn new>(path: P) -> Self { let mut file = File::create(path).expect("Failed to create assets file"); writeln!(file, "// @generated").unwrap(); - writeln!(file, "#![allow(dead_code)]").unwrap(); Self { file, root: Assets::default() @@ -77,6 +76,7 @@ impl AssetsWriter { writeln!(file, "}}")?; } + writeln!(file, "{indent}#[allow(dead_code)]")?; writeln!(file, "{indent}pub struct Assets {{")?; for asset_name in root.assets.keys() { writeln!( -- 2.45.2