141 lines
4.9 KiB
Rust
141 lines
4.9 KiB
Rust
use std::f32::consts::PI;
|
|
use bevy::prelude::*;
|
|
use heron::prelude::*;
|
|
use rand::prelude::*;
|
|
use crate::{
|
|
input::{InputState, Key, Source as InputSource},
|
|
map::GroundContact,
|
|
off_map::CanFallOffMap,
|
|
Layer,
|
|
};
|
|
|
|
#[derive(Component)]
|
|
pub struct Player {
|
|
input_source: InputSource,
|
|
rotation: f32,
|
|
}
|
|
|
|
pub fn spawn_player(
|
|
mut commands: Commands,
|
|
players: Query<&Player>,
|
|
input: Res<InputState>,
|
|
asset_server: Res<AssetServer>,
|
|
) {
|
|
let input_source = match input.keys.iter().find(|(input_source, key)|
|
|
if *key == Key::Jump {
|
|
! players.iter().any(|player| player.input_source == *input_source)
|
|
} else {
|
|
false
|
|
}
|
|
) {
|
|
Some((input_source, _)) => input_source,
|
|
None => return,
|
|
};
|
|
println!("New input_source: {:?}", input_source);
|
|
|
|
let mesh1 = asset_server.load("Mini-Game Variety Pack/Models/Characters/gltf/character_duck.gltf#Mesh0/Primitive0");
|
|
let mesh2 = asset_server.load("Mini-Game Variety Pack/Models/Characters/gltf/character_duck.gltf#Mesh0/Primitive1");
|
|
let mesh3 = asset_server.load("Mini-Game Variety Pack/Models/Characters/gltf/character_duck.gltf#Mesh0/Primitive2");
|
|
let mesh4 = asset_server.load("Mini-Game Variety Pack/Models/Characters/gltf/character_duck.gltf#Mesh1/Primitive0");
|
|
let material1 = asset_server.load("Mini-Game Variety Pack/Models/Characters/gltf/character_duck.gltf#Material0");
|
|
let material2 = asset_server.load("Mini-Game Variety Pack/Models/Characters/gltf/character_duck.gltf#Material1");
|
|
let material3 = asset_server.load("Mini-Game Variety Pack/Models/Characters/gltf/character_duck.gltf#Material2");
|
|
|
|
let mut rng = rand::thread_rng();
|
|
let transform = Transform::from_xyz(rng.gen_range(-3.0..3.0), 5.0, rng.gen_range(-3.0..3.0));
|
|
commands.spawn()
|
|
.insert(RigidBody::Dynamic)
|
|
.insert(CollisionLayers::none()
|
|
.with_group(Layer::Player)
|
|
.with_masks(&[Layer::Player, Layer::Map])
|
|
)
|
|
.insert(CollisionShape::Cone {
|
|
half_height: 0.7,
|
|
radius: 0.4,
|
|
})
|
|
.insert(PhysicMaterial {
|
|
restitution: 0.0,
|
|
density: 20.0,
|
|
friction: 1.0,
|
|
})
|
|
.insert(RotationConstraints::lock())
|
|
.insert(Velocity::default())
|
|
.insert(Player {
|
|
input_source: input_source.clone(),
|
|
rotation: 0.0,
|
|
})
|
|
.insert(CanFallOffMap)
|
|
.insert(GroundContact::default())
|
|
.insert(GlobalTransform::default())
|
|
.insert(transform)
|
|
.with_children(|children| {
|
|
children.spawn_bundle(PbrBundle {
|
|
mesh: mesh1.clone(),
|
|
material: material1.clone(),
|
|
..Default::default()
|
|
});
|
|
children.spawn_bundle(PbrBundle {
|
|
mesh: mesh2.clone(),
|
|
material: material2.clone(),
|
|
..Default::default()
|
|
});
|
|
children.spawn_bundle(PbrBundle {
|
|
mesh: mesh3.clone(),
|
|
material: material3.clone(),
|
|
..Default::default()
|
|
});
|
|
let transform = Transform::from_translation(-0.71 * Vec3::Y);
|
|
children.spawn_bundle(PbrBundle {
|
|
mesh: mesh4.clone(),
|
|
material: material1.clone(),
|
|
transform,
|
|
..Default::default()
|
|
});
|
|
});
|
|
}
|
|
|
|
pub fn input(
|
|
time: Res<Time>,
|
|
input: Res<InputState>,
|
|
mut players: Query<(&mut Velocity, &mut Player, &mut Transform, &GroundContact)>
|
|
) {
|
|
const SPEED: f32 = 4.0;
|
|
|
|
for (mut velocity, mut player, mut transform, contact) in players.iter_mut() {
|
|
let direction = input.direction_of(&player.input_source);
|
|
let x = direction.x;
|
|
let z = direction.y;
|
|
|
|
let y = if input.keys.contains(&(player.input_source.clone(), Key::Jump)) {
|
|
1.2
|
|
} else if x != 0.0 || z != 0.0 {
|
|
// walk bobbing
|
|
0.2
|
|
} else {
|
|
0.0
|
|
};
|
|
|
|
let target_velocity = SPEED * Vec3::new(x, y, z);
|
|
|
|
if contact.0 > 0 && velocity.linear.y.abs() < 0.2 {
|
|
velocity.linear = target_velocity;
|
|
}
|
|
|
|
if direction.length_squared() > 0.0 {
|
|
let target_rotation = direction.angle_between(Vec2::Y);
|
|
|
|
if (player.rotation - 2.0 * PI - target_rotation).abs() < (player.rotation - target_rotation).abs() {
|
|
player.rotation -= 2.0 * PI;
|
|
}
|
|
if (player.rotation + 2.0 * PI - target_rotation).abs() < (player.rotation - target_rotation).abs() {
|
|
player.rotation += 2.0 * PI;
|
|
}
|
|
player.rotation += 10.0 * time.delta_seconds() * (target_rotation - player.rotation);
|
|
transform.rotation = Quat::from_axis_angle(
|
|
Vec3::Y,
|
|
player.rotation
|
|
);
|
|
}
|
|
}
|
|
}
|