Initial commit

This commit is contained in:
Franklin 2023-09-12 00:47:37 -04:00
commit f55faadbe4
29 changed files with 4228 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

3907
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

19
Cargo.toml Normal file
View File

@ -0,0 +1,19 @@
[package]
name = "experiment"
version = "0.1.0"
edition = "2021"
# Enable a small amount of optimization in debug mode
[profile.dev]
opt-level = 1
# Enable high optimizations for dependencies (incl. Bevy), but not for our code:
[profile.dev.package."*"]
opt-level = 3
[profile.dev.package.bevy_rapier3d]
opt-level = 3
[dependencies]
bevy = { version = "0.11.2", features = ["dynamic_linking"]}
bevy_rapier3d = { version = "0.22.0", features = ["debug-render-3d"] }

2
rust-toolchain.toml Normal file
View File

@ -0,0 +1,2 @@
[toolchain]
channel = "nightly"

1
src/assets/mod.rs Normal file
View File

@ -0,0 +1 @@

5
src/comps/core/camera.rs Normal file
View File

@ -0,0 +1,5 @@
use bevy::prelude::Component;
#[derive(Component)]
pub struct MainCamera;

View File

@ -0,0 +1,24 @@
use bevy::prelude::*;
use bevy_rapier3d::prelude::*;
use crate::logic::core::player::player_movement::{PlayerMovementInput, move_player};
use super::markers::player::Player;
/// System that captures input and fires events
pub fn capture_input(keyboard_input: Res<Input<KeyCode>>, query: Query<(&mut Velocity, &mut ExternalImpulse), With<Player>>, time: Res<Time>) {
// Don't allocate on each frame. Instead Check if any of the inputs are being pressed and then allocate.
if keyboard_input.any_pressed([KeyCode::A, KeyCode::S, KeyCode::D, KeyCode::W, KeyCode::C, KeyCode::Space]) {
let player_movement_input = PlayerMovementInput {
up: keyboard_input.pressed(KeyCode::Space),
down: keyboard_input.pressed(KeyCode::C),
left: keyboard_input.pressed(KeyCode::A),
right: keyboard_input.pressed(KeyCode::D),
front: keyboard_input.pressed(KeyCode::W),
back: keyboard_input.pressed(KeyCode::S),
sprint: keyboard_input.pressed(KeyCode::ShiftLeft),
};
move_player(player_movement_input, query, time);
}
}

View File

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

View File

@ -0,0 +1,4 @@
use bevy::prelude::Component;
#[derive(Component)]
pub struct Player;

3
src/comps/core/mod.rs Normal file
View File

@ -0,0 +1,3 @@
pub mod camera;
pub mod controller;
pub mod markers;

1
src/comps/mod.rs Normal file
View File

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

1
src/constants/mod.rs Normal file
View File

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

View File

@ -0,0 +1,3 @@
pub const MAX_LINEAR_PLAYER_VELOCITY: f32 = 10.0;
pub const PLAYER_ACCELERATION: f32 = 10.0;

1
src/logic/core/mod.rs Normal file
View File

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

View File

@ -0,0 +1,19 @@
use bevy::prelude::*;
use crate::{comps::core::{markers::player::Player, camera::MainCamera}, utils::rad_deg::radians_from_degrees};
pub fn sync_camera_to_player(
player: Query<&Transform, (With<Player>, Without<MainCamera>)>,
mut camera: Query<&mut Transform, (With<MainCamera>, Without<Player>)>,
) {
let Ok(player) = player.get_single() else { return };
let Ok(mut camera_transform) = camera.get_single_mut() else { return };
camera_transform.translation = player.translation;
camera_transform.rotation = player.rotation;
camera_transform.translation.y += 0.5;
camera_transform.rotate_x(radians_from_degrees(-15.0)); // Make camera slightly point downward.
}

View File

@ -0,0 +1,3 @@
pub mod player_movement;
pub mod spawn_player;
pub mod camera_player_sync;

View File

@ -0,0 +1,87 @@
use bevy::prelude::*;
use bevy_rapier3d::prelude::*;
use crate::{comps::core::markers::player::Player, constants::player_values::{MAX_LINEAR_PLAYER_VELOCITY, PLAYER_ACCELERATION}};
/// Holds all the possible ways a player can be attempting to move at any time.
#[derive(Default)]
pub struct PlayerMovementInput {
/// Means the player is pressing the space bar key. (JUMP)
/// ## DOES NOT MEAN the player should gain upwards velocity
pub up: bool,
/// Means the player is pressing the control key. (CROUCH)
/// ## DOES NOT MEAN the player should gain downards velocity
pub down: bool,
/// A KEY
pub left: bool,
/// D KEY
pub right: bool,
/// W KEY
pub front: bool,
/// S KEY
pub back: bool,
// LShift (SPRINTING)
pub sprint: bool,
}
/// Applies game logic to determine how player should move.
pub fn move_player(player_movement_input: PlayerMovementInput, mut query: Query<(&mut Velocity, &mut ExternalImpulse), With<Player>>, time: Res<Time>,) {
for (mut player_velocity, mut player_external_force) in &mut query {
let crouch_multiplier = if player_movement_input.down {
0.25
} else {
1.0
};
let sprint_multiplier = if player_movement_input.sprint && !player_movement_input.down {
2.5
} else {
1.0
};
if player_movement_input.front {
player_velocity.linvel.z = apply_movement_acceleration(player_velocity.linvel.z, false, time.delta_seconds(), sprint_multiplier);
}
if player_movement_input.back {
player_velocity.linvel.z = apply_movement_acceleration(player_velocity.linvel.z, true, time.delta_seconds(), 1.0);
}
if player_movement_input.right {
player_velocity.linvel.x = apply_movement_acceleration(player_velocity.linvel.x, true, time.delta_seconds(), 1.0);
}
if player_movement_input.left {
player_velocity.linvel.x = apply_movement_acceleration(player_velocity.linvel.x, false, time.delta_seconds(), 1.0);
}
if player_movement_input.up {
player_external_force.impulse = Vec3::new(0.0, 200.0, 0.0);
}
// When player velocity exceeds max linear velocity then set to max_linear_vel value
if player_velocity.linvel.x.abs() > MAX_LINEAR_PLAYER_VELOCITY * crouch_multiplier * sprint_multiplier {
let positive = player_velocity.linvel.x.is_sign_positive();
if positive { player_velocity.linvel.x = MAX_LINEAR_PLAYER_VELOCITY * crouch_multiplier * sprint_multiplier }
else { player_velocity.linvel.x = MAX_LINEAR_PLAYER_VELOCITY * -1.0 * crouch_multiplier }
}
if player_velocity.linvel.z.abs() > MAX_LINEAR_PLAYER_VELOCITY * crouch_multiplier {
let positive = player_velocity.linvel.z.is_sign_positive();
if positive { player_velocity.linvel.z = MAX_LINEAR_PLAYER_VELOCITY * crouch_multiplier }
else { player_velocity.linvel.z = MAX_LINEAR_PLAYER_VELOCITY * -1.0 * crouch_multiplier }
}
}
}
// currentLinearVelocity + Acceleration * deltaTime
fn apply_movement_acceleration(current_linvel: f32, positive: bool, delta_time_secs: f32, multiplier: f32) -> f32 {
if positive {
if current_linvel.is_sign_positive() {
current_linvel + PLAYER_ACCELERATION * delta_time_secs * multiplier
} else {
// Make it so deacceleration is faster
current_linvel + (PLAYER_ACCELERATION * delta_time_secs * 2.0) * multiplier
}
} else {
if current_linvel.is_sign_negative() {
current_linvel - PLAYER_ACCELERATION * delta_time_secs * multiplier
} else {
// Make it so deacceleration is faster
current_linvel - (PLAYER_ACCELERATION * delta_time_secs * 2.0) * multiplier
}
}
}

View File

@ -0,0 +1,29 @@
use bevy::prelude::*;
use bevy_rapier3d::prelude::*;
use crate::comps::core::{markers::player::Player, camera::MainCamera};
pub fn spawn_player(mut commands: Commands) {
commands.spawn(Player)
.insert(RigidBody::Dynamic)
.insert(GravityScale(1.0))
.insert(Collider::capsule_y(2.0, 2.0))
.insert(Restitution::coefficient(0.3))
.insert(Friction { coefficient: 0.0, ..Default::default() })
.insert(TransformBundle::from(Transform::from_xyz(3.0, 5.0, 2.0)))
.insert(Velocity::zero())
.insert(Damping { linear_damping: 1.0, angular_damping: 1.0 })
.insert(LockedAxes::ROTATION_LOCKED_X | LockedAxes::ROTATION_LOCKED_Z)
.insert(ColliderMassProperties::Mass(100.0))
.insert(ExternalImpulse {
impulse: Vec3::ZERO,
torque_impulse: Vec3::ZERO,
});
commands.spawn(MainCamera)
.insert(Camera3dBundle {
transform: Transform::from_xyz(0.0, 0.0, 0.0).looking_at(Vec3::ZERO, Vec3::Y),
..Default::default()
});
}

