mirror of
https://github.com/bevyengine/bevy.git
synced 2026-05-06 06:06:42 -04:00
f6b77e4e49
# Objective Split out post process effects from bevy_core_pipeline because they are not core pipelines. ## Solution @IceSentry proposed something like this, not sure if the split is exactly as he envisioned but this seems reasonable to me. The goal is to move absolutely everything possible out of bevy_core_pipelines to unblock bevy_pbr/bevy_sprite_render compilation. Future PRs may attempt to move more little bits out. ## Testing
117 lines
3.5 KiB
Rust
117 lines
3.5 KiB
Rust
//! This example showcases a 2D top-down camera with smooth player tracking.
|
|
//!
|
|
//! ## Controls
|
|
//!
|
|
//! | Key Binding | Action |
|
|
//! |:---------------------|:--------------|
|
|
//! | `W` | Move up |
|
|
//! | `S` | Move down |
|
|
//! | `A` | Move left |
|
|
//! | `D` | Move right |
|
|
|
|
use bevy::{post_process::bloom::Bloom, prelude::*};
|
|
|
|
/// Player movement speed factor.
|
|
const PLAYER_SPEED: f32 = 100.;
|
|
|
|
/// How quickly should the camera snap to the desired location.
|
|
const CAMERA_DECAY_RATE: f32 = 2.;
|
|
|
|
#[derive(Component)]
|
|
struct Player;
|
|
|
|
fn main() {
|
|
App::new()
|
|
.add_plugins(DefaultPlugins)
|
|
.add_systems(Startup, (setup_scene, setup_instructions, setup_camera))
|
|
.add_systems(Update, (move_player, update_camera).chain())
|
|
.run();
|
|
}
|
|
|
|
fn setup_scene(
|
|
mut commands: Commands,
|
|
mut meshes: ResMut<Assets<Mesh>>,
|
|
mut materials: ResMut<Assets<ColorMaterial>>,
|
|
) {
|
|
// World where we move the player
|
|
commands.spawn((
|
|
Mesh2d(meshes.add(Rectangle::new(1000., 700.))),
|
|
MeshMaterial2d(materials.add(Color::srgb(0.2, 0.2, 0.3))),
|
|
));
|
|
|
|
// Player
|
|
commands.spawn((
|
|
Player,
|
|
Mesh2d(meshes.add(Circle::new(25.))),
|
|
MeshMaterial2d(materials.add(Color::srgb(6.25, 9.4, 9.1))), // RGB values exceed 1 to achieve a bright color for the bloom effect
|
|
Transform::from_xyz(0., 0., 2.),
|
|
));
|
|
}
|
|
|
|
fn setup_instructions(mut commands: Commands) {
|
|
commands.spawn((
|
|
Text::new("Move the light with WASD.\nThe camera will smoothly track the light."),
|
|
Node {
|
|
position_type: PositionType::Absolute,
|
|
bottom: px(12),
|
|
left: px(12),
|
|
..default()
|
|
},
|
|
));
|
|
}
|
|
|
|
fn setup_camera(mut commands: Commands) {
|
|
commands.spawn((Camera2d, Bloom::NATURAL));
|
|
}
|
|
|
|
/// Update the camera position by tracking the player.
|
|
fn update_camera(
|
|
mut camera: Single<&mut Transform, (With<Camera2d>, Without<Player>)>,
|
|
player: Single<&Transform, (With<Player>, Without<Camera2d>)>,
|
|
time: Res<Time>,
|
|
) {
|
|
let Vec3 { x, y, .. } = player.translation;
|
|
let direction = Vec3::new(x, y, camera.translation.z);
|
|
|
|
// Applies a smooth effect to camera movement using stable interpolation
|
|
// between the camera position and the player position on the x and y axes.
|
|
camera
|
|
.translation
|
|
.smooth_nudge(&direction, CAMERA_DECAY_RATE, time.delta_secs());
|
|
}
|
|
|
|
/// Update the player position with keyboard inputs.
|
|
/// Note that the approach used here is for demonstration purposes only,
|
|
/// as the point of this example is to showcase the camera tracking feature.
|
|
///
|
|
/// A more robust solution for player movement can be found in `examples/movement/physics_in_fixed_timestep.rs`.
|
|
fn move_player(
|
|
mut player: Single<&mut Transform, With<Player>>,
|
|
time: Res<Time>,
|
|
kb_input: Res<ButtonInput<KeyCode>>,
|
|
) {
|
|
let mut direction = Vec2::ZERO;
|
|
|
|
if kb_input.pressed(KeyCode::KeyW) {
|
|
direction.y += 1.;
|
|
}
|
|
|
|
if kb_input.pressed(KeyCode::KeyS) {
|
|
direction.y -= 1.;
|
|
}
|
|
|
|
if kb_input.pressed(KeyCode::KeyA) {
|
|
direction.x -= 1.;
|
|
}
|
|
|
|
if kb_input.pressed(KeyCode::KeyD) {
|
|
direction.x += 1.;
|
|
}
|
|
|
|
// Progressively update the player's position over time. Normalize the
|
|
// direction vector to prevent it from exceeding a magnitude of 1 when
|
|
// moving diagonally.
|
|
let move_delta = direction.normalize_or_zero() * PLAYER_SPEED * time.delta_secs();
|
|
player.translation += move_delta.extend(0.);
|
|
}
|