diff --git a/src/level_instantiation/mod.rs b/src/level_instantiation/mod.rs index 98f5448..dc64127 100644 --- a/src/level_instantiation/mod.rs +++ b/src/level_instantiation/mod.rs @@ -18,7 +18,14 @@ pub fn map_plugin(app: &mut App) { ); } -fn spawn_level(mut commands: Commands, models: Res>, gltf_assets: Res) { + +fn spawn_level( + mut commands: Commands, + mut meshes: ResMut>, + mut materials: ResMut>, + models: Res>, + gltf_assets: Res +) { println!("LIBRARY: {:?}", gltf_assets.library); let mesh_names = [ "corner_inside", @@ -112,228 +119,188 @@ fn spawn_level(mut commands: Commands, models: Res>, gltf_assets: R // Transform::from_xyz(-500.0, 3.0, -500.0), // )); // let map = GameMap::test(); - let map = GameMap::new(100); - map.print_map(); - for ((x, z), node) in map.nodes.into_iter() { - let values = { - // corners are handled later, for now just a wall to test - let node = node.clone(); - let pos = Transform::from_xyz(2.0 * x as f32, 0.0, -2.0 * z as f32); + let maps = create_maps(3); - use Side::{Closed, Connection}; - match (node.north, node.east, node.south, node.west) { - // hallway horizontal - (Closed, Connection, Closed, Connection) => { - vec![ - (wall.clone(), pos), - ( - wall.clone(), - pos.with_rotation(Quat::from_rotation_y(180.0_f32.to_radians())), - ), - ] - } - // hallway vertical - (Connection, Closed, Connection, Closed) => { - vec![ - ( - wall.clone(), - pos.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians())), - ), - ( - wall.clone(), - pos.with_rotation(Quat::from_rotation_y(270.0_f32.to_radians())), - ), - ] - } - // dead ends - (Connection, Closed, Closed, Closed) => { - vec![ - ( - wall.clone(), - pos.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians())), - ), - ( - round_door.clone(), - pos.with_rotation(Quat::from_rotation_y(180.0_f32.to_radians())), - ), - ( - wall.clone(), - pos.with_rotation(Quat::from_rotation_y(270.0_f32.to_radians())), - ), - ] - } - (Closed, Closed, Connection, Closed) => { - vec![ - ( - wall.clone(), - pos.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians())), - ), - ( - round_door.clone(), - pos.with_rotation(Quat::from_rotation_y(0.0_f32.to_radians())), - ), - ( - wall.clone(), - pos.with_rotation(Quat::from_rotation_y(270.0_f32.to_radians())), - ), - ] - } - (Closed, Connection, Closed, Closed) => { - vec![ - (wall.clone(), pos), - ( - round_door.clone(), - pos.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians())), - ), - ( - wall.clone(), - pos.with_rotation(Quat::from_rotation_y(180.0_f32.to_radians())), - ), - ] - } - (Closed, Closed, Closed, Connection) => { - vec![ - (wall.clone(), pos), - ( - round_door.clone(), - pos.with_rotation(Quat::from_rotation_y(270.0_f32.to_radians())), - ), - ( - wall.clone(), - pos.with_rotation(Quat::from_rotation_y(180.0_f32.to_radians())), - ), - ] - } - // T hallways - (Closed, Connection, Connection, Connection) => { - vec![ - (wall.clone(), pos), - ( - round_hole.clone(), - pos.with_rotation(Quat::from_rotation_y(180.0_f32.to_radians())), - ), - ] - } - (Connection, Closed, Connection, Connection) => { - vec![ - ( - round_hole.clone(), - pos.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians())), - ), - ( - wall.clone(), - pos.with_rotation(Quat::from_rotation_y(270.0_f32.to_radians())), - ), - ] - } - (Connection, Connection, Closed, Connection) => { - vec![ - (round_hole.clone(), pos), - ( - wall.clone(), - pos.with_rotation(Quat::from_rotation_y(180.0_f32.to_radians())), - ), - ] - } - (Connection, Connection, Connection, Closed) => { - vec![ - ( - wall.clone(), - pos.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians())), - ), - ( - round_hole.clone(), - pos.with_rotation(Quat::from_rotation_y(270.0_f32.to_radians())), - ), - ] - } - // fourway - (Connection, Connection, Connection, Connection) => { - vec![ - ( - corner_inside.clone(), - pos.with_rotation(Quat::from_rotation_y(0.0_f32.to_radians())), - ), - ( - corner_inside.clone(), - pos.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians())), - ), - ( - corner_inside.clone(), - pos.with_rotation(Quat::from_rotation_y(180.0_f32.to_radians())), - ), - ( - corner_inside.clone(), - pos.with_rotation(Quat::from_rotation_y(270.0_f32.to_radians())), - ), - ] - } - // corners - (Connection, Connection, Closed, Closed) => { - vec![ - ( - corner_outside.clone(), - pos.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians())), - ), - ( - corner_inside.clone(), - pos.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians())), - ), - ] - } - (Closed, Connection, Connection, Closed) => { - vec![ - ( - corner_outside.clone(), - pos.with_rotation(Quat::from_rotation_y(0.0_f32.to_radians())), - ), - ( - corner_inside.clone(), - pos.with_rotation(Quat::from_rotation_y(0.0_f32.to_radians())), - ), - ] - } - (Closed, Closed, Connection, Connection) => { - vec![ - ( - corner_outside.clone(), - pos.with_rotation(Quat::from_rotation_y(270.0_f32.to_radians())), - ), - ( - corner_inside.clone(), - pos.with_rotation(Quat::from_rotation_y(270.0_f32.to_radians())), - ), - ] - } - (Connection, Closed, Closed, Connection) => { - vec![ - ( - corner_outside.clone(), - pos.with_rotation(Quat::from_rotation_y(180.0_f32.to_radians())), - ), - ( - corner_inside.clone(), - pos.with_rotation(Quat::from_rotation_y(180.0_f32.to_radians())), - ), - ] - } - _ => vec![], - } - }; + for map in maps { + for ((x, z), node) in map.nodes.into_iter() { + let values = { + // corners are handled later, for now just a wall to test + let node = node.clone(); + let pos = Transform::from_xyz(2.0*x as f32, 0.0, -2.0*z as f32); - for ((scene_root, colliders), pos) in values { - commands - .spawn((RigidBody::Fixed, scene_root, pos)) - .with_children(|parent| { + use Side::{Connection, Closed}; + match (node.north, node.east, node.south, node.west) { + // hallway horizontal + (Closed, Connection, Closed, Connection) => { + vec![ + (wall.clone(), pos), + (wall.clone(), pos.with_rotation(Quat::from_rotation_y(180.0_f32.to_radians()))) + ] + }, + // hallway vertical + (Connection, Closed, Connection, Closed) => { + vec![ + (wall.clone(), pos.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians()))), + (wall.clone(), pos.with_rotation(Quat::from_rotation_y(270.0_f32.to_radians()))) + ] + } + // dead ends + (Connection, Closed, Closed, Closed) => { + vec![ + (wall.clone(), pos.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians()))), + (round_door.clone(), pos.with_rotation(Quat::from_rotation_y(180.0_f32.to_radians()))), + (wall.clone(), pos.with_rotation(Quat::from_rotation_y(270.0_f32.to_radians()))) + ] + } + (Closed, Closed, Connection, Closed) => { + vec![ + (wall.clone(), pos.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians()))), + (round_door.clone(), pos.with_rotation(Quat::from_rotation_y(0.0_f32.to_radians()))), + (wall.clone(), pos.with_rotation(Quat::from_rotation_y(270.0_f32.to_radians()))) + ] + } + (Closed, Connection, Closed, Closed) => { + vec![ + (wall.clone(), pos), + (round_door.clone(), pos.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians()))), + (wall.clone(), pos.with_rotation(Quat::from_rotation_y(180.0_f32.to_radians()))) + ] + }, + (Closed, Closed, Closed, Connection) => { + vec![ + (wall.clone(), pos), + (round_door.clone(), pos.with_rotation(Quat::from_rotation_y(270.0_f32.to_radians()))), + (wall.clone(), pos.with_rotation(Quat::from_rotation_y(180.0_f32.to_radians()))) + ] + }, + // T hallways + (Closed, Connection, Connection, Connection) => { + vec![ + (wall.clone(), pos), + (round_hole.clone(), pos.with_rotation(Quat::from_rotation_y(180.0_f32.to_radians()))) + ] + }, + (Connection, Closed, Connection, Connection) => { + vec![ + (round_hole.clone(), pos.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians()))), + (wall.clone(), pos.with_rotation(Quat::from_rotation_y(270.0_f32.to_radians()))) + ] + }, + (Connection, Connection, Closed, Connection) => { + vec![ + (round_hole.clone(), pos), + (wall.clone(), pos.with_rotation(Quat::from_rotation_y(180.0_f32.to_radians()))) + ] + }, + (Connection, Connection, Connection, Closed) => { + vec![ + (wall.clone(), pos.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians()))), + (round_hole.clone(), pos.with_rotation(Quat::from_rotation_y(270.0_f32.to_radians()))) + ] + }, + // fourway + (Connection, Connection, Connection, Connection) => { + vec![ + (corner_inside.clone(), pos.with_rotation(Quat::from_rotation_y(0.0_f32.to_radians()))), + (corner_inside.clone(), pos.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians()))), + (corner_inside.clone(), pos.with_rotation(Quat::from_rotation_y(180.0_f32.to_radians()))), + (corner_inside.clone(), pos.with_rotation(Quat::from_rotation_y(270.0_f32.to_radians()))) + ] + }, + // corners + (Connection, Connection, Closed, Closed) => { + vec![ + (corner_outside.clone(), pos.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians()))), + (corner_inside.clone(), pos.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians()))), + ] + }, + (Closed, Connection, Connection, Closed) => { + vec![ + (corner_outside.clone(), pos.with_rotation(Quat::from_rotation_y(0.0_f32.to_radians()))), + (corner_inside.clone(), pos.with_rotation(Quat::from_rotation_y(0.0_f32.to_radians()))), + ] + }, + (Closed, Closed, Connection, Connection) => { + vec![ + (corner_outside.clone(), pos.with_rotation(Quat::from_rotation_y(270.0_f32.to_radians()))), + (corner_inside.clone(), pos.with_rotation(Quat::from_rotation_y(270.0_f32.to_radians()))), + ] + }, + (Connection, Closed, Closed, Connection) => { + vec![ + (corner_outside.clone(), pos.with_rotation(Quat::from_rotation_y(180.0_f32.to_radians()))), + (corner_inside.clone(), pos.with_rotation(Quat::from_rotation_y(180.0_f32.to_radians()))), + ] + } + _ => vec![] + } + }; + + for ((scene_root, colliders), pos) in values { + commands.spawn(( + RigidBody::Fixed, + scene_root, + pos, + )).with_children(|parent| { for (collider, transform) in colliders { parent.spawn((collider, transform)); } }); + } } + let (x,z) = map.end_node; + commands.spawn(( + Mesh3d(meshes.add(Cuboid::new(1.0, 20.0, 1.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), + )); } } + +fn create_maps(n: i32) -> Vec { + let mut maps = Vec::new(); + let mut initial_node = MapNode::new(); + initial_node.east = Side::Closed; + initial_node.south = Side::Closed; + initial_node.west = Side::Closed; + initial_node.north = Side::Connection; + + let pos = (0, 0); + + let map = GameMap::new(pos, initial_node.clone(), 5); + + maps.push(map); + + for _ in 0..n-1 { + let map = maps.last().unwrap(); + let mut pos = map.end_node.clone(); + + let mut next_node = MapNode::new(); + next_node.east = Side::Connection; + next_node.south = Side::Connection; + next_node.west = Side::Connection; + next_node.north = Side::Connection; + + if map.end_node.0 >= map.end_node.1 { + next_node.south = Side::Closed; + next_node.north = Side::Closed; + pos.0 += 1; + } else { + next_node.east = Side::Closed; + next_node.west = Side::Closed; + pos.1 += 1; + } + + initial_node = next_node; + let map = GameMap::new(pos, initial_node.clone(), 5); + maps.push(map); + } + + maps +} + #[derive(Clone, Copy, Debug, PartialEq, Eq)] enum Side { Empty, @@ -347,7 +314,6 @@ struct MapNode { south: Side, east: Side, west: Side, - collapsed: bool, } impl MapNode { @@ -357,97 +323,40 @@ 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, + initial_point: (i32, i32) } impl GameMap { - fn new(max_nodes: i32) -> Self { + fn new(initial_point: (i32, i32), node: MapNode, grid_size: i32) -> Self { let mut nodes = HashMap::new(); - let mut start_node = MapNode::new(); - start_node.north = Side::Connection; - start_node.south = Side::Connection; - start_node.east = Side::Connection; - start_node.west = Side::Connection; - nodes.insert((0, 0), start_node); - let mut m = GameMap { nodes, max_nodes }; + nodes.insert(initial_point, node); + let mut m = GameMap { initial_point, nodes, grid_size, end_node: initial_point}; m.generate_map(); m } - - fn test() -> Self { - let mut nodes = HashMap::new(); - - let mut wall_node0 = MapNode::new(); - wall_node0.north = Side::Connection; - wall_node0.south = Side::Closed; - wall_node0.east = Side::Closed; - wall_node0.west = Side::Closed; - nodes.insert((0, -1), wall_node0); - - let mut wall_node1 = MapNode::new(); - wall_node1.north = Side::Connection; - wall_node1.south = Side::Connection; - wall_node1.east = Side::Connection; - wall_node1.west = Side::Closed; - nodes.insert((0, 0), wall_node1); - - let mut wall_node2 = MapNode::new(); - wall_node2.north = Side::Connection; - wall_node2.south = Side::Connection; - wall_node2.east = Side::Closed; - wall_node2.west = Side::Connection; - nodes.insert((0, 1), wall_node2); - - let mut corner_node = MapNode::new(); - corner_node.south = Side::Connection; - corner_node.east = Side::Connection; - corner_node.north = Side::Closed; - corner_node.west = Side::Closed; - nodes.insert((0, 2), corner_node); - - let mut wall_node3 = MapNode::new(); - wall_node3.west = Side::Connection; - wall_node3.east = Side::Connection; - wall_node3.north = Side::Closed; - wall_node3.south = Side::Connection; - nodes.insert((1, 2), wall_node3); - - let mut wall_node4 = MapNode::new(); - wall_node4.west = Side::Connection; - wall_node4.east = Side::Connection; - wall_node4.north = Side::Connection; - wall_node4.south = Side::Closed; - nodes.insert((2, 2), wall_node4); - - let mut wall_node5 = MapNode::new(); - wall_node5.west = Side::Connection; - wall_node5.east = Side::Closed; - wall_node5.north = Side::Closed; - wall_node5.south = Side::Connection; - nodes.insert((3, 2), wall_node5); - - GameMap { - nodes, - max_nodes: 7, - } - } - fn generate_map(&mut self) { - self.create_node(&(0, 1)); // North - // self.create_node(&(0, -1)); // South - // self.create_node(&(1, 0)); // East - // self.create_node(&(-1, 0)); // West + let mut first_point = self.initial_point.clone(); + first_point.1 += 1; + self.create_node(first_point); // North } - fn choose_side(&self) -> Side { - if self.nodes.len() > self.max_nodes as usize { + fn pos_within_boundaries(&self, pos: (i32, i32)) -> bool { + pos.0 > self.grid_size + self.initial_point.0 + || pos.1 > self.grid_size + self.initial_point.1 + || pos.0 < self.initial_point.0 + || pos.1 < self.initial_point.1 + } + + fn choose_side(&self, pos: (i32, i32)) -> Side { + if self.pos_within_boundaries(pos) { Side::Closed } else { if rand::rng().random_bool(0.5) { @@ -458,9 +367,30 @@ impl GameMap { } } - fn create_node(&mut self, idx: &(i32, i32)) { - let mut nodes_to_process = vec![*idx]; - let mut nodes_created = 0; + fn ensure_connection(&self, node: &mut MapNode, (x, y): (i32, i32)) { + 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 && !self.nodes.contains_key(&(x, y + 1)) { + node.north = Side::Connection + } + else if node.south != Side::Connection && !self.nodes.contains_key(&(x, y - 1)) { + node.south = Side::Connection + } + else if node.east != Side::Connection && !self.nodes.contains_key(&(x + 1, y)) { + node.east = Side::Connection + } + else if node.west != Side::Connection && !self.nodes.contains_key(&(x - 1, y)) { + node.west = Side::Connection + } + } + } + + fn create_node(&mut self, idx: (i32, i32)) { + let mut nodes_to_process = vec![idx]; while let Some(current_idx) = nodes_to_process.pop() { if self.nodes.contains_key(¤t_idx) { @@ -470,16 +400,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 !self.pos_within_boundaries(current_idx) { + self.ensure_connection(&mut new_node, current_idx); + } if new_node.north == Side::Connection && !self.nodes.contains_key(&(x, y + 1)) { nodes_to_process.push((x, y + 1)); } @@ -494,7 +431,14 @@ impl GameMap { } self.nodes.insert(current_idx, new_node); - nodes_created += 1; + } + + let end_node = self.nodes.get_mut(&self.end_node).unwrap(); + if self.end_node.1 >= self.end_node.0 { + end_node.north = Side::Connection; + } + else if self.end_node.0 >= self.end_node.1 { + end_node.east = Side::Connection; } } @@ -529,29 +473,6 @@ fn spawn_objects( gltf_assets: Res, image_assets: Res, ) { - // let hammer = gltf_assets - // .library - // .get("meshes/library/hammer.glb") - // .unwrap(); - - // let hammer = models.get(hammer).unwrap(); - // let asset = hammer.default_scene.as_ref().unwrap(); - // // hammer - // commands - // .spawn(( - // Transform::from_xyz(0.0, 100.0, 0.0).with_scale(Vec3::splat(0.1)), - // Interact, - // RigidBody::Dynamic, - // SceneRoot(asset.clone()), - // )) - // .with_children(|parent| { - // parent - // .spawn(Collider::cuboid(0.8, 10f32, 0.8)) - // .insert(Transform::from_xyz(0.0, -5.0, 0.0)); - // parent - // .spawn(Collider::cuboid(1.0, 1.0, 4.5)) - // .insert(Transform::from_xyz(0.0, 4.2, 1.0)); - // }); // id card let card = models.get(&gltf_assets.card).unwrap(); diff --git a/src/main.rs b/src/main.rs index a8ae9c1..1641f01 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,11 +20,16 @@ fn main() { level_instantiation::map_plugin, interaction::plugin, RapierPhysicsPlugin::::default(), - RapierDebugRenderPlugin::default(), + // RapierDebugRenderPlugin::default(), player::plugin, // debugging::plugin )) .init_state::() + .insert_resource(AmbientLight { + color: Color::srgba(0.8, 0.8, 1.0, 1.0), + // brightness: 10.0, + brightness: 80.0, + }) .add_systems(OnEnter(GameState::Playing), setup) .run(); } diff --git a/src/player.rs b/src/player.rs index 4297c2c..059be77 100644 --- a/src/player.rs +++ b/src/player.rs @@ -1,8 +1,5 @@ use bevy::{ - input::mouse::AccumulatedMouseMotion, - prelude::*, - render::view::RenderLayers, - window::{PrimaryWindow, WindowResized}, + input::mouse::AccumulatedMouseMotion, pbr::VolumetricFog, prelude::*, render::view::RenderLayers, window::{PrimaryWindow, WindowResized} }; use bevy_kira_audio::{Audio, AudioControl}; use bevy_rapier3d::prelude::*; @@ -132,6 +129,14 @@ pub fn init_player( fov: 90.0_f32.to_radians(), ..default() }), + DistanceFog { + color: Color::srgba(0.12, 0.08, 0.08, 0.65), + falloff: FogFalloff::Linear { + start: 3.0, + end: 12.0, + }, + ..default() + }, )); // camera voor pitslampke @@ -158,12 +163,12 @@ pub fn init_player( Flashlight, SpotLight { intensity: 0.0, - color: Color::WHITE, - range: 4.0, - outer_angle: 30.0_f32.to_radians(), // wide cone for flashlight - inner_angle: 10.0_f32.to_radians(), // narrower inner cone - shadows_enabled: false, // (set to true for realism) - radius: 0.35, // low value for hard light + color: Color::srgba(0.9, 0.628, 0.392, 1.0), + range: 5.0, + outer_angle: 28.0_f32.to_radians(), // wide cone for flashlight + inner_angle: 12.0_f32.to_radians(), // narrower inner cone + shadows_enabled: false, // (set to true for realism) + radius: 0.35, // low value for hard light ..default() }, Transform::from_xyz(0.0, -0.15, 0.5), @@ -408,7 +413,7 @@ pub fn handle_flashlight( spotlight.intensity = if spotlight.intensity > 0.0 { 0.0 } else { - 300_000.0 + 320_000.0 }; } }