entevsbaer/src/player.rs

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
);
}
}
}