solar-sim/examples/cam_follow.rs
2025-08-14 10:00:31 +09:00

88 lines
3.0 KiB
Rust

//! Demonstrates how to have the camera follow a target object
use bevy::prelude::*;
use bevy_panorbit_camera::{PanOrbitCamera, PanOrbitCameraPlugin};
use std::f32::consts::TAU;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(PanOrbitCameraPlugin)
.add_systems(Startup, setup)
.add_systems(Update, (animate_cube, cam_follow).chain())
.run();
}
#[derive(Component)]
struct Cube;
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
// Ground
commands.spawn((
Mesh3d(meshes.add(Plane3d::default().mesh().size(0.5, 0.5))),
MeshMaterial3d(materials.add(Color::srgb(0.3, 0.5, 0.3))),
));
// Cube
commands
.spawn((
Mesh3d(meshes.add(Cuboid::new(0.1, 0.1, 0.1))),
MeshMaterial3d(materials.add(Color::srgb(0.8, 0.7, 0.6))),
Transform::from_xyz(0.0, 0.5, 0.0),
))
.insert(Cube);
// Light
commands.spawn((
PointLight {
shadows_enabled: true,
..default()
},
Transform::from_xyz(4.0, 8.0, 4.0),
));
// Camera
commands.spawn((
Transform::from_translation(Vec3::new(0.0, 0.15, 0.5)),
PanOrbitCamera {
// Panning the camera changes the focus, and so you most likely want to disable
// panning when setting the focus manually
pan_sensitivity: 0.0,
// If you want to fully control the camera's focus, set smoothness to 0 so it
// immediately snaps to that location. If you want the 'follow' to be smoothed,
// leave this at default or set it to something between 0 and 1.
pan_smoothness: 0.0,
..default()
},
));
}
/// Move the cube in a circle around the Y axis
fn animate_cube(
time: Res<Time>,
mut cube_q: Query<&mut Transform, With<Cube>>,
mut angle: Local<f32>,
) {
if let Ok(mut cube_tfm) = cube_q.single_mut() {
// Rotate 20 degrees a second, wrapping around to 0 after a full rotation
*angle += 20f32.to_radians() * time.delta_secs() % TAU;
// Convert angle to position
let pos = Vec3::new(angle.sin() * 0.15, 0.05, angle.cos() * 0.15);
cube_tfm.translation = pos;
}
}
/// Set the camera's focus to the cube's position
fn cam_follow(mut pan_orbit_q: Query<&mut PanOrbitCamera>, cube_q: Query<&Transform, With<Cube>>) {
if let Ok(mut pan_orbit) = pan_orbit_q.single_mut() {
if let Ok(cube_tfm) = cube_q.single() {
pan_orbit.target_focus = cube_tfm.translation;
// Whenever changing properties manually like this, it's necessary to force
// PanOrbitCamera to update this frame (by default it only updates when there are
// input events).
pan_orbit.force_update = true;
}
}
}