diff --git a/game/dist/.gitignore b/game/dist/.gitignore new file mode 100644 index 00000000..a06c1e50 --- /dev/null +++ b/game/dist/.gitignore @@ -0,0 +1 @@ +!**/env/ \ No newline at end of file diff --git a/game/dist/assets/env/env_beachTile/beachTile.tsx b/game/dist/assets/env/env_beachTile/beachTile.tsx new file mode 100644 index 00000000..01ca4a6e --- /dev/null +++ b/game/dist/assets/env/env_beachTile/beachTile.tsx @@ -0,0 +1,7 @@ + + + + + + + diff --git a/game/dist/assets/env/env_beachTile/beachTileSwirly.tsx b/game/dist/assets/env/env_beachTile/beachTileSwirly.tsx new file mode 100644 index 00000000..a2ed1733 --- /dev/null +++ b/game/dist/assets/env/env_beachTile/beachTileSwirly.tsx @@ -0,0 +1,7 @@ + + + + + + + diff --git a/game/dist/assets/env/env_beachTile/env_beachTile.png b/game/dist/assets/env/env_beachTile/env_beachTile.png new file mode 100644 index 00000000..fafdd41a Binary files /dev/null and b/game/dist/assets/env/env_beachTile/env_beachTile.png differ diff --git a/game/dist/assets/env/env_beachTile/env_beachTileSwirly.png b/game/dist/assets/env/env_beachTile/env_beachTileSwirly.png new file mode 100644 index 00000000..d4563aa5 Binary files /dev/null and b/game/dist/assets/env/env_beachTile/env_beachTileSwirly.png differ diff --git a/game/dist/map_gameMap.tmx b/game/dist/map_gameMap.tmx index 9ad47e4a..aab04cf8 100644 --- a/game/dist/map_gameMap.tmx +++ b/game/dist/map_gameMap.tmx @@ -2,7 +2,7 @@ - + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, diff --git a/game/game_logic/Cargo.toml b/game/game_logic/Cargo.toml index be0d2754..01481368 100644 --- a/game/game_logic/Cargo.toml +++ b/game/game_logic/Cargo.toml @@ -25,4 +25,5 @@ thiserror = "1.0.30" approx = "0.5.1" poll-promise = { version = "0.1.0", features = ["tokio"] } tempfile = "3.3.0" -nalgebra = "0.30.1" \ No newline at end of file +nalgebra = "0.30.1" +tiled = "0.10.1" \ No newline at end of file diff --git a/game/game_logic/src/coord_convert.rs b/game/game_logic/src/coord_convert.rs new file mode 100644 index 00000000..92d4d9a4 --- /dev/null +++ b/game/game_logic/src/coord_convert.rs @@ -0,0 +1,11 @@ +use nalgebra as na; + +/// Converts from the tiled coordinate system to the game coordinate system. +pub fn tiled_to_game(vec: na::Vector2) -> na::Vector2 { + na::Vector2::new(vec.x, vec.y * -1.0) +} + +/// Converts from the game coordinate system to the tiled coordinate system. +pub fn game_to_tiled(vec: na::Vector2) -> na::Vector2 { + tiled_to_game(vec) +} \ No newline at end of file diff --git a/game/game_logic/src/lib.rs b/game/game_logic/src/lib.rs index 7744fcec..f41e176c 100644 --- a/game/game_logic/src/lib.rs +++ b/game/game_logic/src/lib.rs @@ -40,6 +40,7 @@ pub(crate) mod project_constants; pub(crate) mod rendering; pub(crate) mod scenes; pub(crate) mod model; +pub(crate) mod coord_convert; /// This is the game logic entrypoint. Despite being async, /// this is expected to block the main thread for rendering and stuff. diff --git a/game/game_logic/src/rendering/utilities/map_render.rs b/game/game_logic/src/rendering/utilities/map_render.rs new file mode 100644 index 00000000..a94e79e3 --- /dev/null +++ b/game/game_logic/src/rendering/utilities/map_render.rs @@ -0,0 +1,96 @@ +use std::{collections::HashMap, sync::Arc}; + +use crate::asset_manager::InternalData; +use nalgebra as na; +use tiled::{Loader, ResourceCache, ResourcePath, ResourcePathBuf, Tileset}; + +/// Possible errors generated by the map loading process +#[derive(Debug, thiserror::Error)] +pub enum MapRenderError { + #[error("Could not load embedded asset: {0}")] + AssetNotFound(String), + #[error(transparent)] + TiledError(#[from] tiled::Error), +} + +#[derive(Debug)] +struct ProgramDataTileCache { + tilesets: HashMap>, + internal_loader: Loader, +} + +impl ProgramDataTileCache { + fn new() -> Self { + Self { + tilesets: HashMap::new(), + internal_loader: Loader::new(), + } + } +} + +impl ResourceCache for ProgramDataTileCache { + /// Load the tileset. First attempts to pull from an in-RAM cache, otherwise attempts to load from disk. + fn get_tileset(&self, path: impl AsRef) -> Option> { + let possibly_cached_tileset = self.tilesets.get(path.as_ref()).map(Clone::clone); + if let Some(tileset) = possibly_cached_tileset { + return Some(tileset); + } else { + // Pull the TSX from storage and parse it + InternalData::get(path.as_ref().to_str().unwrap()).map(|file| { + let data = file.data.into_owned(); + Arc::new( + self.internal_loader + .load_tsx_tileset_from(data.as_slice(), path) + .unwrap(), + ) + }) + + // .ok_or(MapRenderError::AssetNotFound(path.to_string()))? + // .data + // .into_owned(); + } + } + + fn get_or_try_insert_tileset_with( + &mut self, + path: ResourcePathBuf, + f: F, + ) -> Result, E> + where + F: FnOnce() -> Result, + { + Ok(match self.tilesets.entry(path) { + std::collections::hash_map::Entry::Occupied(o) => o.into_mut(), + std::collections::hash_map::Entry::Vacant(v) => v.insert(Arc::new(f()?)), + } + .clone()) + } +} + +#[derive(Debug)] +pub struct MapRenderer {} + +impl MapRenderer { + /// Construct a new MapRenderer. + pub fn new(tmx_path: &str) -> Result { + // Pull the TMX from storage + let data = InternalData::get(tmx_path) + .ok_or(MapRenderError::AssetNotFound(tmx_path.to_string()))? + .data + .into_owned(); + + // Attempt to parse the TMX file + let mut loader = Loader::with_cache(ProgramDataTileCache::new()); + let map = loader.load_tmx_map_from(data.as_slice(), tmx_path)?; + + Ok(Self {}) + } + + pub fn sample_friction_at(&self, position: na::Vector2) -> f32 { + todo!() + } + + pub fn sample_temperature_at(&self, position: na::Vector2) -> f32 { + todo!() + } +} diff --git a/game/game_logic/src/rendering/utilities/mod.rs b/game/game_logic/src/rendering/utilities/mod.rs index 09d38ecf..524ae38e 100644 --- a/game/game_logic/src/rendering/utilities/mod.rs +++ b/game/game_logic/src/rendering/utilities/mod.rs @@ -1 +1,2 @@ -pub mod anim_texture; \ No newline at end of file +pub mod anim_texture; +pub mod map_render; \ No newline at end of file diff --git a/game/game_logic/src/scenes/mod.rs b/game/game_logic/src/scenes/mod.rs index 940ccafd..98924aba 100644 --- a/game/game_logic/src/scenes/mod.rs +++ b/game/game_logic/src/scenes/mod.rs @@ -53,8 +53,8 @@ impl SceneRenderDelegate { constants: &ProjectConstants, ) { // For now, we will just render the game scene - self.scene_playable - .render_frame(raylib, rl_thread, &discord, global_resources, constants) + self.scene_test_fox + .render_frame(raylib, rl_thread, &discord, global_resources) .await; } } diff --git a/game/game_logic/src/scenes/test_fox.rs b/game/game_logic/src/scenes/test_fox.rs index 526dc57e..29911212 100644 --- a/game/game_logic/src/scenes/test_fox.rs +++ b/game/game_logic/src/scenes/test_fox.rs @@ -6,12 +6,13 @@ use nalgebra as na; use crate::{ discord::DiscordChannel, global_resource_package::GlobalResources, - rendering::utilities::anim_texture::AnimatedTexture, + rendering::utilities::{anim_texture::AnimatedTexture, map_render::MapRenderer}, }; #[derive(Debug)] pub struct TestFoxScene { fox_animation: AnimatedTexture, + world_map: MapRenderer } impl TestFoxScene { @@ -20,11 +21,14 @@ impl TestFoxScene { // Load the fox texture let fox = AnimatedTexture::new(raylib_handle, thread, "chr", "testFox").unwrap(); - Self { fox_animation: fox } + // Load the map + let map_renderer = MapRenderer::new("map_gameMap.tmx").unwrap(); + + Self { fox_animation: fox, world_map: map_renderer } } /// Handler for each frame - pub fn render_frame( + pub async fn render_frame( &mut self, raylib: &mut RaylibHandle, rl_thread: &RaylibThread,