688 lines
24 KiB
Rust
688 lines
24 KiB
Rust
use std::collections::HashMap;
|
|
|
|
use bevy::prelude::*;
|
|
use bevy_rapier3d::prelude::*;
|
|
use rand::{Rng, seq::IteratorRandom};
|
|
|
|
use crate::{
|
|
asset_loading::{GltfAssets, ImageAssets}, interaction::Interact, player::{toolbar::ItemIcon, Player, PlayerAction}, GameState
|
|
};
|
|
|
|
pub fn map_plugin(app: &mut App) {
|
|
app.add_systems(
|
|
OnEnter(GameState::Playing),
|
|
(spawn_level, spawn_objects, spawn_doors).chain(),
|
|
);
|
|
app.add_systems(Update, handle_door_pos);
|
|
}
|
|
|
|
fn spawn_level(
|
|
mut commands: Commands,
|
|
mut meshes: ResMut<Assets<Mesh>>,
|
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
|
models: Res<Assets<Gltf>>,
|
|
gltf_assets: Res<GltfAssets>,
|
|
) {
|
|
println!("LIBRARY: {:?}", gltf_assets.library);
|
|
let mesh_names = [
|
|
"corner_inside",
|
|
"corner_outside",
|
|
"wall",
|
|
"door",
|
|
"round_door",
|
|
"round_hole",
|
|
];
|
|
let shapes = mesh_names.map(|mesh_name| {
|
|
let collider: Vec<(Collider, Transform)> = match mesh_name {
|
|
"corner_inside" => vec![(
|
|
Collider::cuboid(0.2, 1.0, 0.2),
|
|
Transform::from_xyz(1.0, 1.0, 1.0)
|
|
.with_rotation(Quat::from_rotation_y(45.0_f32.to_radians())),
|
|
)],
|
|
"corner_outside" => vec![
|
|
(
|
|
Collider::cuboid(1.0, 1.0, 0.1),
|
|
Transform::from_xyz(0.0, 1.0, -1.0),
|
|
),
|
|
(
|
|
Collider::cuboid(1.0, 1.0, 0.1),
|
|
Transform::from_xyz(-1.0, 1.0, 0.0)
|
|
.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians())),
|
|
),
|
|
],
|
|
"wall" => vec![(
|
|
Collider::cuboid(1.0, 1.0, 0.1),
|
|
Transform::from_xyz(0.0, 1.0, -1.0),
|
|
)],
|
|
"door" => vec![(
|
|
Collider::cuboid(1.0, 1.0, 0.1),
|
|
Transform::from_xyz(0.0, 1.0, -1.0),
|
|
)],
|
|
"round_door" => vec![(
|
|
Collider::cuboid(1.0, 1.0, 0.1),
|
|
Transform::from_xyz(0.0, 1.0, -1.0),
|
|
)],
|
|
"round_hole" => vec![
|
|
(
|
|
Collider::cuboid(0.2, 1.0, 0.2),
|
|
Transform::from_xyz(1.0, 1.0, -1.0)
|
|
.with_rotation(Quat::from_rotation_y(45.0_f32.to_radians())),
|
|
),
|
|
(
|
|
Collider::cuboid(0.2, 1.0, 0.2),
|
|
Transform::from_xyz(-1.0, 1.0, -1.0)
|
|
.with_rotation(Quat::from_rotation_y(45.0_f32.to_radians())),
|
|
),
|
|
],
|
|
_ => vec![(
|
|
Collider::cuboid(1.0, 0.1, 1.0),
|
|
Transform::from_xyz(0.0, 0.0, 0.0),
|
|
)],
|
|
};
|
|
let path = format!("meshes/library/space_{}.glb", mesh_name);
|
|
let handle = gltf_assets
|
|
.library
|
|
.get(&path)
|
|
.expect(&format!("Couldn't find {} in library", mesh_name));
|
|
let gltf = models
|
|
.get(handle)
|
|
.expect(&format!("No model for {}", mesh_name));
|
|
|
|
let asset = gltf
|
|
.default_scene
|
|
.as_ref()
|
|
.expect(&format!("No scene in {}", mesh_name));
|
|
(SceneRoot(asset.clone()), collider)
|
|
});
|
|
let [
|
|
corner_inside,
|
|
corner_outside,
|
|
wall,
|
|
door,
|
|
round_door,
|
|
round_hole,
|
|
] = shapes.clone();
|
|
|
|
// huge floor
|
|
commands.spawn((
|
|
RigidBody::Fixed,
|
|
Collider::cuboid(1000.0, 0.1, 1000.0),
|
|
Transform::from_xyz(-500.0, 0.0, -500.0),
|
|
));
|
|
// huge roof
|
|
// commands.spawn((
|
|
// RigidBody::Fixed,
|
|
// Collider::cuboid(1000.0, 0.1, 1000.0),
|
|
// Transform::from_xyz(-500.0, 3.0, -500.0),
|
|
// ));
|
|
// let map = GameMap::test();
|
|
|
|
let levels = create_levels(3);
|
|
|
|
for level in &levels {
|
|
for ((x, z), node) in level.nodes.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);
|
|
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 ((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) = level.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),
|
|
));
|
|
}
|
|
commands.insert_resource(GameLevels { levels });
|
|
}
|
|
|
|
fn create_levels(n: i32) -> Vec<GameLevel> {
|
|
let mut maps = Vec::new();
|
|
let mut initial_node = LevelNode::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 = GameLevel::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 = LevelNode::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 = GameLevel::new(pos, initial_node.clone(), 5);
|
|
maps.push(map);
|
|
}
|
|
|
|
maps
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
|
enum Side {
|
|
Empty,
|
|
Connection,
|
|
Closed,
|
|
}
|
|
|
|
#[derive(Clone, Debug)]
|
|
struct LevelNode {
|
|
north: Side,
|
|
south: Side,
|
|
east: Side,
|
|
west: Side,
|
|
}
|
|
|
|
impl LevelNode {
|
|
fn new() -> Self {
|
|
LevelNode {
|
|
north: Side::Empty,
|
|
south: Side::Empty,
|
|
east: Side::Empty,
|
|
west: Side::Empty,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Resource)]
|
|
struct GameLevels {
|
|
pub levels: Vec<GameLevel>,
|
|
}
|
|
|
|
struct GameLevel {
|
|
nodes: HashMap<(i32, i32), LevelNode>,
|
|
end_node: (i32, i32),
|
|
grid_size: i32,
|
|
initial_point: (i32, i32),
|
|
}
|
|
|
|
impl GameLevel {
|
|
fn new(initial_point: (i32, i32), node: LevelNode, grid_size: i32) -> Self {
|
|
let mut nodes = HashMap::new();
|
|
nodes.insert(initial_point, node);
|
|
let mut m = GameLevel {
|
|
initial_point,
|
|
nodes,
|
|
grid_size,
|
|
end_node: initial_point,
|
|
};
|
|
m.generate_map();
|
|
m
|
|
}
|
|
fn generate_map(&mut self) {
|
|
let mut first_point = self.initial_point.clone();
|
|
first_point.1 += 1;
|
|
self.create_node(first_point); // North
|
|
}
|
|
|
|
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) {
|
|
Side::Connection
|
|
} else {
|
|
Side::Closed
|
|
}
|
|
}
|
|
}
|
|
|
|
fn ensure_connection(&self, node: &mut LevelNode, (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) {
|
|
continue;
|
|
}
|
|
|
|
let (x, y) = current_idx;
|
|
let mut new_node = LevelNode::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(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));
|
|
}
|
|
if new_node.south == Side::Connection && !self.nodes.contains_key(&(x, y - 1)) {
|
|
nodes_to_process.push((x, y - 1));
|
|
}
|
|
if new_node.east == Side::Connection && !self.nodes.contains_key(&(x + 1, y)) {
|
|
nodes_to_process.push((x + 1, y));
|
|
}
|
|
if new_node.west == Side::Connection && !self.nodes.contains_key(&(x - 1, y)) {
|
|
nodes_to_process.push((x - 1, y));
|
|
}
|
|
|
|
self.nodes.insert(current_idx, new_node);
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
fn print_map(&self) {
|
|
let mut min_x = 0;
|
|
let mut max_x = 0;
|
|
let mut min_y = 0;
|
|
let mut max_y = 0;
|
|
|
|
for &(x, y) in self.nodes.keys() {
|
|
min_x = min_x.min(x);
|
|
max_x = max_x.max(x);
|
|
min_y = min_y.min(y);
|
|
max_y = max_y.max(y);
|
|
}
|
|
|
|
for y in (min_y..=max_y).rev() {
|
|
for x in min_x..=max_x {
|
|
match self.nodes.get(&(x, y)) {
|
|
Some(node) => print!("[+]"),
|
|
None => print!(" "),
|
|
}
|
|
}
|
|
println!();
|
|
}
|
|
}
|
|
}
|
|
|
|
fn spawn_objects(
|
|
mut commands: Commands,
|
|
levels: Res<GameLevels>,
|
|
models: Res<Assets<Gltf>>,
|
|
gltf_assets: Res<GltfAssets>,
|
|
image_assets: Res<ImageAssets>,
|
|
) {
|
|
// id card
|
|
let card = models.get(&gltf_assets.card).unwrap();
|
|
let asset = card.default_scene.as_ref().unwrap();
|
|
|
|
for (i, level) in levels.levels.iter().enumerate() {
|
|
let begin_node = level.initial_point;
|
|
let end_node = level.end_node;
|
|
// take a random position that is not the beginning or end_node
|
|
let (x, z) = loop {
|
|
let positions = level.nodes.keys();
|
|
let random_pos = positions.choose(&mut rand::rng()).unwrap().clone();
|
|
if random_pos != begin_node && random_pos != end_node {
|
|
break random_pos;
|
|
}
|
|
};
|
|
let transform = if x <= z {
|
|
Transform::from_xyz(2.0 * x as f32, 0.5, -2.0 * z as f32)
|
|
.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians()))
|
|
} else {
|
|
Transform::from_xyz(2.0 * x as f32, 0.5, -2.0 * z as f32)
|
|
};
|
|
commands
|
|
.spawn((
|
|
transform,
|
|
Interact,
|
|
RigidBody::Dynamic,
|
|
Name::new(format!("Id Card {i}")),
|
|
Visibility::Visible,
|
|
ItemIcon::new(image_assets.id_card.clone()),
|
|
SceneRoot(asset.clone()),
|
|
))
|
|
.with_children(|parent| {
|
|
parent.spawn((
|
|
ColliderMassProperties::Mass(10.0),
|
|
Collider::cuboid(0.05, 0.05, 0.01),
|
|
Transform::from_rotation(Quat::from_euler(
|
|
EulerRot::XYZ,
|
|
-10.0f32.to_radians(), // X-axis rotation (tilt)
|
|
-5.0f32.to_radians(), // Y-axis rotation
|
|
10.0f32.to_radians(), // Z-axis rotation
|
|
)),
|
|
));
|
|
parent.spawn((
|
|
ActiveEvents::COLLISION_EVENTS,
|
|
Transform::default(),
|
|
Collider::ball(0.5), // Interaction radius
|
|
Sensor,
|
|
));
|
|
});
|
|
}
|
|
}
|
|
|
|
#[derive(Component)]
|
|
pub struct Door {
|
|
pub is_open: bool,
|
|
pub open_direction: (i32, i32),
|
|
pub position: (i32, i32)
|
|
}
|
|
|
|
fn spawn_doors(
|
|
mut commands: Commands,
|
|
levels: Res<GameLevels>,
|
|
models: Res<Assets<Gltf>>,
|
|
gltf_assets: Res<GltfAssets>,
|
|
) {
|
|
let collider: Vec<(Collider, Transform)> = vec![(
|
|
Collider::cuboid(1.0, 1.0, 0.1),
|
|
Transform::from_xyz(0.0, 1.0, -1.0),
|
|
)];
|
|
let path = format!("meshes/library/space_round_door.glb",);
|
|
let handle = gltf_assets.library.get(&path).unwrap();
|
|
let gltf = models.get(handle).unwrap();
|
|
|
|
let asset = gltf.default_scene.as_ref().unwrap();
|
|
let scene_root = SceneRoot(asset.clone());
|
|
|
|
for level in levels.levels.iter() {
|
|
let (x, z) = level.end_node;
|
|
let (direction, transform) = if x >= z {
|
|
(
|
|
(0, 1),
|
|
Transform::from_xyz(2.0 * x as f32, 0.0, -2.0 * z as f32)
|
|
.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians()))
|
|
)
|
|
} else {
|
|
(
|
|
(1, 0),
|
|
Transform::from_xyz(2.0 * x as f32, 0.0, -2.0 * z as f32)
|
|
)
|
|
};
|
|
commands.spawn((
|
|
RigidBody::Fixed,
|
|
Door {
|
|
is_open: false,
|
|
open_direction: direction,
|
|
position: (x, z)
|
|
},
|
|
transform,
|
|
scene_root.clone(),
|
|
)).with_children(|parent| {
|
|
for (collider, transform) in collider.clone() {
|
|
parent.spawn((collider, transform));
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
fn handle_door_pos(mut query: Query<(&Door, &mut Transform)>) {
|
|
for (door, mut transform) in query.iter_mut() {
|
|
if door.is_open {
|
|
transform.translation.y = 2.0
|
|
}
|
|
else {
|
|
transform.translation.y = 0.0;
|
|
}
|
|
}
|
|
}
|