basic moving camera

This commit is contained in:
Felix Ableitner 2020-12-29 16:39:10 +01:00
parent d5bcbb5339
commit 2ce1d6e809
5 changed files with 4050 additions and 1 deletions

3845
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -4,3 +4,4 @@ version = "0.1.0"
edition = "2018" edition = "2018"
[dependencies] [dependencies]
bevy = "0.4"

152
src/camera.rs Normal file
View 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
View file

@ -0,0 +1 @@
pub mod camera;

View file

@ -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);
}
} }