game: create TopDown2dCamera controller, fix warning

This commit is contained in:
SeanOMik 2024-11-15 23:45:58 -05:00 committed by SeanOMik
parent c73ba3b943
commit b78101718e
4 changed files with 110 additions and 8 deletions

View File

@ -493,7 +493,7 @@ impl ActionHandlerBuilder {
//fn actions_system(world: &mut World) -> anyhow::Result<()> {
fn actions_system(
input_btns: Res<InputButtons<KeyCode>>,
mut mouse_ev: EventReader<MouseMotion>,
mouse_ev: EventReader<MouseMotion>,
mut handler: ResMut<ActionHandler>,
) -> anyhow::Result<()> {
// clear the states of all axises each frame

View File

@ -4,4 +4,7 @@ pub use camera::*;
mod free_fly_camera;
pub use free_fly_camera::*;
mod top_down_controller;
pub use top_down_controller::*;
pub use lyra_scene::*;

View File

@ -0,0 +1,100 @@
use std::ops::DerefMut;
use glam::{EulerRot, Quat, Vec3};
use lyra_ecs::{query::{Res, View}, Component};
use lyra_math::Transform;
use lyra_reflect::Reflect;
use crate::{game::App, input::ActionHandler, plugin::Plugin, DeltaTime};
use super::{CameraProjection, ACTLBL_LOOK_LEFT_RIGHT, ACTLBL_LOOK_ROLL, ACTLBL_LOOK_UP_DOWN, ACTLBL_MOVE_FORWARD_BACKWARD, ACTLBL_MOVE_LEFT_RIGHT, ACTLBL_MOVE_UP_DOWN};
#[derive(Clone, Component, Reflect)]
pub struct TopDown2dCamera {
pub speed: f32,
/// The zoom speed of the camera, set to `None` to disable zooming.
pub zoom_speed: Option<f32>,
/// The smallest scale of the orthographic projection view.
///
/// When the scale of the projection approaches zero, the more zoomed in the camera
/// will appear.
pub max_zoom: f32,
pub min_zoom: f32,
}
impl Default for TopDown2dCamera {
fn default() -> Self {
Self {
speed: 5.0,
zoom_speed: None,
max_zoom: 0.36,
min_zoom: 1.0,
}
}
}
pub fn top_down_2d_camera_controller(delta_time: Res<DeltaTime>, handler: Res<ActionHandler>, view: View<(&mut Transform, &mut CameraProjection, &TopDown2dCamera)>) -> anyhow::Result<()> {
let delta_time = **delta_time;
for (mut transform, mut proj, controller) in view.into_iter() {
let left = transform.left();
let up = Vec3::Y;
let move_y = handler.get_axis_modifier(ACTLBL_MOVE_FORWARD_BACKWARD).unwrap_or(0.0);
let move_x = handler.get_axis_modifier(ACTLBL_MOVE_LEFT_RIGHT).unwrap_or(0.0);
let move_z = handler.get_axis_modifier(ACTLBL_MOVE_UP_DOWN);
let mut velocity = Vec3::ZERO;
velocity += move_y * up;
velocity += move_x * left;
if let (Some(zoom_speed), Some(move_z)) = (controller.zoom_speed, move_z) {
match proj.deref_mut() {
CameraProjection::Orthographic(ortho) => {
let m = move_z * zoom_speed * delta_time;
ortho.scale = (ortho.scale + m).clamp(controller.max_zoom, controller.min_zoom);
},
_ => {}
}
}
if velocity != Vec3::ZERO {
transform.translation += velocity.normalize() * controller.speed * delta_time; // TODO: speeding up
}
let motion_x = handler.get_axis_modifier(ACTLBL_LOOK_LEFT_RIGHT).unwrap_or(0.0);
let motion_y = handler.get_axis_modifier(ACTLBL_LOOK_UP_DOWN).unwrap_or(0.0);
let motion_z = handler.get_axis_modifier(ACTLBL_LOOK_ROLL).unwrap_or(0.0);
let mut camera_rot = Vec3::ZERO;
camera_rot.y -= motion_x;
camera_rot.x -= motion_y;
camera_rot.z -= motion_z;
if camera_rot != Vec3::ZERO {
let look_velocity = camera_rot * delta_time;
let (mut y, mut x, _) = transform.rotation.to_euler(EulerRot::YXZ);
x += look_velocity.x;
y += look_velocity.y;
x = x.clamp(-1.54, 1.54);
// rotation is not commutative, keep this order to avoid unintended roll
transform.rotation = Quat::from_axis_angle(Vec3::Y, y)
* Quat::from_axis_angle(Vec3::X, x);
}
}
Ok(())
}
/// A plugin that adds the top down 2d camera controller system to the world.
///
/// It is expected that there is a [`TopDown2dCamera`] in the world, if there isn't,
/// the camera would not move.
pub struct TopDown2dCameraPlugin;
impl Plugin for TopDown2dCameraPlugin {
fn setup(&mut self, app: &mut App) {
app.with_system("top_down_2d_camera_system", top_down_2d_camera_controller, &[]);
}
}

View File

@ -9,7 +9,7 @@ use lyra_engine::{
math::{self, Transform, Vec3},
render::light::directional::DirectionalLight,
scene::{
system_update_world_transforms, Camera2dBundle, CameraProjection, FreeFly3dCamera, FreeFlyCameraPlugin, OrthographicProjection, ScaleMode, WorldTransform, ACTLBL_LOOK_LEFT_RIGHT, ACTLBL_LOOK_ROLL, ACTLBL_LOOK_UP_DOWN, ACTLBL_MOVE_FORWARD_BACKWARD, ACTLBL_MOVE_LEFT_RIGHT, ACTLBL_MOVE_UP_DOWN
system_update_world_transforms, Camera2dBundle, CameraProjection, OrthographicProjection, ScaleMode, TopDown2dCamera, TopDown2dCameraPlugin, WorldTransform, ACTLBL_LOOK_LEFT_RIGHT, ACTLBL_LOOK_ROLL, ACTLBL_LOOK_UP_DOWN, ACTLBL_MOVE_FORWARD_BACKWARD, ACTLBL_MOVE_LEFT_RIGHT, ACTLBL_MOVE_UP_DOWN
},
sprite::{self, Sprite},
};
@ -90,7 +90,7 @@ async fn main() {
.with_plugin(setup_scene_plugin)
.with_plugin(action_handler_plugin)
//.with_plugin(camera_debug_plugin)
.with_plugin(FreeFlyCameraPlugin)
.with_plugin(TopDown2dCameraPlugin)
.with_system(
"system_update_world_transforms",
system_update_world_transforms,
@ -162,16 +162,15 @@ fn setup_scene_plugin(app: &mut App) {
world.spawn((
Camera2dBundle {
projection: CameraProjection::Orthographic(OrthographicProjection {
//scale_mode: ScaleMode::Width(960.0),
scale_mode: ScaleMode::Height(180.0),
//scale_mode: ScaleMode::Width(320.0),
//scale_mode: ScaleMode::Size(lyra_engine::math::Vec2::new(320.0, 180.0)),
..Default::default()
}),
..Default::default()
},
//Transform::from_xyz(200.0, 120.0, 0.0),
Transform::from_xyz(0.0, 0.0, 0.0),
FreeFly3dCamera::default(),
TopDown2dCamera {
zoom_speed: Some(0.1),
..Default::default()
}
));
}