basic moving camera
This commit is contained in:
parent
d5bcbb5339
commit
2ce1d6e809
5 changed files with 4050 additions and 1 deletions
3845
Cargo.lock
generated
3845
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -4,3 +4,4 @@ version = "0.1.0"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
bevy = "0.4"
|
||||||
|
|
152
src/camera.rs
Normal file
152
src/camera.rs
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
use bevy::{input::mouse::MouseMotion, math::clamp, prelude::*};
|
||||||
|
|
||||||
|
pub struct FlyCamera {
|
||||||
|
/// The speed the FlyCamera moves at. Defaults to `1.0`
|
||||||
|
pub speed: f32,
|
||||||
|
/// The sensitivity of the FlyCamera's motion based on mouse movement. Defaults to `3.0`
|
||||||
|
pub sensitivity: f32,
|
||||||
|
/// The amount of deceleration to apply to the camera's motion. Defaults to `1.0`
|
||||||
|
pub friction: f32,
|
||||||
|
/// The current pitch of the FlyCamera in degrees. This value is always up-to-date, enforced by [FlyCameraPlugin](struct.FlyCameraPlugin.html)
|
||||||
|
pub pitch: f32,
|
||||||
|
/// The current pitch of the FlyCamera in degrees. This value is always up-to-date, enforced by [FlyCameraPlugin](struct.FlyCameraPlugin.html)
|
||||||
|
pub yaw: f32,
|
||||||
|
/// The current velocity of the FlyCamera. This value is always up-to-date, enforced by [FlyCameraPlugin](struct.FlyCameraPlugin.html)
|
||||||
|
pub velocity: Vec3,
|
||||||
|
}
|
||||||
|
impl Default for FlyCamera {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
speed: 1.5,
|
||||||
|
sensitivity: 3.0,
|
||||||
|
friction: 1.0,
|
||||||
|
pitch: 0.0,
|
||||||
|
yaw: 0.0,
|
||||||
|
velocity: Vec3::zero(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn forward_vector(rotation: &Quat) -> Vec3 {
|
||||||
|
rotation.mul_vec3(Vec3::unit_z()).normalize()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn forward_walk_vector(rotation: &Quat) -> Vec3 {
|
||||||
|
let f = forward_vector(rotation);
|
||||||
|
let f_flattened = Vec3::new(f.x, 0.0, f.z).normalize();
|
||||||
|
f_flattened
|
||||||
|
}
|
||||||
|
|
||||||
|
fn strafe_vector(rotation: &Quat) -> Vec3 {
|
||||||
|
// Rotate it 90 degrees to get the strafe direction
|
||||||
|
Quat::from_rotation_y(90.0f32.to_radians())
|
||||||
|
.mul_vec3(forward_walk_vector(rotation))
|
||||||
|
.normalize()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn movement_axis(
|
||||||
|
input: &Res<Input<KeyCode>>,
|
||||||
|
plus: KeyCode,
|
||||||
|
minus: KeyCode,
|
||||||
|
) -> f32 {
|
||||||
|
let mut axis = 0.0;
|
||||||
|
if input.pressed(plus) {
|
||||||
|
axis += 1.0;
|
||||||
|
}
|
||||||
|
if input.pressed(minus) {
|
||||||
|
axis -= 1.0;
|
||||||
|
}
|
||||||
|
axis
|
||||||
|
}
|
||||||
|
|
||||||
|
fn camera_movement_system(
|
||||||
|
time: Res<Time>,
|
||||||
|
keyboard_input: Res<Input<KeyCode>>,
|
||||||
|
mut query: Query<(&mut FlyCamera, &mut Transform)>,
|
||||||
|
) {
|
||||||
|
for (mut options, mut transform) in query.iter_mut() {
|
||||||
|
let (axis_h, axis_v, axis_float) = (movement_axis(&keyboard_input, KeyCode::D, KeyCode::A),
|
||||||
|
movement_axis(
|
||||||
|
&keyboard_input,
|
||||||
|
KeyCode::S,
|
||||||
|
KeyCode::W,
|
||||||
|
),
|
||||||
|
movement_axis(&keyboard_input, KeyCode::Space, KeyCode::LControl),
|
||||||
|
);
|
||||||
|
|
||||||
|
let rotation = transform.rotation;
|
||||||
|
let accel: Vec3 = (strafe_vector(&rotation) * axis_h)
|
||||||
|
+ (forward_walk_vector(&rotation) * axis_v)
|
||||||
|
+ (Vec3::unit_y() * axis_float);
|
||||||
|
let accel: Vec3 = if accel.length() != 0.0 {
|
||||||
|
accel.normalize() * options.speed
|
||||||
|
} else {
|
||||||
|
Vec3::zero()
|
||||||
|
};
|
||||||
|
|
||||||
|
let friction: Vec3 = if options.velocity.length() != 0.0 {
|
||||||
|
options.velocity.normalize() * -1.0 * options.friction
|
||||||
|
} else {
|
||||||
|
Vec3::zero()
|
||||||
|
};
|
||||||
|
|
||||||
|
options.velocity += accel * time.delta_seconds();
|
||||||
|
|
||||||
|
let delta_friction = friction * time.delta_seconds();
|
||||||
|
|
||||||
|
options.velocity = if (options.velocity + delta_friction).signum()
|
||||||
|
!= options.velocity.signum()
|
||||||
|
{
|
||||||
|
Vec3::zero()
|
||||||
|
} else {
|
||||||
|
options.velocity + delta_friction
|
||||||
|
};
|
||||||
|
|
||||||
|
transform.translation += options.velocity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct State {
|
||||||
|
mouse_motion_event_reader: EventReader<MouseMotion>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mouse_motion_system(
|
||||||
|
time: Res<Time>,
|
||||||
|
mut state: ResMut<State>,
|
||||||
|
mouse_motion_events: Res<Events<MouseMotion>>,
|
||||||
|
mut query: Query<(&mut FlyCamera, &mut Transform)>,
|
||||||
|
) {
|
||||||
|
let mut delta: Vec2 = Vec2::zero();
|
||||||
|
for event in state.mouse_motion_event_reader.iter(&mouse_motion_events) {
|
||||||
|
delta += event.delta;
|
||||||
|
}
|
||||||
|
if delta.is_nan() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (mut options, mut transform) in query.iter_mut() {
|
||||||
|
options.yaw -= delta.x * options.sensitivity * time.delta_seconds();
|
||||||
|
options.pitch += delta.y * options.sensitivity * time.delta_seconds();
|
||||||
|
|
||||||
|
options.pitch = clamp(options.pitch, -89.9, 89.9);
|
||||||
|
// println!("pitch: {}, yaw: {}", options.pitch, options.yaw);
|
||||||
|
|
||||||
|
let yaw_radians = options.yaw.to_radians();
|
||||||
|
let pitch_radians = options.pitch.to_radians();
|
||||||
|
|
||||||
|
transform.rotation = Quat::from_axis_angle(Vec3::unit_y(), yaw_radians)
|
||||||
|
* Quat::from_axis_angle(-Vec3::unit_x(), pitch_radians);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct FlyCameraPlugin;
|
||||||
|
|
||||||
|
impl Plugin for FlyCameraPlugin {
|
||||||
|
fn build(&self, app: &mut AppBuilder) {
|
||||||
|
app
|
||||||
|
.init_resource::<State>()
|
||||||
|
.add_system(camera_movement_system.system())
|
||||||
|
.add_system(mouse_motion_system.system());
|
||||||
|
}
|
||||||
|
}
|
1
src/lib.rs
Normal file
1
src/lib.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
pub mod camera;
|
52
src/main.rs
52
src/main.rs
|
@ -1,3 +1,53 @@
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use rake::camera::FlyCamera;
|
||||||
|
use rake::camera::FlyCameraPlugin;
|
||||||
|
use std::process::exit;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("Hello, world!");
|
App::build()
|
||||||
|
.add_resource(Msaa { samples: 4 })
|
||||||
|
.add_plugins(DefaultPlugins)
|
||||||
|
.add_startup_system(init.system())
|
||||||
|
.add_plugin(FlyCameraPlugin)
|
||||||
|
.add_system(exit_game_system.system())
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init(
|
||||||
|
commands: &mut Commands,
|
||||||
|
mut meshes: ResMut<Assets<Mesh>>,
|
||||||
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
|
) {
|
||||||
|
commands
|
||||||
|
.spawn(LightBundle {
|
||||||
|
transform: Transform::from_translation(Vec3::new(4.0, 8.0, 4.0)),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.spawn(Camera3dBundle::default())
|
||||||
|
.with(FlyCamera::default());
|
||||||
|
|
||||||
|
let box_mesh = meshes.add(Mesh::from(shape::Cube { size: 0.25 }));
|
||||||
|
let box_material = materials.add(Color::rgb(1.0, 0.2, 0.3).into());
|
||||||
|
|
||||||
|
const AMOUNT: i32 = 6;
|
||||||
|
for x in -(AMOUNT / 2)..(AMOUNT / 2) {
|
||||||
|
for y in -(AMOUNT / 2)..(AMOUNT / 2) {
|
||||||
|
for z in -(AMOUNT / 2)..(AMOUNT / 2) {
|
||||||
|
commands.spawn(PbrBundle {
|
||||||
|
mesh: box_mesh.clone(),
|
||||||
|
material: box_material.clone(),
|
||||||
|
transform: Transform::from_translation(Vec3::new(
|
||||||
|
x as f32, y as f32, z as f32,
|
||||||
|
)),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn exit_game_system(keyboard_input: Res<Input<KeyCode>>) {
|
||||||
|
if keyboard_input.pressed(KeyCode::Escape) {
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue