Skip to content

Commit 78d1f9f

Browse files
author
Carter Hollman
committed
feat: Complete camera system w/o stretch goals
1 parent 1bf2d4f commit 78d1f9f

File tree

4 files changed

+126
-0
lines changed

4 files changed

+126
-0
lines changed

game/src/camera.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod camera_plugin;

game/src/camera/camera_plugin.rs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
use bevy::{input::mouse::MouseWheel, prelude::*};
2+
3+
pub struct CameraPlugin;
4+
5+
//Component that marks our Camera's current target
6+
#[derive(Component)]
7+
pub struct CameraTarget;
8+
9+
//Component that marks our main camera
10+
#[derive(Component)]
11+
pub struct MainCamera;
12+
13+
impl Plugin for CameraPlugin{
14+
fn build(&self, app: &mut App){
15+
app.add_systems(Startup, setup_main_camera);
16+
app.add_systems(Update, (update_camera, zoom_camera).chain());
17+
}
18+
}
19+
20+
21+
//Sets up a 2d camera and attaches the MainCamera marker to it
22+
fn setup_main_camera(
23+
mut commands: Commands
24+
) {
25+
commands.spawn((
26+
Camera2dBundle::default(),
27+
MainCamera
28+
));
29+
}
30+
31+
32+
//Update camera function will have our main camera follow any entity with the CameraTarget tag
33+
fn update_camera(
34+
mut camera_query : Query<&mut Transform, (With<MainCamera>, Without<CameraTarget>)>,
35+
target_query: Query<&Transform, (With<CameraTarget>, Without<MainCamera>)>,
36+
){
37+
//getting camera from query
38+
let Ok(mut camera) = camera_query.get_single_mut() else{
39+
return;
40+
};
41+
42+
//getting target from query
43+
let Ok(target) = target_query.get_single() else{
44+
return;
45+
};
46+
47+
//Gets the x and y coordinates of our target
48+
let Vec3 {x,y,..} = target.translation;
49+
50+
//Stores the target x y with our camera z cuz our camera z not changing
51+
let direction = Vec3::new(x,y,camera.translation.z);
52+
53+
//Debug statements if we want to use them :)
54+
//info!("Camera: {:?}", camera);
55+
//info!("Target: {:?}", target);
56+
57+
//Make our camera translation match our target translation
58+
camera.translation = direction;
59+
}
60+
61+
//Camera Zooming Function, uses MouseWheel Scrolling up/down for zooming in/out
62+
fn zoom_camera(
63+
mut scroll_event : EventReader<MouseWheel>,
64+
mut camera: Query<&mut OrthographicProjection, With<MainCamera>>
65+
){
66+
67+
68+
//Zoom Sensitivity
69+
let zoom_factor = 0.1;
70+
71+
//Amount to zoom in this update cycle
72+
let mut zoom_amount = 0.0;
73+
74+
75+
//For every event read in this cycle increase the zoom amount by 1 event * sensitivity
76+
for event in scroll_event.read(){
77+
zoom_amount += -event.y * zoom_factor
78+
}
79+
80+
//If we have had any mouse scroll events in this update then apply it to the camera projection
81+
if zoom_amount != 0.0{
82+
//extracting the type of projection from camera, only ever going to be Orthographic since 2d but I don't know a better way lol
83+
for mut projection in camera.iter_mut(){
84+
projection.scale += zoom_amount;
85+
86+
//This statement makes sure that the amount of zoom is capped, can change if need be
87+
projection.scale = projection.scale.clamp(0.1,5.0);
88+
}
89+
}
90+
}

game/src/debug/debug_plugin.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
use bevy::prelude::*;
2+
use avian2d::prelude::*;
3+
use avian2d::math::*;
4+
5+
use crate::movement::plugin::*;
6+
use crate::camera::camera_plugin::*;
27

38
///This plugin provides terminal debug capabilities
49
///By adding systems, requested information will be printed to the terminal
@@ -8,6 +13,7 @@ pub struct DebugPlugin;
813
impl Plugin for DebugPlugin {
914
fn build(&self, app: &mut App) {
1015
app.add_systems(Startup, print_debug_active_message);
16+
app.add_systems(Startup, display_dudes);
1117
}
1218
}
1319

@@ -16,3 +22,27 @@ impl Plugin for DebugPlugin {
1622
fn print_debug_active_message() {
1723
info!("The debugger is active!");
1824
}
25+
26+
27+
//Displays two pixel like sprites where one is stationary, then the other that has the CameraTarget component
28+
//falls forever. Used to test camera system tracking and zooming.
29+
fn display_dudes(mut commands : Commands){
30+
commands.spawn((
31+
SpriteBundle::default(),
32+
33+
CharacterControllerBundle::new(Collider::capsule(12.5, 20.0)).with_movement(
34+
1250.0,
35+
0.92,
36+
400.0,
37+
(30.0 as Scalar).to_radians(),
38+
),
39+
Friction::ZERO.with_combine_rule(CoefficientCombine::Min),
40+
Restitution::ZERO.with_combine_rule(CoefficientCombine::Min),
41+
ColliderDensity(2.0),
42+
GravityScale(1.5),
43+
)).insert(CameraTarget);
44+
45+
commands.spawn(
46+
SpriteBundle::default()
47+
);
48+
}

game/src/main.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
mod debug;
22
mod movement;
3+
mod camera;
34

45
use avian2d::prelude::*;
56
use bevy::prelude::*;
67
use bevy_ecs_ldtk::prelude::*;
78
use debug::debug_plugin::DebugPlugin;
89
use movement::plugin::CharacterControllerPlugin;
10+
use camera::camera_plugin::CameraPlugin;
11+
912

1013
fn main() {
1114
App::new()
@@ -15,5 +18,7 @@ fn main() {
1518
.add_plugins(CharacterControllerPlugin)
1619
//user plugins
1720
.add_plugins(DebugPlugin)
21+
.add_plugins(CameraPlugin)
1822
.run();
1923
}
24+

0 commit comments

Comments
 (0)