replicates bevy_flycam demo
This commit is contained in:
commit
c7452bba11
6 changed files with 3569 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
/target
|
||||||
|
.#*
|
3361
Cargo.lock
generated
Normal file
3361
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
9
Cargo.toml
Normal file
9
Cargo.toml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
[package]
|
||||||
|
name = "cyber_rider"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
bevy = { path = "../bevy" }
|
152
src/flycam.rs
Normal file
152
src/flycam.rs
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
use bevy::app::{Events, ManualEventReader};
|
||||||
|
use bevy::input::mouse::MouseMotion;
|
||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
// stolen with neither shame nor pity from git@github.com:sburris0/bevy_flycam.git, b90f6fc, which is copyright 2020 Spencer Burris
|
||||||
|
|
||||||
|
/// Keeps track of mouse motion events, pitch, and yaw
|
||||||
|
#[derive(Default)]
|
||||||
|
struct InputState {
|
||||||
|
reader_motion: ManualEventReader<MouseMotion>,
|
||||||
|
pitch: f32,
|
||||||
|
yaw: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Mouse sensitivity and movement speed
|
||||||
|
pub struct MovementSettings {
|
||||||
|
pub sensitivity: f32,
|
||||||
|
pub speed: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for MovementSettings {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
sensitivity: 0.00012,
|
||||||
|
speed: 12.,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Used in queries when you want flycams and not other cameras
|
||||||
|
#[derive(Debug, Component)]
|
||||||
|
pub struct FlyCam;
|
||||||
|
|
||||||
|
/// Grabs/ungrabs mouse cursor
|
||||||
|
fn toggle_grab_cursor(window: &mut Window) {
|
||||||
|
window.set_cursor_lock_mode(!window.cursor_locked());
|
||||||
|
window.set_cursor_visibility(!window.cursor_visible());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Grabs the cursor when game first starts
|
||||||
|
fn initial_grab_cursor(mut windows: ResMut<Windows>) {
|
||||||
|
toggle_grab_cursor(windows.get_primary_mut().unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Spawns the `Camera3dBundle` to be controlled
|
||||||
|
fn setup_player(mut commands: Commands) {
|
||||||
|
commands
|
||||||
|
.spawn_bundle(PerspectiveCameraBundle {
|
||||||
|
transform: Transform::from_xyz(-2.0, 5.0, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.insert(FlyCam);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Handles keyboard input and movement
|
||||||
|
fn player_move(
|
||||||
|
keys: Res<Input<KeyCode>>,
|
||||||
|
time: Res<Time>,
|
||||||
|
windows: Res<Windows>,
|
||||||
|
settings: Res<MovementSettings>,
|
||||||
|
mut query: Query<(&FlyCam, &mut Transform)>,
|
||||||
|
) {
|
||||||
|
let window = windows.get_primary().unwrap();
|
||||||
|
for (_camera, mut transform) in query.iter_mut() {
|
||||||
|
let mut velocity = Vec3::ZERO;
|
||||||
|
let local_z = transform.local_z();
|
||||||
|
let forward = -Vec3::new(local_z.x, 0., local_z.z);
|
||||||
|
let right = Vec3::new(local_z.z, 0., -local_z.x);
|
||||||
|
|
||||||
|
for key in keys.get_pressed() {
|
||||||
|
if window.cursor_locked() {
|
||||||
|
match key {
|
||||||
|
KeyCode::W => velocity += forward,
|
||||||
|
KeyCode::S => velocity -= forward,
|
||||||
|
KeyCode::A => velocity -= right,
|
||||||
|
KeyCode::D => velocity += right,
|
||||||
|
KeyCode::Space => velocity += Vec3::Y,
|
||||||
|
KeyCode::LShift => velocity -= Vec3::Y,
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
velocity = velocity.normalize();
|
||||||
|
|
||||||
|
if !velocity.is_nan() {
|
||||||
|
transform.translation += velocity * time.delta_seconds() * settings.speed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Handles looking around if cursor is locked
|
||||||
|
fn player_look(
|
||||||
|
settings: Res<MovementSettings>,
|
||||||
|
windows: Res<Windows>,
|
||||||
|
mut state: ResMut<InputState>,
|
||||||
|
motion: Res<Events<MouseMotion>>,
|
||||||
|
mut query: Query<(&FlyCam, &mut Transform)>,
|
||||||
|
) {
|
||||||
|
let window = windows.get_primary().unwrap();
|
||||||
|
for (_camera, mut transform) in query.iter_mut() {
|
||||||
|
for ev in state.reader_motion.iter(&motion) {
|
||||||
|
if window.cursor_locked() {
|
||||||
|
// Using smallest of height or width ensures equal vertical and horizontal sensitivity
|
||||||
|
let window_scale = window.height().min(window.width());
|
||||||
|
|
||||||
|
state.pitch -= (settings.sensitivity * ev.delta.y * window_scale).to_radians();
|
||||||
|
state.yaw -= (settings.sensitivity * ev.delta.x * window_scale).to_radians();
|
||||||
|
}
|
||||||
|
|
||||||
|
state.pitch = state.pitch.clamp(-1.54, 1.54);
|
||||||
|
|
||||||
|
// Order is important to prevent unintended roll
|
||||||
|
transform.rotation = Quat::from_axis_angle(Vec3::Y, state.yaw)
|
||||||
|
* Quat::from_axis_angle(Vec3::X, state.pitch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cursor_grab(keys: Res<Input<KeyCode>>, mut windows: ResMut<Windows>) {
|
||||||
|
let window = windows.get_primary_mut().unwrap();
|
||||||
|
if keys.just_pressed(KeyCode::Escape) {
|
||||||
|
toggle_grab_cursor(window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Contains everything needed to add first-person fly camera behavior to your game
|
||||||
|
pub struct PlayerPlugin;
|
||||||
|
impl Plugin for PlayerPlugin {
|
||||||
|
fn build(&self, app: &mut App) {
|
||||||
|
app.init_resource::<InputState>()
|
||||||
|
.init_resource::<MovementSettings>()
|
||||||
|
.add_startup_system(setup_player.system())
|
||||||
|
.add_startup_system(initial_grab_cursor.system())
|
||||||
|
.add_system(player_move.system())
|
||||||
|
.add_system(player_look.system())
|
||||||
|
.add_system(cursor_grab.system());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Same as `PlayerPlugin` but does not spawn a camera
|
||||||
|
pub struct NoCameraPlayerPlugin;
|
||||||
|
impl Plugin for NoCameraPlayerPlugin {
|
||||||
|
fn build(&self, app: &mut App) {
|
||||||
|
app.init_resource::<InputState>()
|
||||||
|
.init_resource::<MovementSettings>()
|
||||||
|
.add_startup_system(initial_grab_cursor.system())
|
||||||
|
.add_system(player_move.system())
|
||||||
|
.add_system(player_look.system())
|
||||||
|
.add_system(cursor_grab.system());
|
||||||
|
}
|
||||||
|
}
|
1
src/lib.rs
Normal file
1
src/lib.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
pub mod flycam;
|
44
src/main.rs
Normal file
44
src/main.rs
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use cyber_rider::flycam::MovementSettings;
|
||||||
|
use cyber_rider::flycam::PlayerPlugin;
|
||||||
|
|
||||||
|
// stolen with neither shame nor pity from git@github.com:sburris0/bevy_flycam.git, b90f6fc, which is copyright 2020 Spencer Burris
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
App::new()
|
||||||
|
.insert_resource(Msaa { samples: 4 })
|
||||||
|
.add_plugins(DefaultPlugins)
|
||||||
|
.add_plugin(PlayerPlugin)
|
||||||
|
.insert_resource(MovementSettings {
|
||||||
|
sensitivity: 0.00015, // default: 0.00012
|
||||||
|
speed: 12.0, // default: 12.0
|
||||||
|
})
|
||||||
|
.add_startup_system(setup.system())
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// set up a simple 3D scene
|
||||||
|
fn setup(
|
||||||
|
mut commands: Commands,
|
||||||
|
mut meshes: ResMut<Assets<Mesh>>,
|
||||||
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
|
) {
|
||||||
|
// plane
|
||||||
|
commands.spawn_bundle(PbrBundle {
|
||||||
|
mesh: meshes.add(Mesh::from(shape::Plane { size: 5.0 })),
|
||||||
|
material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
// cube
|
||||||
|
commands.spawn_bundle(PbrBundle {
|
||||||
|
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
|
||||||
|
material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()),
|
||||||
|
transform: Transform::from_xyz(0.0, 0.5, 0.0),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
// light
|
||||||
|
commands.spawn_bundle(PointLightBundle {
|
||||||
|
transform: Transform::from_xyz(4.0, 8.0, 4.0),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in a new issue