From bb17d22b351e57e24430f1ec2c698d664c4a000e Mon Sep 17 00:00:00 2001 From: Corentin Date: Sat, 2 Mar 2024 11:18:10 +0000 Subject: [PATCH] Add a camera system (#69) closes: #63 Reviewed-on: https://git.tipragot.fr/corentin/border-wars/pulls/69 Reviewed-by: Tipragot --- Cargo.lock | 74 ------------------- crates/border-wars/src/camera.rs | 123 +++++++++++++++++++++++++++++++ crates/border-wars/src/lib.rs | 1 + crates/border-wars/src/main.rs | 2 + 4 files changed, 126 insertions(+), 74 deletions(-) create mode 100644 crates/border-wars/src/camera.rs diff --git a/Cargo.lock b/Cargo.lock index 33c901a..6ac8535 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1317,8 +1317,6 @@ dependencies = [ "bevy", "bevy_egui", "noise", - "num", - "partial-min-max", "paste", ] @@ -3019,40 +3017,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "num" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-complex" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" -dependencies = [ - "num-traits", -] - [[package]] name = "num-derive" version = "0.3.3" @@ -3064,38 +3028,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" -dependencies = [ - "autocfg", - "num-bigint", - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.18" @@ -3353,12 +3285,6 @@ dependencies = [ "windows-targets 0.48.5", ] -[[package]] -name = "partial-min-max" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6448add382c60bbbc64f9dab41309a12ec530c05191601042f911356ac09758c" - [[package]] name = "paste" version = "1.0.14" diff --git a/crates/border-wars/src/camera.rs b/crates/border-wars/src/camera.rs new file mode 100644 index 0000000..067da21 --- /dev/null +++ b/crates/border-wars/src/camera.rs @@ -0,0 +1,123 @@ +//! This module contains the camera systems responsible for movement and +//! scaling. + +use bevy::input::mouse::{MouseScrollUnit, MouseWheel}; +use bevy::prelude::*; + +use crate::CurrentScene; + +/// The speed of camera movement. +#[derive(Resource)] +struct CameraSpeedMouvement(f32); + +/// The speed of camera scaling. +#[derive(Resource)] +struct CameraSpeedScale(f32); + +/// The minimum scale of the camera. +#[derive(Resource)] +struct MinimumScale(f32); + +/// The maximum scale of the camera. +#[derive(Resource)] +struct MaximumScale(f32); + +/// Key settings for camera movement. +#[derive(Resource)] +pub struct KeysMovementSettings { + /// Key to move the camera up. + pub up: KeyCode, + + /// Key to move the camera down. + pub down: KeyCode, + + /// Key to move the camera right. + pub right: KeyCode, + + /// Key to move the camera left. + pub left: KeyCode, +} + +/// A Bevy plugin for the camera. +/// Allows camera movement with the keyboard and scaling with the mouse. +pub struct CameraPlugin; + +impl Plugin for CameraPlugin { + fn build(&self, app: &mut App) { + app.add_systems(Startup, init_camera) + .add_systems(Startup, init_resources_for_camera) + .add_systems(Update, movement_system.run_if(in_state(CurrentScene::Game))) + .add_systems(Update, scale_system.run_if(in_state(CurrentScene::Game))); + } +} + +/// Initializes the camera. +fn init_camera(mut commands: Commands) { + commands.spawn(Camera2dBundle::default()); +} + +/// Initializes the resources related to the camera. +/// +/// - [KeysMovementSettings]: The key settings for camera movement. +/// - [CameraSpeedMouvement]: The speed of camera movement. +/// - [CameraSpeedScale]: The speed of camera scaling. +/// - [MinimumScale]: The minimum scale of the camera. +/// - [MaximumScale]: The maximum scale of the camera. +fn init_resources_for_camera(mut commands: Commands) { + commands.insert_resource(KeysMovementSettings { + up: KeyCode::Z, + down: KeyCode::S, + right: KeyCode::D, + left: KeyCode::Q, + }); + + commands.insert_resource(CameraSpeedMouvement(10.0)); + commands.insert_resource(CameraSpeedScale(0.1)); + commands.insert_resource(MinimumScale(0.1)); + commands.insert_resource(MaximumScale(10.0)); +} + +/// Moves the camera with keyboard input. +fn movement_system( + mut query: Query<&mut Transform, With>, + keys: Res>, + keys_settings: Res, + movement_speed: Res, +) { + for mut transform in query.iter_mut() { + let mut target = Vec3::ZERO; + for key in keys.get_pressed() { + match *key { + value if value == keys_settings.up => target.y += movement_speed.0, + value if value == keys_settings.down => target.y -= movement_speed.0, + value if value == keys_settings.right => target.x += movement_speed.0, + value if value == keys_settings.left => target.x -= movement_speed.0, + _ => continue, + } + } + + transform.translation += target; + } +} + +/// Scales the view with mouse input. +fn scale_system( + mut scroll_event: EventReader, + mut query: Query<&mut OrthographicProjection, With>, + min_scale: Res, + max_scale: Res, + scale_speed: Res, +) { + for event in scroll_event.read() { + for mut projection in query.iter_mut() { + if event.unit != MouseScrollUnit::Line { + return; + } + + let future_scale = event.y.mul_add(scale_speed.0, projection.scale); + if min_scale.0 < future_scale && future_scale < max_scale.0 { + projection.scale = future_scale; + } + } + } +} diff --git a/crates/border-wars/src/lib.rs b/crates/border-wars/src/lib.rs index db4c6db..a4acdb8 100644 --- a/crates/border-wars/src/lib.rs +++ b/crates/border-wars/src/lib.rs @@ -2,6 +2,7 @@ use bevy::prelude::*; +pub mod camera; pub mod map; pub mod scenes; diff --git a/crates/border-wars/src/main.rs b/crates/border-wars/src/main.rs index ef67c5e..909ac0a 100644 --- a/crates/border-wars/src/main.rs +++ b/crates/border-wars/src/main.rs @@ -1,11 +1,13 @@ //! The main entry point of the game. use bevy::prelude::*; +use border_wars::camera::CameraPlugin; use border_wars::scenes::ScenesPlugin; fn main() { App::new() .add_plugins(DefaultPlugins) .add_plugins(ScenesPlugin) + .add_plugins(CameraPlugin) .run(); }