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