This commit is contained in:
Back777space
2025-04-05 22:06:08 +02:00
parent 4dd5b14ea1
commit 2f42713a9d
7 changed files with 410 additions and 124 deletions

View File

@@ -1,11 +1,10 @@
use crate::{
GameState,
physics::{AccumulatedInput, PhysicalTranslation, PreviousPhysicalTranslation, Velocity},
};
use bevy::{
input::mouse::AccumulatedMouseMotion, pbr::NotShadowCaster, prelude::*,
render::view::RenderLayers, window::PrimaryWindow,
};
use bevy_rapier3d::prelude::*;
use crate::GameState;
#[derive(Debug, Component)]
pub struct Player;
@@ -21,24 +20,24 @@ impl Default for CameraSensitivity {
#[derive(Debug, Component)]
struct WorldModelCamera;
#[derive(Debug, Component, Default)]
pub struct PlayerInput {
movement_direction: Vec3,
}
pub fn plugin(app: &mut App) {
app.add_systems(OnEnter(GameState::Playing), (init_player, hide_cursor))
.add_systems(Update, move_camera.run_if(in_state(GameState::Playing)))
.add_systems(
RunFixedMainLoop,
handle_input
.in_set(RunFixedMainLoopSystem::BeforeFixedMainLoop)
.run_if(in_state(GameState::Playing)),
Update,
(move_camera, handle_input).run_if(in_state(GameState::Playing)),
)
.add_systems(
FixedUpdate,
apply_player_movement.run_if(in_state(GameState::Playing)),
);
}
/// Used implicitly by all entities without a `RenderLayers` component.
/// Our world model camera and all objects other than the player are on this layer.
/// The light source belongs to both layers.
// const DEFAULT_RENDER_LAYER: usize = 0;
/// Used by the view model camera and the player's arm.
/// The light source belongs to both layers.
/// used by the view model camera and the player's arm.
const STATIC_LAYER: usize = 1;
pub fn init_player(
@@ -53,12 +52,23 @@ pub fn init_player(
.spawn((
Player,
CameraSensitivity::default(),
PlayerInput::default(),
// rapier
RigidBody::Dynamic,
Collider::capsule(Vec3::new(0.0, -0.5, 0.0), Vec3::new(0.0, 0.5, 0.0), 0.5),
Velocity::zero(),
LockedAxes::ROTATION_LOCKED,
Damping {
linear_damping: 6.0,
angular_damping: 1.0,
},
Transform::from_xyz(0.0, 1.0, 0.0),
GlobalTransform::default(),
Visibility::default(),
AccumulatedInput::default(),
Velocity::default(),
PhysicalTranslation(Vec3::new(0.0, 1.0, 0.0)),
PreviousPhysicalTranslation(Vec3::new(0.0, 1.0, 0.0)),
InheritedVisibility::default(),
ViewVisibility::default(),
))
.with_children(|parent| {
parent.spawn((
@@ -68,11 +78,14 @@ pub fn init_player(
fov: 90.0_f32.to_radians(),
..default()
}),
Transform::default(),
GlobalTransform::default(),
Visibility::default(),
InheritedVisibility::default(),
ViewVisibility::default(),
));
// we use a second layer ("framebuffer") to draw the player's arm on
// there also a second camera that only views this buffer
// this makes it easy because the second camera doesn't move with the player
// camera voor pitslampke
parent.spawn((
Camera3d::default(),
Camera {
@@ -84,19 +97,29 @@ pub fn init_player(
..default()
}),
RenderLayers::layer(STATIC_LAYER),
Transform::default(),
GlobalTransform::default(),
Visibility::default(),
InheritedVisibility::default(),
ViewVisibility::default(),
));
// pitslampke
parent.spawn((
Mesh3d(arm),
MeshMaterial3d(arm_material),
Transform::from_xyz(0.2, -0.1, -0.25),
GlobalTransform::default(),
RenderLayers::layer(STATIC_LAYER),
NotShadowCaster,
Visibility::default(),
InheritedVisibility::default(),
ViewVisibility::default(),
));
});
}
fn hide_cursor(mut windows: Query<&mut Window, With<PrimaryWindow>>) {
// Query returns one window typically.
for mut window in windows.iter_mut() {
window.cursor_options.visible = false;
}
@@ -126,35 +149,56 @@ pub fn move_camera(
pub fn handle_input(
keyboard_input: Res<ButtonInput<KeyCode>>,
mut query: Query<(&Transform, &mut AccumulatedInput, &mut Velocity), With<Player>>,
mut query: Query<(&Transform, &mut PlayerInput), With<Player>>,
) {
const SPEED: f32 = 2.0;
for (transform, mut input, mut velocity) in query.iter_mut() {
let forward = transform.forward(); // Forward direction (z axis)
let right = transform.right(); // Right direction (x axis)
for (transform, mut input) in query.iter_mut() {
let forward = transform.forward();
let right = transform.right();
let mut movement_direction = Vec3::ZERO;
if keyboard_input.pressed(KeyCode::KeyW) {
input.x += forward.x;
input.z += forward.z;
movement_direction += Vec3::new(forward.x, 0.0, forward.z).normalize_or_zero();
}
if keyboard_input.pressed(KeyCode::KeyS) {
input.x -= forward.x;
input.z -= forward.z;
movement_direction -= Vec3::new(forward.x, 0.0, forward.z).normalize_or_zero();
}
if keyboard_input.pressed(KeyCode::KeyA) {
input.x -= right.x;
input.z -= right.z;
movement_direction -= Vec3::new(right.x, 0.0, right.z).normalize_or_zero();
}
if keyboard_input.pressed(KeyCode::KeyD) {
input.x += right.x;
input.z += right.z;
movement_direction += Vec3::new(right.x, 0.0, right.z).normalize_or_zero();
}
if keyboard_input.pressed(KeyCode::Space) {
input.y += 1.0;
movement_direction += Vec3::Y;
}
if keyboard_input.pressed(KeyCode::ShiftLeft) {
input.y -= 1.0;
movement_direction -= Vec3::Y;
}
velocity.0 = input.normalize_or_zero() * SPEED;
input.movement_direction = movement_direction.normalize_or_zero();
}
}
pub fn apply_player_movement(
mut player_query: Query<(&PlayerInput, &mut Velocity), With<Player>>,
) {
const SPEED: f32 = 3.0;
const JUMP_FORCE: f32 = 4.0;
for (input, mut velocity) in player_query.iter_mut() {
let horizontal_movement = Vec3::new(
input.movement_direction.x * SPEED,
0.0,
input.movement_direction.z * SPEED,
);
velocity.linvel.x = horizontal_movement.x;
velocity.linvel.z = horizontal_movement.z;
if input.movement_direction.y > 0.0 {
velocity.linvel.y = JUMP_FORCE;
} else if input.movement_direction.y < 0.0 {
velocity.linvel.y = -SPEED;
}
}
}