entevsbaer/src/player.rs

159 lines
5.2 KiB
Rust

use std::f32::consts::PI;
use bevy::prelude::*;
use heron::prelude::*;
use crate::{
map::GroundContact,
Layer,
};
#[derive(Component)]
pub struct Player {
rotation: f32,
}
pub fn setup(
mut commands: Commands,
asset_server: Res<AssetServer>,
) {
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 transform = Transform::from_xyz(0.0, 12.0, 0.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: 8.0,
friction: 1.0,
})
.insert(RotationConstraints::lock())
.insert(Velocity::default())
.insert(Player {
rotation: 0.0,
})
.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<Input<KeyCode>>, mut players: Query<(&mut Velocity, &mut Player, &mut Transform, &GroundContact)>) {
let x;
let z;
let target_rotation;
match [KeyCode::Right, KeyCode::Left, KeyCode::Up, KeyCode::Down].map(|k| input.pressed(k)) {
[false, false, false, true] => {
z = 1.0;
x = 0.0;
target_rotation = Some(0.0);
}
[false, true, false, true] => {
z = 0.7;
x = -0.7;
target_rotation = Some(1.75 * PI);
}
[false, true, false, false] => {
z = 0.0;
x = -1.0;
target_rotation = Some(1.5 * PI);
}
[false, true, true, false] => {
z = -0.7;
x = -0.7;
target_rotation = Some(1.25 * PI);
}
[false, false, true, false] => {
z = -1.0;
x = 0.0;
target_rotation = Some(1.0 * PI);
}
[true, false, true, false] => {
z = -0.7;
x = 0.7;
target_rotation = Some(0.75 * PI);
}
[true, false, false, false] => {
z = 0.0;
x = 1.0;
target_rotation = Some(0.5 * PI);
}
[true, false, false, true] => {
z = 0.7;
x = 0.7;
target_rotation = Some(0.25 * PI);
}
_ => {
z = 0.0;
x = 0.0;
target_rotation = None;
}
}
let y = if input.pressed(KeyCode::Space) {
1.6
} else if x != 0.0 || z != 0.0 {
// walk bobbing
0.3
} else {
0.0
};
const SPEED: f32 = 3.0;
let target_velocity = SPEED * Vec3::new(x, y, z);
for (mut velocity, mut player, mut transform, contact) in players.iter_mut() {
if contact.0 > 0 && velocity.linear.y.abs() < 0.2 {
velocity.linear = target_velocity;
}
if let Some(target_rotation) = target_rotation {
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
);
}
}
}