From 77099ab8a6615de27ab6c410056f65df404456d3 Mon Sep 17 00:00:00 2001 From: crumblingstatue Date: Sat, 8 Apr 2023 01:26:44 +0200 Subject: [PATCH] Add torches --- Cargo.lock | 146 +++++++++++++++++++++++++++++++++++- Cargo.toml | 4 + res/tiles.png | Bin 13941 -> 10232 bytes src/app.rs | 132 +++++--------------------------- src/debug.rs | 102 ++++++++++++++++++++++++- src/game.rs | 30 ++++---- src/game/player.rs | 1 + src/graphics.rs | 3 +- src/main.rs | 5 ++ src/stringfmt.rs | 22 ++++++ src/tiles.rs | 106 ++++++++++++++++++++++++++ src/tiles/tiledb_edit_ui.rs | 9 +++ tiles.dat | Bin 0 -> 76 bytes 13 files changed, 427 insertions(+), 133 deletions(-) create mode 100644 src/stringfmt.rs create mode 100644 src/tiles.rs create mode 100644 src/tiles/tiledb_edit_ui.rs create mode 100644 tiles.dat diff --git a/Cargo.lock b/Cargo.lock index 512d975..dd30eea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -29,6 +29,15 @@ dependencies = [ "version_check", ] +[[package]] +name = "aho-corasick" +version = "0.7.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +dependencies = [ + "memchr", +] + [[package]] name = "anyhow" version = "1.0.70" @@ -106,6 +115,12 @@ version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + [[package]] name = "cairo-sys-rs" version = "0.16.3" @@ -163,7 +178,7 @@ checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -205,7 +220,7 @@ source = "git+https://github.com/crumblingstatue/egui-inspect.git#5cf1f05c0f4f66 dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -225,6 +240,19 @@ version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8ecd80612937e0267909d5351770fe150004e24dab93954f69ca62eecd3f77e" +[[package]] +name = "env_logger" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + [[package]] name = "epaint" version = "0.21.0" @@ -474,6 +502,12 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + [[package]] name = "indexmap" version = "1.9.3" @@ -504,6 +538,18 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "is-terminal" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" +dependencies = [ + "hermit-abi", + "io-lifetimes", + "rustix", + "windows-sys 0.48.0", +] + [[package]] name = "js-sys" version = "0.3.61" @@ -571,13 +617,17 @@ dependencies = [ "egui", "egui-inspect", "egui-sfml", + "env_logger", "fnv", "gamedebug_core", "hecs", + "log", "num-traits", "rand", "rfd", + "rmp-serde", "s2dc", + "serde", "sfml", "sfml-xt", "worldgen", @@ -689,6 +739,12 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "paste" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" + [[package]] name = "pin-project-lite" version = "0.2.9" @@ -792,6 +848,23 @@ dependencies = [ "bitflags", ] +[[package]] +name = "regex" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + [[package]] name = "rfd" version = "0.11.3" @@ -817,6 +890,28 @@ dependencies = [ "windows", ] +[[package]] +name = "rmp" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44519172358fd6d58656c86ab8e7fbc9e1490c3e8f14d35ed78ca0dd07403c9f" +dependencies = [ + "byteorder", + "num-traits", + "paste", +] + +[[package]] +name = "rmp-serde" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5b13be192e0220b8afb7222aa5813cb62cc269ebb5cac346ca6487681d2913e" +dependencies = [ + "byteorder", + "rmp", + "serde", +] + [[package]] name = "rustix" version = "0.37.8" @@ -850,6 +945,20 @@ name = "serde" version = "1.0.159" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.159" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c614d17805b093df4b147b51339e7e44bf05ef59fba1e45d83500bcfb4d8585" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.13", +] [[package]] name = "serde_spanned" @@ -924,6 +1033,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "2.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c9da457c5285ac1f936ebd076af6dac17a61cfe7826f2076b4d015cf47bc8ec" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "system-deps" version = "6.0.4" @@ -937,6 +1057,15 @@ dependencies = [ "version-compare", ] +[[package]] +name = "termcolor" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +dependencies = [ + "winapi-util", +] + [[package]] name = "toml" version = "0.7.3" @@ -1028,7 +1157,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn", + "syn 1.0.109", "wasm-bindgen-shared", ] @@ -1062,7 +1191,7 @@ checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -1105,6 +1234,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/Cargo.toml b/Cargo.toml index 354b5bc..0f4059c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,10 @@ rand = "0.8.5" rfd = "0.11.3" sfml = "0.20.0" worldgen = "0.5.3" +rmp-serde = "1.1.1" +serde = { version = "1.0.159", features = ["derive"] } +log = "0.4.17" +env_logger = "0.10.0" [dependencies.s2dc] git = "https://github.com/crumblingstatue/s2dc.git" diff --git a/res/tiles.png b/res/tiles.png index d54a977886e5000127ea521084257b995c056733..74d44ea0743a7dd061b96d00a9127474c5b92f82 100644 GIT binary patch literal 10232 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 diff --git a/src/app.rs b/src/app.rs index 24a7d01..63053ae 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,8 +1,5 @@ -use std::fmt::{self}; - use anyhow::Context; -use egui_inspect::inspect; -use egui_sfml::{egui, SfEgui}; +use egui_sfml::SfEgui; use gamedebug_core::{imm, imm_dbg}; use sfml::{ audio::SoundSource, @@ -15,13 +12,13 @@ use sfml::{ }; use crate::{ - debug::DebugState, - game::{for_each_tile_on_screen, Biome, GameState, LightSource}, + debug::{self, DebugState}, + game::{for_each_tile_on_screen, Biome, GameState}, graphics::{self, ScreenPos, ScreenPosScalar}, input::Input, - math::{center_offset, px_per_frame_to_km_h, WorldPos, M_PER_PX, TILE_SIZE}, + math::{center_offset, TILE_SIZE}, res::Res, - world::{Tile, TilePosScalar, CHUNK_EXTENT}, + world::{TilePosScalar, CHUNK_EXTENT}, }; /// Application level state (includes game and ui state, etc.) @@ -76,6 +73,7 @@ impl App { self.input.clear_pressed(); gamedebug_core::inc_frame(); } + self.game.tile_db.try_save(); } fn do_event_handling(&mut self) { @@ -132,7 +130,7 @@ impl App { let mut on_screen_tile_ents = Vec::new(); for_each_tile_on_screen(self.game.camera_offset, self.rt.size(), |tp, _sp| { let tid = self.game.world.tile_at_mut(tp, &self.game.worldgen).mid; - if tid == Tile::EMPTY { + if !self.game.tile_db[tid].solid { return; } let tsize = TILE_SIZE as i32; @@ -186,7 +184,12 @@ impl App { wpos.x = wpos.x.saturating_add_signed(loc.x.into()); wpos.y = wpos.y.saturating_add_signed(loc.y.into()); let mouse_tpos = wpos.tile_pos(); - imm!("Mouse @ tile {}, {}", mouse_tpos.x, mouse_tpos.y); + imm!( + "Mouse @ tile {}, {} ({:?})", + mouse_tpos.x, + mouse_tpos.y, + self.game.world.tile_at_mut(mouse_tpos, &self.game.worldgen) + ); imm!( "@ chunk {}, {}", mouse_tpos.x / CHUNK_EXTENT as TilePosScalar, @@ -207,8 +210,6 @@ impl App { } else { t.bg = self.game.tile_to_place; } - } else if self.input.mid_pressed { - self.game.light_sources.push(LightSource { pos: wpos }); } if self.game.camera_offset.y > 643_000 { self.game.current_biome = Biome::Underground; @@ -274,15 +275,13 @@ impl App { self.rw.draw_with_renderstates(&spr, &rst); self.sf_egui .do_frame(|ctx| { - if self.debug.panel { - debug_panel_ui( - &mut self.debug, - &mut self.game, - ctx, - &mut self.res, - &mut self.scale, - ); - } + debug::do_debug_ui( + ctx, + &mut self.debug, + &mut self.game, + &mut self.res, + &mut self.scale, + ); }) .unwrap(); self.sf_egui.draw(&mut self.rw, None); @@ -300,94 +299,3 @@ fn viewport_center_offset(rw_size: Vector2u, rt_size: Vector2u, scale: u8) -> Sc y: y as ScreenPosScalar, } } - -fn debug_panel_ui( - debug: &mut DebugState, - mut game: &mut GameState, - ctx: &egui::Context, - res: &mut Res, - mut scale: &mut u8, -) { - egui::Window::new("Debug (F12)").show(ctx, |ui| { - if debug.freecam { - ui.label("Cam x"); - ui.add(egui::DragValue::new(&mut game.camera_offset.x)); - ui.label("Cam y"); - ui.add(egui::DragValue::new(&mut game.camera_offset.y)); - let co = game.camera_offset; - ui.label(format!( - "Cam Depth: {}", - LengthDisp(co.y as f32 - WorldPos::SURFACE as f32) - )); - ui.label(format!( - "Cam offset from center: {}", - LengthDisp(co.x as f32 - WorldPos::CENTER as f32) - )); - } else { - let tp = game.player.center_tp(); - imm_dbg!(tp); - ui.label(format!( - "Player Depth: {}", - LengthDisp(game.player.feet_y() as f32 - WorldPos::SURFACE as f32) - )); - ui.label(format!( - "Player offset from center: {}", - LengthDisp(game.player.col_en.en.pos.x as f32 - WorldPos::CENTER as f32) - )); - ui.label(format!( - "Hspeed: {} ({} km/h)", - game.player.hspeed, - px_per_frame_to_km_h(game.player.hspeed) - )); - ui.label(format!( - "Vspeed: {} ({} km/h)", - game.player.vspeed, - px_per_frame_to_km_h(game.player.vspeed) - )); - } - ui.label("Music volume"); - let mut vol = res.surf_music.volume(); - ui.add(egui::DragValue::new(&mut vol)); - res.surf_music.set_volume(vol); - ui.separator(); - egui::ScrollArea::both() - .id_source("insp_scroll") - .max_height(240.) - .max_width(340.0) - .show(ui, |ui| { - inspect! { - ui, - scale, game - } - }); - ui.separator(); - egui::ScrollArea::vertical().show(ui, |ui| { - gamedebug_core::for_each_imm(|info| match info { - gamedebug_core::Info::Msg(msg) => { - ui.label(msg); - } - gamedebug_core::Info::Rect(_, _, _, _, _) => todo!(), - }); - }); - gamedebug_core::clear_immediates(); - }); -} - -struct LengthDisp(f32); - -impl fmt::Display for LengthDisp { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let meters = self.0 * M_PER_PX; - if meters.abs() > 1000. { - let km = if meters.is_sign_negative() { - (meters / 1000.).ceil() - } else { - (meters / 1000.).floor() - }; - let m = meters % 1000.; - write!(f, "{km} km, {m} m") - } else { - write!(f, "{meters} m") - } - } -} diff --git a/src/debug.rs b/src/debug.rs index 9576ffa..ddb2c83 100644 --- a/src/debug.rs +++ b/src/debug.rs @@ -1,11 +1,20 @@ -use sfml::window::Key; +use egui_inspect::inspect; +use sfml::{audio::SoundSource, window::Key}; -use crate::input::Input; +use crate::{ + game::GameState, + input::Input, + math::{px_per_frame_to_km_h, WorldPos}, + res::Res, + stringfmt::LengthDisp, + tiles::tiledb_edit_ui::tiledb_edit_ui, +}; #[derive(Default, Debug)] pub struct DebugState { - pub panel: bool, + panel: bool, pub freecam: bool, + tiledb_edit: bool, } impl DebugState { @@ -18,3 +27,90 @@ impl DebugState { } } } + +fn debug_panel_ui( + debug: &mut DebugState, + mut game: &mut GameState, + ctx: &egui::Context, + res: &mut Res, + mut scale: &mut u8, +) { + egui::Window::new("Debug (F12)").show(ctx, |ui| { + if debug.freecam { + ui.label("Cam x"); + ui.add(egui::DragValue::new(&mut game.camera_offset.x)); + ui.label("Cam y"); + ui.add(egui::DragValue::new(&mut game.camera_offset.y)); + let co = game.camera_offset; + ui.label(format!( + "Cam Depth: {}", + LengthDisp(co.y as f32 - WorldPos::SURFACE as f32) + )); + ui.label(format!( + "Cam offset from center: {}", + LengthDisp(co.x as f32 - WorldPos::CENTER as f32) + )); + } else { + ui.label(format!( + "Player Depth: {}", + LengthDisp(game.player.feet_y() as f32 - WorldPos::SURFACE as f32) + )); + ui.label(format!( + "Player offset from center: {}", + LengthDisp(game.player.col_en.en.pos.x as f32 - WorldPos::CENTER as f32) + )); + ui.label(format!( + "Hspeed: {} ({} km/h)", + game.player.hspeed, + px_per_frame_to_km_h(game.player.hspeed) + )); + ui.label(format!( + "Vspeed: {} ({} km/h)", + game.player.vspeed, + px_per_frame_to_km_h(game.player.vspeed) + )); + } + ui.label("Music volume"); + let mut vol = res.surf_music.volume(); + ui.add(egui::DragValue::new(&mut vol)); + res.surf_music.set_volume(vol); + ui.separator(); + egui::ScrollArea::both() + .id_source("insp_scroll") + .max_height(240.) + .max_width(340.0) + .show(ui, |ui| { + inspect! { + ui, + scale, + game, + debug.tiledb_edit + } + }); + ui.separator(); + egui::ScrollArea::vertical().show(ui, |ui| { + gamedebug_core::for_each_imm(|info| match info { + gamedebug_core::Info::Msg(msg) => { + ui.label(msg); + } + gamedebug_core::Info::Rect(_, _, _, _, _) => todo!(), + }); + }); + gamedebug_core::clear_immediates(); + }); +} + +pub(crate) fn do_debug_ui( + ctx: &egui::Context, + debug: &mut DebugState, + game: &mut GameState, + res: &mut Res, + scale: &mut u8, +) { + if debug.panel { + debug_panel_ui(debug, game, ctx, res, scale); + } + if debug.tiledb_edit { + tiledb_edit_ui(ctx, &mut game.tile_db); + } +} diff --git a/src/game.rs b/src/game.rs index b1640be..1abf5c3 100644 --- a/src/game.rs +++ b/src/game.rs @@ -3,17 +3,16 @@ mod player; use derivative::Derivative; use egui_inspect::derive::Inspect; use sfml::{ - graphics::{ - Color, Rect, RectangleShape, RenderTarget, RenderTexture, Shape, Sprite, Transformable, - }, + graphics::{Color, RectangleShape, RenderTarget, RenderTexture, Shape, Sprite, Transformable}, system::{Clock, Vector2u}, SfBox, }; use crate::{ graphics::{ScreenPos, ScreenPosScalar}, - math::{wp_to_tp, WorldPos}, + math::{wp_to_tp, WorldPos, TILE_SIZE}, res::Res, + tiles::TileDb, world::{Tile, TileId, TilePos, World}, worldgen::Worldgen, }; @@ -37,11 +36,12 @@ pub struct GameState { #[opaque] pub clock: SfBox, pub light_sources: Vec, + pub tile_db: TileDb, } #[derive(Debug, Inspect)] pub struct LightSource { - pub pos: WorldPos, + pub pos: ScreenPos, } #[derive(PartialEq, Eq, Clone, Copy, Debug, Inspect)] @@ -52,20 +52,27 @@ pub enum Biome { 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); 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(Rect::new((tile.bg - 1) as i32 * 32, 0, 32, 32)); + s.set_texture_rect(self.tile_db[tile.bg].atlas_offset.to_sf_rect()); rt.draw(&s); } if tile.mid != Tile::EMPTY { - s.set_texture_rect(Rect::new((tile.mid - 1) as i32 * 32, 0, 32, 32)); + s.set_texture_rect(self.tile_db[tile.mid].atlas_offset.to_sf_rect()); + if self.tile_db[tile.mid].emits_light { + let mut pos = sp; + pos.x += (TILE_SIZE / 2) as i16; + pos.y += (TILE_SIZE / 2) as i16; + self.light_sources.push(LightSource { pos: sp }); + } rt.draw(&s); } if tile.fg != Tile::EMPTY { - s.set_texture_rect(Rect::new((tile.fg - 1) as i32 * 32, 0, 32, 32)); + s.set_texture_rect(self.tile_db[tile.fg].atlas_offset.to_sf_rect()); rt.draw(&s); } }); @@ -102,14 +109,10 @@ impl GameState { 255, )); for ls in &self.light_sources { - let (x, y) = ( - ls.pos.x as i32 - self.camera_offset.x as i32, - ls.pos.y as i32 - self.camera_offset.y as i32, - ); let mut s = Sprite::with_texture(&res.light_texture); s.set_scale((4., 4.)); s.set_origin((128., 128.)); - s.set_position((x as f32, y as f32)); + s.set_position((ls.pos.x.into(), ls.pos.y.into())); lightmap.draw(&s); } } @@ -152,6 +155,7 @@ impl Default for GameState { ambient_light: 0, clock: Clock::start(), light_sources: Vec::new(), + tile_db: TileDb::load_or_default(), } } } diff --git a/src/game/player.rs b/src/game/player.rs index 88fab45..c4ed36e 100644 --- a/src/game/player.rs +++ b/src/game/player.rs @@ -34,6 +34,7 @@ impl Player { jumps_left: 0, } } + #[allow(dead_code)] pub fn center_tp(&self) -> TilePos { TilePos { x: (self.col_en.en.pos.x / TILE_SIZE as i32) as TilePosScalar, diff --git a/src/graphics.rs b/src/graphics.rs index 5540901..78dc868 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -1,3 +1,4 @@ +use egui_inspect::derive::Inspect; use sfml::{ graphics::RenderWindow, system::Vector2f, @@ -23,7 +24,7 @@ impl ScreenRes { } // We assume this game won't be played above 32767*32767 resolution -#[derive(Default, Clone, Copy, Debug)] +#[derive(Default, Clone, Copy, Debug, Inspect)] pub struct ScreenPos { pub x: ScreenPosScalar, pub y: ScreenPosScalar, diff --git a/src/main.rs b/src/main.rs index da54089..02a0827 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,6 +5,8 @@ mod graphics; mod input; mod math; mod res; +mod stringfmt; +mod tiles; mod world; mod worldgen; @@ -18,6 +20,9 @@ fn try_main() -> anyhow::Result<()> { } fn main() { + env_logger::builder() + .filter_level(log::LevelFilter::Info) + .init(); if let Err(e) = try_main() { rfd::MessageDialog::new() .set_title("Fatal error") diff --git a/src/stringfmt.rs b/src/stringfmt.rs new file mode 100644 index 0000000..d67b5bb --- /dev/null +++ b/src/stringfmt.rs @@ -0,0 +1,22 @@ +use std::fmt; + +use crate::math::M_PER_PX; + +pub struct LengthDisp(pub f32); + +impl fmt::Display for LengthDisp { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let meters = self.0 * M_PER_PX; + if meters.abs() > 1000. { + let km = if meters.is_sign_negative() { + (meters / 1000.).ceil() + } else { + (meters / 1000.).floor() + }; + let m = meters % 1000.; + write!(f, "{km} km, {m} m") + } else { + write!(f, "{meters} m") + } + } +} diff --git a/src/tiles.rs b/src/tiles.rs new file mode 100644 index 0000000..eaeefbd --- /dev/null +++ b/src/tiles.rs @@ -0,0 +1,106 @@ +pub mod tiledb_edit_ui; + +use std::ops::Index; + +use egui_inspect::derive::Inspect; +use log::warn; +use serde::{Deserialize, Serialize}; +use sfml::graphics::IntRect; + +use crate::{math::TILE_SIZE, world::TileId}; + +#[derive(Serialize, Deserialize, Default, Debug, Inspect)] +pub struct TileDef { + pub solid: bool, + pub emits_light: bool, + pub atlas_offset: AtlasOffset, +} + +#[derive(Serialize, Deserialize, Debug, Inspect)] +pub struct TileDb { + db: Vec, +} + +impl Default for TileDb { + fn default() -> Self { + Self { + // Add empty/air tile + db: vec![EMPTY], + } + } +} + +const EMPTY: TileDef = TileDef { + solid: false, + emits_light: false, + // 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, +}; + +impl Index for TileDb { + type Output = TileDef; + + fn index(&self, index: TileId) -> &Self::Output { + self.db.get(index as usize).unwrap_or(&UNKNOWN_TILE) + } +} + +#[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 { + solid: true, + emits_light: true, + atlas_offset: UNKNOWN_ATLAS_OFF, +}; + +const PATH: &str = "tiles.dat"; + +impl TileDb { + pub fn load_or_default() -> Self { + match std::fs::read(PATH) { + Ok(data) => match rmp_serde::from_slice(&data) { + Ok(db) => db, + Err(e) => { + warn!("Failed to load tile database: {e}\nCreating default."); + Default::default() + } + }, + Err(e) => { + warn!("Failed to load tile database: {e}\nCreating default."); + Default::default() + } + } + } + pub fn try_save(&self) { + match rmp_serde::to_vec(self) { + Ok(vec) => match std::fs::write(PATH, vec) { + Ok(()) => {} + Err(e) => warn!("Failed to save tile db: {e}"), + }, + Err(e) => warn!("Failed to save tile db: {e}"), + } + } +} diff --git a/src/tiles/tiledb_edit_ui.rs b/src/tiles/tiledb_edit_ui.rs new file mode 100644 index 0000000..8ced76b --- /dev/null +++ b/src/tiles/tiledb_edit_ui.rs @@ -0,0 +1,9 @@ +use super::TileDb; + +pub fn tiledb_edit_ui(ctx: &egui::Context, tile_db: &mut TileDb) { + egui::Window::new("Tiledb editor").show(ctx, |ui| { + if ui.button("Add new default").clicked() { + tile_db.db.push(super::TileDef::default()); + } + }); +} diff --git a/tiles.dat b/tiles.dat new file mode 100644 index 0000000000000000000000000000000000000000..e0697deaf36de9f46a25666e6d6987a51d9acaa2 GIT binary patch literal 76 zcmbO@Yx1E(lg=_aFibvtXc7aMRA88V=