can rotate view via TAB

This commit is contained in:
2025-03-19 21:03:06 +01:00
parent 7951d613c4
commit 3f4ffeb489
4 changed files with 73 additions and 25 deletions

View File

@@ -1,7 +1,7 @@
use avian3d::prelude::*;
use bevy::prelude::*;
use crate::physics_layers::GameLayer;
use crate::{controls::Controls, physics_layers::GameLayer, player::PlayerMovement};
#[derive(Component, Reflect, Debug)]
pub struct CameraTarget;
@@ -9,38 +9,59 @@ pub struct CameraTarget;
#[derive(Component, Reflect, Debug)]
pub struct CameraArmRotation;
#[derive(Component, Reflect, Debug)]
#[reflect(Component)]
pub struct CameraRotation(pub f32);
#[derive(Resource, Reflect, Debug, Default)]
#[reflect(Resource)]
pub struct CameraState {
pub cutscene: bool,
}
#[derive(Component, Reflect, Debug)]
pub struct MainCamera {
arm: Vec3,
dir: Dir3,
distance: f32,
}
impl MainCamera {
fn new(arm: Vec3) -> Self {
Self { arm }
let (dir, distance) = Dir3::new_and_length(arm).expect("invalid arm length");
Self { dir, distance }
}
}
pub fn plugin(app: &mut App) {
app.register_type::<CameraRotation>();
app.register_type::<CameraState>();
app.init_resource::<CameraState>();
app.add_systems(Startup, startup);
app.add_systems(Update, update);
app.add_systems(Update, (update, rotate_view));
}
fn startup(mut commands: Commands) {
commands.spawn((
Camera3d::default(),
MainCamera::new(Vec3::new(0., 1., -12.)),
CameraRotation(0.),
));
}
fn update(
mut cam: Query<
(&MainCamera, &mut Transform),
(&MainCamera, &mut Transform, &CameraRotation),
(Without<CameraTarget>, Without<CameraArmRotation>),
>,
target: Query<&GlobalTransform, (With<CameraTarget>, Without<CameraArmRotation>)>,
arm_rotation: Query<&Transform, With<CameraArmRotation>>,
spatial_query: SpatialQuery,
cam_state: Res<CameraState>,
) {
if cam_state.cutscene {
return;
}
let Ok(target) = target.get_single().map(|t| t.translation()) else {
return;
};
@@ -49,20 +70,13 @@ fn update(
return;
};
let Ok((camera, mut cam_transform)) = cam.get_single_mut() else {
let Ok((camera, mut cam_transform, cam_rotation)) = cam.get_single_mut() else {
return;
};
let target_transform = Transform::from_translation(target)
* Transform::from_rotation(rotation.rotation)
* Transform::from_translation(camera.arm);
let direction = rotation.rotation * Quat::from_rotation_y(cam_rotation.0) * camera.dir;
let ideal_cam_pos = target_transform.translation;
let max_distance = camera.arm.length();
let Ok(direction) = Dir3::new(ideal_cam_pos - target) else {
return;
};
let max_distance = camera.distance;
let filter = SpatialQueryFilter::from_mask(LayerMask(GameLayer::Level.to_bits()));
let cam_pos = if let Some(first_hit) =
@@ -70,8 +84,29 @@ fn update(
{
target + (direction * first_hit.distance)
} else {
ideal_cam_pos
target + (direction * camera.distance)
};
*cam_transform = Transform::from_translation(cam_pos).looking_at(target, Vec3::Y);
}
fn rotate_view(
mut controls: ResMut<Controls>,
mut cam: Query<&mut CameraRotation>,
movement: Res<PlayerMovement>,
) {
let Ok(mut cam) = cam.get_single_mut() else {
return;
};
if !controls.keyboard_state.view_mode {
if movement.any_direction {
cam.0 = 0.;
}
return;
}
cam.0 += controls.keyboard_state.look_dir.x * -0.001;
controls.keyboard_state.look_dir = Vec2::ZERO;
}