game: create TopDown2dCamera controller, fix warning
This commit is contained in:
parent
c73ba3b943
commit
b78101718e
|
@ -493,7 +493,7 @@ impl ActionHandlerBuilder {
|
||||||
//fn actions_system(world: &mut World) -> anyhow::Result<()> {
|
//fn actions_system(world: &mut World) -> anyhow::Result<()> {
|
||||||
fn actions_system(
|
fn actions_system(
|
||||||
input_btns: Res<InputButtons<KeyCode>>,
|
input_btns: Res<InputButtons<KeyCode>>,
|
||||||
mut mouse_ev: EventReader<MouseMotion>,
|
mouse_ev: EventReader<MouseMotion>,
|
||||||
mut handler: ResMut<ActionHandler>,
|
mut handler: ResMut<ActionHandler>,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
// clear the states of all axises each frame
|
// clear the states of all axises each frame
|
||||||
|
|
|
@ -4,4 +4,7 @@ pub use camera::*;
|
||||||
mod free_fly_camera;
|
mod free_fly_camera;
|
||||||
pub use free_fly_camera::*;
|
pub use free_fly_camera::*;
|
||||||
|
|
||||||
|
mod top_down_controller;
|
||||||
|
pub use top_down_controller::*;
|
||||||
|
|
||||||
pub use lyra_scene::*;
|
pub use lyra_scene::*;
|
|
@ -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, &[]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,7 +9,7 @@ use lyra_engine::{
|
||||||
math::{self, Transform, Vec3},
|
math::{self, Transform, Vec3},
|
||||||
render::light::directional::DirectionalLight,
|
render::light::directional::DirectionalLight,
|
||||||
scene::{
|
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},
|
sprite::{self, Sprite},
|
||||||
};
|
};
|
||||||
|
@ -90,7 +90,7 @@ async fn main() {
|
||||||
.with_plugin(setup_scene_plugin)
|
.with_plugin(setup_scene_plugin)
|
||||||
.with_plugin(action_handler_plugin)
|
.with_plugin(action_handler_plugin)
|
||||||
//.with_plugin(camera_debug_plugin)
|
//.with_plugin(camera_debug_plugin)
|
||||||
.with_plugin(FreeFlyCameraPlugin)
|
.with_plugin(TopDown2dCameraPlugin)
|
||||||
.with_system(
|
.with_system(
|
||||||
"system_update_world_transforms",
|
"system_update_world_transforms",
|
||||||
system_update_world_transforms,
|
system_update_world_transforms,
|
||||||
|
@ -162,16 +162,15 @@ fn setup_scene_plugin(app: &mut App) {
|
||||||
world.spawn((
|
world.spawn((
|
||||||
Camera2dBundle {
|
Camera2dBundle {
|
||||||
projection: CameraProjection::Orthographic(OrthographicProjection {
|
projection: CameraProjection::Orthographic(OrthographicProjection {
|
||||||
//scale_mode: ScaleMode::Width(960.0),
|
|
||||||
scale_mode: ScaleMode::Height(180.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()
|
||||||
}),
|
}),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
//Transform::from_xyz(200.0, 120.0, 0.0),
|
|
||||||
Transform::from_xyz(0.0, 0.0, 0.0),
|
Transform::from_xyz(0.0, 0.0, 0.0),
|
||||||
FreeFly3dCamera::default(),
|
TopDown2dCamera {
|
||||||
|
zoom_speed: Some(0.1),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue