diff --git a/Cargo.toml b/Cargo.toml index 08af584ee8..263f23d866 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3086,6 +3086,17 @@ path = "examples/dev_tools/fps_overlay.rs" doc-scrape-examples = true required-features = ["bevy_dev_tools"] +[[example]] +name = "2d_top_down_camera" +path = "examples/camera/2d_top_down_camera.rs" +doc-scrape-examples = true + +[package.metadata.example.2d_top_down_camera] +name = "2D top-down camera" +description = "A 2D top-down camera smoothly following player movements" +category = "Camera" +wasm = true + [package.metadata.example.fps_overlay] name = "FPS overlay" description = "Demonstrates FPS overlay" diff --git a/examples/README.md b/examples/README.md index c4f46cc013..1d1d995cf3 100644 --- a/examples/README.md +++ b/examples/README.md @@ -45,6 +45,7 @@ git checkout v0.4.0 - [Assets](#assets) - [Async Tasks](#async-tasks) - [Audio](#audio) + - [Camera](#camera) - [Dev tools](#dev-tools) - [Diagnostics](#diagnostics) - [ECS (Entity Component System)](#ecs-entity-component-system) @@ -240,6 +241,12 @@ Example | Description [Spatial Audio 2D](../examples/audio/spatial_audio_2d.rs) | Shows how to play spatial audio, and moving the emitter in 2D [Spatial Audio 3D](../examples/audio/spatial_audio_3d.rs) | Shows how to play spatial audio, and moving the emitter in 3D +## Camera + +Example | Description +--- | --- +[2D top-down camera](../examples/camera/2d_top_down_camera.rs) | A 2D top-down camera smoothly following player movements + ## Dev tools Example | Description diff --git a/examples/camera/2d_top_down_camera.rs b/examples/camera/2d_top_down_camera.rs new file mode 100644 index 0000000000..7321712988 --- /dev/null +++ b/examples/camera/2d_top_down_camera.rs @@ -0,0 +1,149 @@ +//! This example showcases a 2D top-down camera with smooth player tracking. +//! +//! ## Controls +//! +//! | Key Binding | Action | +//! |:---------------------|:--------------| +//! | `Z`(azerty), `W`(US) | Move forward | +//! | `S` | Move backward | +//! | `Q`(azerty), `A`(US) | Move left | +//! | `D` | Move right | + +use bevy::core_pipeline::bloom::BloomSettings; +use bevy::math::vec3; +use bevy::prelude::*; +use bevy::sprite::{MaterialMesh2dBundle, Mesh2dHandle}; + +/// Player movement speed factor. +const PLAYER_SPEED: f32 = 100.; + +/// Camera lerp factor. +const CAM_LERP_FACTOR: 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>, + mut materials: ResMut>, +) { + // World where we move the player + commands.spawn(MaterialMesh2dBundle { + mesh: Mesh2dHandle(meshes.add(Rectangle::new(1000., 700.))), + material: materials.add(Color::srgb(0.2, 0.2, 0.3)), + ..default() + }); + + // Player + commands.spawn(( + Player, + MaterialMesh2dBundle { + mesh: meshes.add(Circle::new(25.)).into(), + material: materials.add(Color::srgb(6.25, 9.4, 9.1)), // RGB values exceed 1 to achieve a bright color for the bloom effect + transform: Transform { + translation: vec3(0., 0., 2.), + ..default() + }, + ..default() + }, + )); +} + +fn setup_instructions(mut commands: Commands) { + commands.spawn( + TextBundle::from_section( + "Move the light with ZQSD or WASD.\nThe camera will smoothly track the light.", + TextStyle::default(), + ) + .with_style(Style { + position_type: PositionType::Absolute, + bottom: Val::Px(12.0), + left: Val::Px(12.0), + ..default() + }), + ); +} + +fn setup_camera(mut commands: Commands) { + commands.spawn(( + Camera2dBundle { + camera: Camera { + hdr: true, // HDR is required for the bloom effect + ..default() + }, + ..default() + }, + BloomSettings::NATURAL, + )); +} + +/// Update the camera position by tracking the player. +fn update_camera( + mut camera: Query<&mut Transform, (With, Without)>, + player: Query<&Transform, (With, Without)>, + time: Res