1
src/logic/mod.rs Normal file
View File

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

32
src/main.rs Normal file
View File

@ -0,0 +1,32 @@
use bevy::prelude::*;
use bevy_rapier3d::prelude::*;
use scenes::scene1;
mod assets;
mod comps;
mod scenes;
mod setup;
mod logic;
mod constants;
mod utils;
fn main() {
let mut application = App::new();
setup_plugins(&mut application);
load(&mut application);
application.run();
}
fn setup_plugins(application: &mut App) {
application
.add_plugins(DefaultPlugins)
.add_plugins(RapierPhysicsPlugin::<NoUserData>::default()) // Rapier Physics
;//.add_plugins(RapierDebugRenderPlugin::default()); // Uncomment this to see physics objects as wireframes
}
fn load(application: &mut App) {
scene1::init::load_scene(application);
}

1
src/scenes/mod.rs Normal file
View File

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

View File

@ -0,0 +1,19 @@
use bevy::prelude::*;
use bevy_rapier3d::prelude::*;
pub fn spawn_ground(mut commands: Commands, mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,) {
commands
.spawn(Collider::cuboid(20.0, 0.1, 20.0))
.insert(TransformBundle::from(Transform::from_xyz(0.0, -2.0, 0.0)))
.insert(RigidBody::Fixed)
.insert(PbrBundle {
mesh: meshes.add(shape::Plane::from_size(40.0).into()),
material: materials.add(StandardMaterial {
base_color: Color::WHITE,
perceptual_roughness: 1.0,
..default()
}),
..default()
});
}

20
src/scenes/scene1/init.rs Normal file
View File

@ -0,0 +1,20 @@
use bevy::prelude::*;
use crate::{logic::core::player::{spawn_player::spawn_player, camera_player_sync::sync_camera_to_player}, comps::core::controller::capture_input};
use super::{ground::spawn_ground, lighting::setup_lighting, obstacles::spawn_obstacles};
pub fn load_scene(application: &mut App) {
// Startup
application.add_systems(Startup, spawn_ground);
application.add_systems(Startup, spawn_obstacles);
application.add_systems(Startup, spawn_player);
// Update
application.add_systems(Update, capture_input);
application.add_systems(Update, sync_camera_to_player);
application.add_systems(Startup, setup_lighting);
}

View File

@ -0,0 +1,10 @@
use bevy::prelude::*;
pub fn setup_lighting(mut commands: Commands) {
commands.spawn(SpotLightBundle {
spot_light: SpotLight { color: Color::WHITE, intensity: 3000.0, range: 500.0, shadows_enabled: true, ..Default::default() },
transform: Transform::from_xyz(20.0, 20.0, 20.0).looking_at(Vec3::ZERO, Vec3::Y),
visibility: Visibility::Visible,
..Default::default()
});
}

5
src/scenes/scene1/mod.rs Normal file
View File

@ -0,0 +1,5 @@
pub mod init;
pub mod ground;
pub mod lighting;
pub mod obstacles;

View File

@ -0,0 +1,20 @@
use bevy::prelude::*;
use bevy_rapier3d::prelude::*;
pub fn spawn_obstacles(mut commands: Commands, mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,) {
let mesh = shape::Box::new(3.0, 7.0, 3.0).into();
commands
.spawn(Collider::from_bevy_mesh(&mesh, &Default::default()).unwrap())
.insert(RigidBody::Fixed)
.insert(PbrBundle {
mesh: meshes.add(mesh.into()),
material: materials.add(StandardMaterial {
base_color: Color::RED,
perceptual_roughness: 1.0,
..default()
}),
transform: Transform::from_xyz(-5.0, 3.5, -10.0),
..default()
});
}

0
src/setup/mod.rs Normal file
View File

2
src/utils/mod.rs Normal file
View File

@ -0,0 +1,2 @@
pub mod rad_deg;

7
src/utils/rad_deg.rs Normal file
View File

@ -0,0 +1,7 @@
use std::f32::consts::PI;
#[allow(unused)]
pub fn radians_from_degrees(degrees: f32) -> f32 {
(PI * degrees) / 180.0
}