Skip to content

Commit

Permalink
Added a custom camera to allow us to more easily zoom in.
Browse files Browse the repository at this point in the history
  • Loading branch information
StarArawn authored and StarArawn committed Apr 13, 2021
1 parent f4476e1 commit fbf6267
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 3 deletions.
4 changes: 3 additions & 1 deletion src/game/camera/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
mod input;
pub use input::camera_movement;
mod ortho;
pub use input::camera_movement;
pub use ortho::{CustomOrthographicCameraBundle, CustomOrthographicProjection};
131 changes: 131 additions & 0 deletions src/game/camera/ortho.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
use bevy::{prelude::*, render::{camera::{Camera, CameraProjection, DepthCalculation, ScalingMode, VisibleEntities, WindowOrigin}, render_graph::base}};
#[derive(Debug, Clone, Reflect)]
#[reflect(Component)]
pub struct CustomOrthographicProjection {
pub left: f32,
pub right: f32,
pub bottom: f32,
pub top: f32,
pub near: f32,
pub far: f32,
pub window_origin: WindowOrigin,
pub scaling_mode: ScalingMode,
pub scale: f32,
pub depth_calculation: DepthCalculation,
}

impl CameraProjection for CustomOrthographicProjection {
fn get_projection_matrix(&self) -> Mat4 {
Mat4::orthographic_rh(
self.left * self.scale,
self.right * self.scale,
self.bottom * self.scale,
self.top * self.scale,
self.near,
self.far,
)
}

fn update(&mut self, width: f32, height: f32) {
match (&self.scaling_mode, &self.window_origin) {
(ScalingMode::WindowSize, WindowOrigin::Center) => {
let half_width = width / 4.0;
let half_height = height / 4.0;
self.left = -half_width;
self.right = half_width;
self.top = half_height;
self.bottom = -half_height;
}
(ScalingMode::WindowSize, WindowOrigin::BottomLeft) => {
self.left = 0.0;
self.right = width;
self.top = height;
self.bottom = 0.0;
}
(ScalingMode::FixedVertical, WindowOrigin::Center) => {
let aspect_ratio = width / height;
self.left = -aspect_ratio;
self.right = aspect_ratio;
self.top = 1.0;
self.bottom = -1.0;
}
(ScalingMode::FixedVertical, WindowOrigin::BottomLeft) => {
let aspect_ratio = width / height;
self.left = 0.0;
self.right = aspect_ratio;
self.top = 1.0;
self.bottom = 0.0;
}
(ScalingMode::FixedHorizontal, WindowOrigin::Center) => {
let aspect_ratio = height / width;
self.left = -1.0;
self.right = 1.0;
self.top = aspect_ratio;
self.bottom = -aspect_ratio;
}
(ScalingMode::FixedHorizontal, WindowOrigin::BottomLeft) => {
let aspect_ratio = height / width;
self.left = 0.0;
self.right = 1.0;
self.top = aspect_ratio;
self.bottom = 0.0;
}
(ScalingMode::None, _) => {}
}
}

fn depth_calculation(&self) -> DepthCalculation {
self.depth_calculation
}
}

impl Default for CustomOrthographicProjection {
fn default() -> Self {
CustomOrthographicProjection {
left: -1.0,
right: 1.0,
bottom: -1.0,
top: 1.0,
near: 0.0,
far: 1000.0,
window_origin: WindowOrigin::Center,
scaling_mode: ScalingMode::WindowSize,
scale: 1.0,
depth_calculation: DepthCalculation::Distance,
}
}
}

/// Component bundle for camera entities with orthographic projection
///
/// Use this for 2D games, isometric games, CAD-like 3D views.
#[derive(Bundle)]
pub struct CustomOrthographicCameraBundle {
pub camera: Camera,
pub orthographic_projection: CustomOrthographicProjection,
pub visible_entities: VisibleEntities,
pub transform: Transform,
pub global_transform: GlobalTransform,
}

impl CustomOrthographicCameraBundle {
pub fn new_2d() -> Self {
// we want 0 to be "closest" and +far to be "farthest" in 2d, so we offset
// the camera's translation by far and use a right handed coordinate system
let far = 1000.0;
Self {
camera: Camera {
name: Some(base::camera::CAMERA_2D.to_string()),
..Default::default()
},
orthographic_projection: CustomOrthographicProjection {
far,
depth_calculation: DepthCalculation::ZDifference,
..Default::default()
},
visible_entities: Default::default(),
transform: Transform::from_xyz(0.0, 0.0, far - 0.1),
global_transform: Default::default(),
}
}
}
4 changes: 3 additions & 1 deletion src/game/map/spawn_map_entity.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use bevy::{prelude::*};
use bevy_tilemap::prelude::*;

use crate::game::camera::CustomOrthographicCameraBundle;

#[derive(Default, Clone)]
pub struct TilemapAtlasHandles {
pub handles: Vec<HandleUntyped>,
Expand Down Expand Up @@ -59,7 +61,7 @@ pub fn spawn_map_entity(

commands
.spawn()
.insert_bundle(OrthographicCameraBundle::new_2d());
.insert_bundle(CustomOrthographicCameraBundle::new_2d());
commands
.spawn()
.insert_bundle(tilemap_components);
Expand Down
10 changes: 9 additions & 1 deletion src/game/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use bevy::prelude::*;
use bevy::{prelude::*, render::RenderSystem};

mod camera;
mod game_state;
Expand All @@ -8,6 +8,7 @@ mod map;
mod timing;

pub use game_state::GameState;
use self::camera::CustomOrthographicProjection;

pub struct GamePlugin;

Expand All @@ -16,6 +17,7 @@ impl Plugin for GamePlugin {
app
.add_state(GameState::default())
.init_resource::<timing::Timing>()
.register_type::<CustomOrthographicProjection>()
.add_system(timing::update.system())
.add_system_set(
SystemSet::on_update(GameState::Loading)
Expand Down Expand Up @@ -46,6 +48,12 @@ impl Plugin for GamePlugin {
.label("realtime_update")
.with_system(camera::camera_movement.system())
)
.add_system_to_stage(
CoreStage::PostUpdate,
bevy::render::camera::camera_system::<CustomOrthographicProjection>
.system()
.before(RenderSystem::VisibleEntities),
)
.add_plugin(map::MapPlugin);
}
}

0 comments on commit fbf6267

Please sign in to comment.