use comfy::{IVec2, TextureHandle, UVec2}; use std::collections::HashMap; pub 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 Tile { pub textures: Vec } 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 { 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)] 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. 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 = self.chunks.get(&tile_coords)?; chunk.get_tile(local_coords) } 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) }) }) } }