From a07ba21a5c34cbd817555e9146171f415494b58d Mon Sep 17 00:00:00 2001 From: AmadeusWM <63149896+AmadeusWM@users.noreply.github.com> Date: Sun, 6 Apr 2025 18:45:43 +0200 Subject: [PATCH] better world generation --- src/level_instantiation/mod.rs | 70 ++++++++++++++++++++++++++-------- 1 file changed, 55 insertions(+), 15 deletions(-) diff --git a/src/level_instantiation/mod.rs b/src/level_instantiation/mod.rs index 043fc81..55d2961 100644 --- a/src/level_instantiation/mod.rs +++ b/src/level_instantiation/mod.rs @@ -12,6 +12,8 @@ pub fn map_plugin(app: &mut App) { fn spawn_level( mut commands: Commands, + mut meshes: ResMut>, + mut materials: ResMut>, models: Res>, gltf_assets: Res ) { @@ -74,7 +76,7 @@ fn spawn_level( // Transform::from_xyz(-500.0, 3.0, -500.0), // )); // let map = GameMap::test(); - let map = GameMap::new(100); + let map = GameMap::new(10); map.print_map(); for ((x, z), node) in map.nodes.into_iter() { @@ -203,6 +205,14 @@ fn spawn_level( }); } } + let (x,z) = map.end_node; + commands.spawn(( + Mesh3d(meshes.add(Cuboid::new(3.0, 3.0, 3.0))), + MeshMaterial3d(materials.add(Color::srgb_u8(255, 0, 0))), + Transform::from_xyz(2.0*x as f32, 0.5, -2.0*z as f32), + RigidBody::Fixed, + Collider::cuboid(0.5, 0.5, 0.5), + )); } #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -218,7 +228,6 @@ struct MapNode { south: Side, east: Side, west: Side, - collapsed: bool, } impl MapNode { @@ -228,18 +237,18 @@ impl MapNode { south: Side::Empty, east: Side::Empty, west: Side::Empty, - collapsed: false, } } } struct GameMap { nodes: HashMap<(i32, i32), MapNode>, - max_nodes: i32 + end_node: (i32, i32), + grid_size: i32 } impl GameMap { - fn new(max_nodes: i32) -> Self { + fn new(grid_size: i32) -> Self { let mut nodes = HashMap::new(); let mut start_node = MapNode::new(); start_node.north = Side::Connection; @@ -247,7 +256,7 @@ impl GameMap { start_node.east = Side::Connection; start_node.west = Side::Connection; nodes.insert((0, 0), start_node); - let mut m = GameMap { nodes, max_nodes }; + let mut m = GameMap { nodes, grid_size, end_node: (0, 0) }; m.generate_map(); m } @@ -305,7 +314,11 @@ impl GameMap { wall_node5.south = Side::Connection; nodes.insert((3, 2), wall_node5); - GameMap { nodes, max_nodes: 7 } + GameMap { + nodes, + grid_size: 7, + end_node: (0, 0) + } } fn generate_map(&mut self) { @@ -315,17 +328,38 @@ impl GameMap { // self.create_node(&(-1, 0)); // West } - fn choose_side(&self) -> Side { - if self.nodes.len() > self.max_nodes as usize { + fn choose_side(&self, pos: (i32, i32)) -> Side { + if pos.0 > self.grid_size || pos.1 > self.grid_size || pos.0 < 0 || pos.1 < 0 { Side::Closed } else { if rand::rng().random_bool(0.5) { Side::Connection } else { Side::Closed } } } + fn ensure_connection(&self, node: &mut MapNode) { + let am_connections = (node.north == Side::Connection) as u8 + + (node.south == Side::Connection) as u8 + + (node.east == Side::Connection) as u8 + + (node.west == Side::Connection) as u8; + + if am_connections <= 2 { + if node.north != Side::Connection { + node.north = Side::Connection + } + else if node.south != Side::Connection { + node.south = Side::Connection + } + else if node.east != Side::Connection { + node.east = Side::Connection + } + else if node.west != Side::Connection { + node.west = Side::Connection + } + } + } + fn create_node(&mut self, idx: &(i32, i32)) { let mut nodes_to_process = vec![*idx]; - let mut nodes_created = 0; while let Some(current_idx) = nodes_to_process.pop() { if self.nodes.contains_key(¤t_idx) { @@ -335,16 +369,23 @@ impl GameMap { let (x, y) = current_idx; let mut new_node = MapNode::new(); + if x >= self.end_node.0 && y >= self.end_node.1 { + self.end_node = (x, y); + } + let north = self.nodes.get(&(x, y + 1)); let south = self.nodes.get(&(x, y - 1)); let east = self.nodes.get(&(x + 1, y)); let west = self.nodes.get(&(x - 1, y)); - new_node.north = north.map_or_else(|| self.choose_side(), |n| n.south); - new_node.south = south.map_or_else(|| self.choose_side(), |s| s.north); - new_node.east = east.map_or_else(|| self.choose_side(), |e| e.west); - new_node.west = west.map_or_else(|| self.choose_side(), |w| w.east); + new_node.north = north.map_or_else(|| self.choose_side(current_idx), |n| n.south); + new_node.south = south.map_or_else(|| self.choose_side(current_idx), |s| s.north); + new_node.east = east.map_or_else(|| self.choose_side(current_idx), |e| e.west); + new_node.west = west.map_or_else(|| self.choose_side(current_idx), |w| w.east); + if !(current_idx.0 > self.grid_size || current_idx.1 > self.grid_size || current_idx.0 < 0 || current_idx.1 < 0) { + self.ensure_connection(&mut new_node); + } if new_node.north == Side::Connection && !self.nodes.contains_key(&(x, y + 1)) { nodes_to_process.push((x, y + 1)); } @@ -359,7 +400,6 @@ impl GameMap { } self.nodes.insert(current_idx, new_node); - nodes_created += 1; } }