Compare commits
2 commits
6b9a879927
...
3d0d86f24c
Author | SHA1 | Date | |
---|---|---|---|
|
3d0d86f24c | ||
|
4d94f2bfa4 |
11 changed files with 172 additions and 121 deletions
23
Cargo.lock
generated
23
Cargo.lock
generated
|
@ -284,9 +284,9 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "avian3d"
|
name = "avian3d"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0a8da53296a1bc166b84f99aa7c6b9d8c10c71f0c022bc4fc72dd1fc49323b29"
|
checksum = "54325576b6efa46576db611624db749b553d0c66e439862bdc60c43e01f012f9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"avian_derive",
|
"avian_derive",
|
||||||
"bevy",
|
"bevy",
|
||||||
|
@ -1223,9 +1223,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "blake3"
|
name = "blake3"
|
||||||
version = "1.5.2"
|
version = "1.5.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3d08263faac5cde2a4d52b513dadb80846023aade56fcd8fc99ba73ba8050e92"
|
checksum = "e9ec96fe9a81b5e365f9db71fe00edc4fe4ca2cc7dcb7861f0603012a7caa210"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayref",
|
"arrayref",
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
|
@ -1296,9 +1296,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytes"
|
name = "bytes"
|
||||||
version = "1.6.0"
|
version = "1.6.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9"
|
checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "calloop"
|
name = "calloop"
|
||||||
|
@ -1316,13 +1316,12 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.1.2"
|
version = "1.1.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "47de7e88bbbd467951ae7f5a6f34f70d1b4d9cfce53d5fd70f74ebe118b3db56"
|
checksum = "324c74f2155653c90b04f25b2a47a8a631360cb908f92a772695f430c7e31052"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"jobserver",
|
"jobserver",
|
||||||
"libc",
|
"libc",
|
||||||
"once_cell",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3067,7 +3066,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"redox_syscall 0.5.2",
|
"redox_syscall 0.5.3",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"windows-targets 0.52.6",
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
@ -3367,9 +3366,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.5.2"
|
version = "0.5.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd"
|
checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.6.0",
|
"bitflags 2.6.0",
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use bevy::{
|
use bevy::{
|
||||||
prelude::{Component, ReflectResource, Resource, Vec3},
|
prelude::{Component, ReflectResource, Resource},
|
||||||
reflect::Reflect,
|
reflect::Reflect,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -26,21 +26,6 @@ impl ActionDebugInstant {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Component)]
|
|
||||||
pub(super) struct Tunneling {
|
|
||||||
pub frames: usize,
|
|
||||||
pub dir: Vec3,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Tunneling {
|
|
||||||
fn default() -> Self {
|
|
||||||
Tunneling {
|
|
||||||
frames: 15,
|
|
||||||
dir: Vec3::ZERO,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Resource, Reflect)]
|
#[derive(Debug, Resource, Reflect)]
|
||||||
#[reflect(Resource)]
|
#[reflect(Resource)]
|
||||||
pub struct MovementSettings {
|
pub struct MovementSettings {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use avian3d::prelude::*;
|
use avian3d::prelude::{PhysicsPlugins, SubstepCount};
|
||||||
use bevy::{
|
use bevy::{
|
||||||
app::{Startup, Update},
|
app::Update,
|
||||||
diagnostic::FrameTimeDiagnosticsPlugin,
|
diagnostic::FrameTimeDiagnosticsPlugin,
|
||||||
ecs::reflect::ReflectResource,
|
ecs::reflect::ReflectResource,
|
||||||
prelude::{App, IntoSystemConfigs, Plugin, Resource},
|
prelude::{App, IntoSystemConfigs, Plugin, Resource},
|
||||||
|
@ -29,14 +29,14 @@ impl Plugin for CyberActionPlugin {
|
||||||
.init_resource::<CyberLean>()
|
.init_resource::<CyberLean>()
|
||||||
.register_type::<CyberLean>()
|
.register_type::<CyberLean>()
|
||||||
.register_type::<CatControllerSettings>()
|
.register_type::<CatControllerSettings>()
|
||||||
.add_plugins((
|
.add_plugins((PhysicsPlugins::default(), FrameTimeDiagnosticsPlugin))
|
||||||
PhysicsPlugins::default(),
|
|
||||||
FrameTimeDiagnosticsPlugin::default(),
|
|
||||||
))
|
|
||||||
.insert_resource(SubstepCount(12))
|
.insert_resource(SubstepCount(12))
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Update,
|
Update,
|
||||||
(gravity, cyber_lean, falling_cat, input_forces).chain(),
|
(
|
||||||
|
gravity,
|
||||||
|
(cyber_lean, suspension, falling_cat, input_forces).after(clear_forces),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
use std::f32::consts::{FRAC_PI_3, FRAC_PI_4};
|
use std::f32::consts::{FRAC_PI_3, FRAC_PI_4};
|
||||||
|
|
||||||
use avian3d::{
|
use avian3d::{
|
||||||
dynamics::solver::xpbd::AngularConstraint, parry::mass_properties::MassProperties, prelude::*,
|
dynamics::solver::xpbd::AngularConstraint,
|
||||||
};
|
prelude::{
|
||||||
use bevy::prelude::{
|
ColliderMassProperties, ExternalForce, ExternalTorque, Gravity, LinearVelocity,
|
||||||
Commands, Entity, Quat, Query, Res, ResMut, Time, Transform, Vec3, With, Without,
|
PrismaticJoint, RigidBodyQuery,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
use bevy::prelude::{Quat, Query, Res, ResMut, Time, Transform, Vec3, With, Without};
|
||||||
|
|
||||||
//#[cfg(feature = "inspector")]
|
use super::{CatControllerSettings, CatControllerState, CyberLean, MovementSettings};
|
||||||
//use super::ActionDebugInstant;
|
|
||||||
use super::{CatControllerSettings, CatControllerState, CyberLean, MovementSettings, Tunneling};
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bike::{CyberBikeBody, CyberSteering, CyberWheel, WheelConfig, BIKE_WHEEL_COLLISION_GROUP},
|
bike::{CyberBikeBody, CyberFork, CyberSpring, CyberSteering, CyberWheel, WheelConfig},
|
||||||
input::InputState,
|
input::InputState,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -37,14 +37,42 @@ fn rotate_point(pt: &Vec3, rot: &Quat) -> Vec3 {
|
||||||
|
|
||||||
/// The gravity vector points from the cyberbike to the center of the planet.
|
/// The gravity vector points from the cyberbike to the center of the planet.
|
||||||
pub(super) fn gravity(
|
pub(super) fn gravity(
|
||||||
mut query: Query<(&Transform, &mut ExternalForce), With<CyberBikeBody>>,
|
xform: Query<&Transform, With<CyberBikeBody>>,
|
||||||
|
|
||||||
settings: Res<MovementSettings>,
|
settings: Res<MovementSettings>,
|
||||||
mut gravity: ResMut<Gravity>,
|
mut gravity: ResMut<Gravity>,
|
||||||
#[cfg(feature = "inspector")] mut debug_instant: ResMut<ActionDebugInstant>,
|
|
||||||
) {
|
) {
|
||||||
let (xform, mut forces) = query.single_mut();
|
let xform = xform.single();
|
||||||
*gravity = Gravity(xform.translation.normalize() * -settings.gravity);
|
*gravity = Gravity(xform.translation.normalize() * -settings.gravity);
|
||||||
forces.clear();
|
|
||||||
|
// clear all external forces
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn clear_forces(mut forces: Query<(&mut ExternalForce, &mut ExternalTorque)>) {
|
||||||
|
for (mut force, mut torque) in forces.iter_mut() {
|
||||||
|
force.clear();
|
||||||
|
torque.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn suspension(
|
||||||
|
movment_settings: Res<MovementSettings>,
|
||||||
|
wheel_config: Res<WheelConfig>,
|
||||||
|
mass: Query<&ColliderMassProperties, With<CyberBikeBody>>,
|
||||||
|
mut axels: Query<(&mut ExternalForce, &CyberSpring, &Transform)>,
|
||||||
|
) {
|
||||||
|
let mass = if let Ok(mass) = mass.get_single() {
|
||||||
|
mass.mass.0
|
||||||
|
} else {
|
||||||
|
1.0
|
||||||
|
};
|
||||||
|
let gravity = movment_settings.gravity;
|
||||||
|
let mag = -wheel_config.stiffness * mass * gravity;
|
||||||
|
for (mut force, spring, xform) in axels.iter_mut() {
|
||||||
|
let spring = mag * spring.0;
|
||||||
|
let spring = xform.translation + spring;
|
||||||
|
let _ = force.apply_force(spring);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The desired lean angle, given steering input and speed.
|
/// The desired lean angle, given steering input and speed.
|
||||||
|
@ -106,26 +134,30 @@ pub(super) fn input_forces(
|
||||||
settings: Res<MovementSettings>,
|
settings: Res<MovementSettings>,
|
||||||
input: Res<InputState>,
|
input: Res<InputState>,
|
||||||
time: Res<Time>,
|
time: Res<Time>,
|
||||||
axle: Query<Entity, With<CyberSteering>>,
|
fork: Query<&PrismaticJoint, With<CyberFork>>,
|
||||||
|
mut axle: Query<(RigidBodyQuery, &Transform), With<CyberSteering>>,
|
||||||
mut braking_query: Query<&mut ExternalTorque, With<CyberWheel>>,
|
mut braking_query: Query<&mut ExternalTorque, With<CyberWheel>>,
|
||||||
mut body_query: Query<
|
mut body_query: Query<
|
||||||
(
|
(
|
||||||
Entity,
|
RigidBodyQuery,
|
||||||
&Transform,
|
&Transform,
|
||||||
&ColliderMassProperties,
|
&ColliderMassProperties,
|
||||||
&mut ExternalForce,
|
&mut ExternalForce,
|
||||||
),
|
),
|
||||||
With<CyberBikeBody>,
|
(With<CyberBikeBody>, Without<CyberSteering>),
|
||||||
>,
|
>,
|
||||||
) {
|
) {
|
||||||
let (bike, xform, mass, mut forces) = body_query.single_mut();
|
let Ok((mut bike, xform, mass, mut forces)) = body_query.get_single_mut() else {
|
||||||
|
bevy::log::warn!("no bike body found");
|
||||||
|
return;
|
||||||
|
};
|
||||||
let dt = time.delta_seconds();
|
let dt = time.delta_seconds();
|
||||||
|
|
||||||
// thrust
|
// thrust
|
||||||
let thrust = xform.forward() * input.throttle * settings.accel;
|
let thrust = xform.forward() * input.throttle * settings.accel;
|
||||||
let point = xform.translation + *xform.back();
|
let point = xform.translation + *xform.back();
|
||||||
|
|
||||||
*forces.apply_force_at_point(dt * thrust, point, mass.center_of_mass.0);
|
let _ = *forces.apply_force_at_point(dt * thrust, point, mass.center_of_mass.0);
|
||||||
|
|
||||||
// brake + thrust
|
// brake + thrust
|
||||||
for mut motor in braking_query.iter_mut() {
|
for mut motor in braking_query.iter_mut() {
|
||||||
|
@ -142,7 +174,14 @@ pub(super) fn input_forces(
|
||||||
|
|
||||||
// steering
|
// steering
|
||||||
let _angle = yaw_to_angle(input.yaw);
|
let _angle = yaw_to_angle(input.yaw);
|
||||||
let _axle = axle.single();
|
let (mut axle, xform) = axle.single_mut();
|
||||||
//steering.align_orientation(bike, steering, rotation_difference, lagrange,
|
|
||||||
// compliance, dt)
|
let cur_rot = xform.rotation;
|
||||||
|
let fork = fork.single();
|
||||||
|
let axis = fork.free_axis.normalize();
|
||||||
|
let new = Quat::from_axis_angle(axis, _angle);
|
||||||
|
let diff = (new - cur_rot).to_scaled_axis();
|
||||||
|
let mut compliance = 1.0;
|
||||||
|
|
||||||
|
fork.align_orientation(&mut axle, &mut bike, diff, &mut compliance, 1.0, dt);
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,24 +37,20 @@ pub(super) fn spawn_cyberbike(
|
||||||
|
|
||||||
let scene = asset_server.load("cb-no-y_up.glb#Scene0");
|
let scene = asset_server.load("cb-no-y_up.glb#Scene0");
|
||||||
|
|
||||||
let spatialbundle = SpatialBundle {
|
let body_collider =
|
||||||
transform: xform,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let body =
|
|
||||||
Collider::capsule_endpoints(0.5, Vec3::new(0.0, 0.0, -0.65), Vec3::new(0.0, 0.0, 0.8));
|
Collider::capsule_endpoints(0.5, Vec3::new(0.0, 0.0, -0.65), Vec3::new(0.0, 0.0, 0.8));
|
||||||
let mass_props = MassPropertiesBundle::new_computed(&body, 0.6);
|
|
||||||
let bike = commands
|
let bike = commands
|
||||||
.spawn(RigidBody::Dynamic)
|
.spawn(SpatialBundle::from_transform(xform))
|
||||||
.insert(spatialbundle)
|
|
||||||
.insert((
|
.insert((
|
||||||
body,
|
RigidBody::Dynamic,
|
||||||
mass_props.clone(),
|
body_collider,
|
||||||
bike_collision_group,
|
bike_collision_group,
|
||||||
restitution,
|
restitution,
|
||||||
friction,
|
friction,
|
||||||
SleepingDisabled,
|
SleepingDisabled,
|
||||||
|
CyberBikeBody,
|
||||||
|
CatControllerState::default(),
|
||||||
|
ColliderDensity(0.6),
|
||||||
LinearDamping(0.1),
|
LinearDamping(0.1),
|
||||||
AngularDamping(2.0),
|
AngularDamping(2.0),
|
||||||
LinearVelocity::ZERO,
|
LinearVelocity::ZERO,
|
||||||
|
@ -68,8 +64,6 @@ pub(super) fn spawn_cyberbike(
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.insert(CyberBikeBody)
|
|
||||||
.insert(CatControllerState::default())
|
|
||||||
.id();
|
.id();
|
||||||
|
|
||||||
spawn_wheels(&mut commands, bike, &wheel_conf, &mut meshterials);
|
spawn_wheels(&mut commands, bike, &wheel_conf, &mut meshterials);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use bevy::{
|
use bevy::{
|
||||||
|
math::Vec3,
|
||||||
prelude::{Component, ReflectResource, Resource},
|
prelude::{Component, ReflectResource, Resource},
|
||||||
reflect::Reflect,
|
reflect::Reflect,
|
||||||
};
|
};
|
||||||
|
@ -6,12 +7,18 @@ use bevy::{
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub struct CyberBikeBody;
|
pub struct CyberBikeBody;
|
||||||
|
|
||||||
#[derive(Clone, Component)]
|
#[derive(Clone, Copy, Component)]
|
||||||
pub struct CyberSteering;
|
pub struct CyberSteering;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Component)]
|
#[derive(Clone, Copy, Debug, Component)]
|
||||||
pub struct CyberWheel;
|
pub struct CyberWheel;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Component)]
|
||||||
|
pub struct CyberSpring(pub Vec3);
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Component)]
|
||||||
|
pub struct CyberFork;
|
||||||
|
|
||||||
#[derive(Resource, Reflect)]
|
#[derive(Resource, Reflect)]
|
||||||
#[reflect(Resource)]
|
#[reflect(Resource)]
|
||||||
pub struct WheelConfig {
|
pub struct WheelConfig {
|
||||||
|
@ -35,7 +42,7 @@ impl Default for WheelConfig {
|
||||||
rear_back: 1.0,
|
rear_back: 1.0,
|
||||||
y: -0.1,
|
y: -0.1,
|
||||||
limits: [-0.5, 0.1],
|
limits: [-0.5, 0.1],
|
||||||
stiffness: 190.0,
|
stiffness: 3.0,
|
||||||
damping: 8.0,
|
damping: 8.0,
|
||||||
radius: 0.25,
|
radius: 0.25,
|
||||||
thickness: 0.11,
|
thickness: 0.11,
|
||||||
|
|
|
@ -3,7 +3,7 @@ mod components;
|
||||||
mod wheels;
|
mod wheels;
|
||||||
|
|
||||||
use bevy::{
|
use bevy::{
|
||||||
app::PostStartup,
|
app::{PostStartup, Startup},
|
||||||
prelude::{App, Assets, Mesh, Plugin, ResMut, StandardMaterial},
|
prelude::{App, Assets, Mesh, Plugin, ResMut, StandardMaterial},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -23,6 +23,6 @@ impl Plugin for CyberBikePlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.insert_resource(WheelConfig::default())
|
app.insert_resource(WheelConfig::default())
|
||||||
.register_type::<WheelConfig>()
|
.register_type::<WheelConfig>()
|
||||||
.add_systems(PostStartup, spawn_cyberbike);
|
.add_systems(Startup, spawn_cyberbike);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
use avian3d::prelude::*;
|
use avian3d::prelude::*;
|
||||||
use bevy::prelude::{Torus as Tire, *};
|
use bevy::prelude::{Torus as Tire, *};
|
||||||
|
|
||||||
use super::{CyberSteering, CyberWheel, Meshterial, WheelConfig, BIKE_WHEEL_COLLISION_GROUP};
|
use super::{
|
||||||
|
CyberFork, CyberSpring, CyberSteering, CyberWheel, Meshterial, WheelConfig,
|
||||||
|
BIKE_WHEEL_COLLISION_GROUP,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn spawn_wheels(
|
pub fn spawn_wheels(
|
||||||
commands: &mut Commands,
|
commands: &mut Commands,
|
||||||
|
@ -12,7 +15,6 @@ pub fn spawn_wheels(
|
||||||
let (membership, filter) = BIKE_WHEEL_COLLISION_GROUP;
|
let (membership, filter) = BIKE_WHEEL_COLLISION_GROUP;
|
||||||
let wheels_collision_group = CollisionLayers::new(membership, filter);
|
let wheels_collision_group = CollisionLayers::new(membership, filter);
|
||||||
let wheel_y = conf.y;
|
let wheel_y = conf.y;
|
||||||
let stiffness = conf.stiffness;
|
|
||||||
let not_sleeping = SleepingDisabled;
|
let not_sleeping = SleepingDisabled;
|
||||||
let ccd = SweptCcd::NON_LINEAR.include_dynamic(false);
|
let ccd = SweptCcd::NON_LINEAR.include_dynamic(false);
|
||||||
let limits = conf.limits;
|
let limits = conf.limits;
|
||||||
|
@ -84,11 +86,26 @@ pub fn spawn_wheels(
|
||||||
))
|
))
|
||||||
.id();
|
.id();
|
||||||
|
|
||||||
let axel = if let Some(ref steering) = steering {
|
let spring = CyberSpring(suspension_axis);
|
||||||
commands.spawn((RigidBody::Dynamic, ExternalForce::ZERO, steering.clone()))
|
let axel = if let Some(steering) = steering {
|
||||||
|
commands.spawn((
|
||||||
|
RigidBody::Dynamic,
|
||||||
|
ExternalForce::ZERO,
|
||||||
|
steering,
|
||||||
|
spring,
|
||||||
|
Collider::sphere(0.1),
|
||||||
|
ColliderDensity(0.1),
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
commands.spawn((RigidBody::Dynamic, ExternalForce::ZERO))
|
commands.spawn((
|
||||||
|
RigidBody::Dynamic,
|
||||||
|
ExternalForce::ZERO,
|
||||||
|
spring,
|
||||||
|
Collider::sphere(0.1),
|
||||||
|
ColliderDensity(0.1),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
.insert(SpatialBundle::default())
|
||||||
.id();
|
.id();
|
||||||
let axel_joint = RevoluteJoint::new(axel, wheel).with_aligned_axis(Vec3::NEG_X);
|
let axel_joint = RevoluteJoint::new(axel, wheel).with_aligned_axis(Vec3::NEG_X);
|
||||||
commands.spawn(axel_joint);
|
commands.spawn(axel_joint);
|
||||||
|
@ -100,7 +117,7 @@ pub fn spawn_wheels(
|
||||||
.with_local_anchor_1(Vec3::new(0.0, 0.0, 0.1))
|
.with_local_anchor_1(Vec3::new(0.0, 0.0, 0.1))
|
||||||
.with_local_anchor_2(offset)
|
.with_local_anchor_2(offset)
|
||||||
.with_limits(limits[0], limits[1]);
|
.with_limits(limits[0], limits[1]);
|
||||||
commands.spawn(joint);
|
commands.spawn((joint, CyberFork));
|
||||||
} else {
|
} else {
|
||||||
let joint = PrismaticJoint::new(axel, bike)
|
let joint = PrismaticJoint::new(axel, bike)
|
||||||
.with_free_axis(suspension_axis)
|
.with_free_axis(suspension_axis)
|
||||||
|
|
|
@ -81,7 +81,7 @@ fn follow_cyberbike(
|
||||||
// handle input pitch
|
// handle input pitch
|
||||||
let angle = input.pitch.powi(3) * MAX_PITCH;
|
let angle = input.pitch.powi(3) * MAX_PITCH;
|
||||||
let axis = cam_xform.right();
|
let axis = cam_xform.right();
|
||||||
cam_xform.rotate(Quat::from_axis_angle(axis, angle));
|
cam_xform.rotate(Quat::from_axis_angle(*axis, angle));
|
||||||
}
|
}
|
||||||
CyberCameras::Debug => {
|
CyberCameras::Debug => {
|
||||||
let mut ncx = bike_xform.to_owned();
|
let mut ncx = bike_xform.to_owned();
|
||||||
|
@ -101,7 +101,7 @@ fn update_active_camera(
|
||||||
) {
|
) {
|
||||||
// find the camera with the current state, set it as the ActiveCamera
|
// find the camera with the current state, set it as the ActiveCamera
|
||||||
query.iter_mut().for_each(|(mut cam, cyber)| {
|
query.iter_mut().for_each(|(mut cam, cyber)| {
|
||||||
if cyber.eq(&state.0) {
|
if cyber.eq(&state.get()) {
|
||||||
cam.is_active = true;
|
cam.is_active = true;
|
||||||
} else {
|
} else {
|
||||||
cam.is_active = false;
|
cam.is_active = false;
|
||||||
|
@ -112,13 +112,13 @@ fn update_active_camera(
|
||||||
fn cycle_cam_state(
|
fn cycle_cam_state(
|
||||||
state: Res<State<CyberCameras>>,
|
state: Res<State<CyberCameras>>,
|
||||||
mut next: ResMut<NextState<CyberCameras>>,
|
mut next: ResMut<NextState<CyberCameras>>,
|
||||||
mut keys: ResMut<Input<KeyCode>>,
|
mut keys: ResMut<ButtonInput<KeyCode>>,
|
||||||
) {
|
) {
|
||||||
if keys.just_pressed(KeyCode::D) {
|
if keys.just_pressed(KeyCode::KeyD) {
|
||||||
let new_state = state.0.next();
|
let new_state = state.get().next();
|
||||||
info!("{:?}", new_state);
|
info!("{:?}", new_state);
|
||||||
next.set(new_state);
|
next.set(new_state);
|
||||||
keys.reset(KeyCode::D);
|
keys.reset(KeyCode::KeyD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,9 +132,10 @@ impl Plugin for CyberCamPlugin {
|
||||||
|
|
||||||
fn common(app: &mut bevy::prelude::App) {
|
fn common(app: &mut bevy::prelude::App) {
|
||||||
app.insert_resource(DebugCamOffset::default())
|
app.insert_resource(DebugCamOffset::default())
|
||||||
.add_startup_system(setup_cybercams)
|
.add_systems(Startup, setup_cybercams)
|
||||||
.add_state::<CyberCameras>()
|
.init_state::<CyberCameras>()
|
||||||
.add_system(cycle_cam_state)
|
.add_systems(
|
||||||
.add_system(update_active_camera)
|
Update,
|
||||||
.add_system(follow_cyberbike);
|
(cycle_cam_state, update_active_camera, follow_cyberbike),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,9 @@ use crate::planet::PLANET_RADIUS;
|
||||||
|
|
||||||
pub const LIGHT_RANGE: f32 = 90.0;
|
pub const LIGHT_RANGE: f32 = 90.0;
|
||||||
|
|
||||||
|
static BLUE: Color = Color::linear_rgb(0.0, 0.0, 1.0);
|
||||||
|
static PINK: Color = Color::linear_rgb(199.0 / 255.0, 21.0 / 255.0, 113.0 / 255.0);
|
||||||
|
|
||||||
fn spawn_static_lights(
|
fn spawn_static_lights(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut meshes: ResMut<Assets<Mesh>>,
|
mut meshes: ResMut<Assets<Mesh>>,
|
||||||
|
@ -12,7 +15,7 @@ fn spawn_static_lights(
|
||||||
let pink_light = PointLight {
|
let pink_light = PointLight {
|
||||||
intensity: 1_00.0,
|
intensity: 1_00.0,
|
||||||
range: LIGHT_RANGE,
|
range: LIGHT_RANGE,
|
||||||
color: Color::PINK,
|
color: PINK,
|
||||||
radius: 1.0,
|
radius: 1.0,
|
||||||
shadows_enabled: true,
|
shadows_enabled: true,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -21,7 +24,7 @@ fn spawn_static_lights(
|
||||||
let blue_light = PointLight {
|
let blue_light = PointLight {
|
||||||
intensity: 1_000.0,
|
intensity: 1_000.0,
|
||||||
range: LIGHT_RANGE,
|
range: LIGHT_RANGE,
|
||||||
color: Color::BLUE,
|
color: BLUE,
|
||||||
radius: 1.0,
|
radius: 1.0,
|
||||||
shadows_enabled: true,
|
shadows_enabled: true,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -48,16 +51,10 @@ fn spawn_static_lights(
|
||||||
})
|
})
|
||||||
.with_children(|builder| {
|
.with_children(|builder| {
|
||||||
builder.spawn(PbrBundle {
|
builder.spawn(PbrBundle {
|
||||||
mesh: meshes.add(
|
mesh: meshes.add(Mesh::from(Sphere::new(10.0))),
|
||||||
Mesh::try_from(shape::Icosphere {
|
|
||||||
radius: 10.0,
|
|
||||||
subdivisions: 2,
|
|
||||||
})
|
|
||||||
.unwrap(),
|
|
||||||
),
|
|
||||||
material: materials.add(StandardMaterial {
|
material: materials.add(StandardMaterial {
|
||||||
base_color: Color::BLUE,
|
base_color: BLUE,
|
||||||
emissive: Color::PINK,
|
emissive: PINK.into(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -72,16 +69,10 @@ fn spawn_static_lights(
|
||||||
})
|
})
|
||||||
.with_children(|builder| {
|
.with_children(|builder| {
|
||||||
builder.spawn(PbrBundle {
|
builder.spawn(PbrBundle {
|
||||||
mesh: meshes.add(
|
mesh: meshes.add(Mesh::from(Sphere::new(10.0))),
|
||||||
Mesh::try_from(shape::Icosphere {
|
|
||||||
radius: 10.0,
|
|
||||||
subdivisions: 2,
|
|
||||||
})
|
|
||||||
.unwrap(),
|
|
||||||
),
|
|
||||||
material: materials.add(StandardMaterial {
|
material: materials.add(StandardMaterial {
|
||||||
base_color: Color::PINK,
|
base_color: PINK,
|
||||||
emissive: Color::BLUE,
|
emissive: BLUE.into(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -92,6 +83,6 @@ fn spawn_static_lights(
|
||||||
pub struct CyberSpaceLightsPlugin;
|
pub struct CyberSpaceLightsPlugin;
|
||||||
impl Plugin for CyberSpaceLightsPlugin {
|
impl Plugin for CyberSpaceLightsPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_startup_system(spawn_static_lights);
|
app.add_systems(Startup, spawn_static_lights);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
38
src/main.rs
38
src/main.rs
|
@ -8,7 +8,7 @@ use cyber_rider::{
|
||||||
};
|
};
|
||||||
|
|
||||||
//const CYBER_SKY: Color = Color::rgb(0.07, 0.001, 0.02);
|
//const CYBER_SKY: Color = Color::rgb(0.07, 0.001, 0.02);
|
||||||
const CYBER_SKY: Color = Color::rgb(0.64, 0.745, 0.937); // a light blue sky
|
const CYBER_SKY: Color = Color::srgb(0.64, 0.745, 0.937); // a light blue sky
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut app = App::new();
|
let mut app = App::new();
|
||||||
|
@ -21,18 +21,36 @@ fn main() {
|
||||||
}),
|
}),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}))
|
}))
|
||||||
.add_plugin(CyberPlanetPlugin)
|
.add_plugins((
|
||||||
.add_plugin(CyberInputPlugin)
|
CyberPlanetPlugin,
|
||||||
.add_plugin(CyberActionPlugin)
|
CyberInputPlugin,
|
||||||
.add_plugin(CyberCamPlugin)
|
CyberActionPlugin,
|
||||||
.add_plugin(CyberSpaceLightsPlugin)
|
CyberCamPlugin,
|
||||||
.add_plugin(CyberUIPlugin)
|
CyberSpaceLightsPlugin,
|
||||||
.add_plugin(CyberBikePlugin)
|
CyberUIPlugin,
|
||||||
.add_startup_system(disable_mouse_trap)
|
CyberBikePlugin,
|
||||||
.add_system(bevy::window::close_on_esc);
|
))
|
||||||
|
.add_systems(Startup, disable_mouse_trap)
|
||||||
|
.add_systems(Update, close_on_esc);
|
||||||
|
|
||||||
#[cfg(feature = "inspector")]
|
#[cfg(feature = "inspector")]
|
||||||
app.add_plugin(CyberGlamorPlugin);
|
app.add_plugin(CyberGlamorPlugin);
|
||||||
|
|
||||||
app.run();
|
app.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn close_on_esc(
|
||||||
|
mut commands: Commands,
|
||||||
|
focused_windows: Query<(Entity, &Window)>,
|
||||||
|
input: Res<ButtonInput<KeyCode>>,
|
||||||
|
) {
|
||||||
|
for (window, focus) in focused_windows.iter() {
|
||||||
|
if !focus.focused {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.just_pressed(KeyCode::Escape) {
|
||||||
|
commands.entity(window).despawn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue