diff --git a/src/bike.rs b/src/bike.rs index d695ef3..9def5f6 100644 --- a/src/bike.rs +++ b/src/bike.rs @@ -6,15 +6,19 @@ use avian3d::{ TransformInterpolation, }, }; -use bevy::prelude::{ - children, AlphaMode, App, Assets, Capsule3d, Color, Commands, Component, Dir3, EntityCommands, - Mesh, Mesh3d, MeshMaterial3d, Name, Plugin, Reflect, ResMut, SpawnRelated, Sphere, - StandardMaterial, Startup, Transform, Vec3, Visibility, +use bevy::{ + asset::Handle, + ecs::{bundle::Bundle, entity::Entity}, + prelude::{ + children, AlphaMode, App, Assets, Capsule3d, Color, Commands, Component, Dir3, Mesh, + Mesh3d, MeshMaterial3d, Name, Plugin, Reflect, ResMut, SpawnRelated, Sphere, + StandardMaterial, Startup, Transform, Vec3, Visibility, + }, }; use crate::physics::CatControllerState; -pub const SPRING_CONSTANT: Scalar = 60.0; +pub const SPRING_CONSTANT: Scalar = 50.0; pub const DAMPING_CONSTANT: Scalar = 10.0; pub const WHEEL_RADIUS: Scalar = 0.4; pub const REST_DISTANCE: Scalar = 1.5 + WHEEL_RADIUS; @@ -97,87 +101,96 @@ fn spawn_bike( SleepingDisabled, CyberBikeBody, CatControllerState::default(), - ColliderDensity(1.2), + ColliderDensity(1.4), AngularDamping(0.2), LinearDamping(0.1), ExternalForce::ZERO.with_persistence(false), ExternalTorque::ZERO.with_persistence(false), )); - let color = Color::srgb(0.7, 0.05, 0.7); - let mut xform = Transform::default(); - xform.rotate_x(FRAC_PI_2); - let pbr_bundle = ( - Mesh3d(meshes.add(Capsule3d::new(0.5, 1.45))), - xform, - MeshMaterial3d(materials.add(color)), - ); - - body.insert(children![pbr_bundle]); - - spawn_wheels(&mut body, meshes, materials); + let pbr_bundle = { + let color = Color::srgb(0.7, 0.05, 0.7); + let mut xform = Transform::default(); + xform.rotate_x(FRAC_PI_2); + ( + Mesh3d(meshes.add(Capsule3d::new(0.5, 1.45))), + xform, + Visibility::Visible, + MeshMaterial3d(materials.add(color)), + TransformInterpolation, + ) + }; + let parent = body.id(); + body.insert(spawn_children(parent, pbr_bundle, meshes, materials)); } -fn spawn_wheels( - commands: &mut EntityCommands, +fn spawn_children( + parent: Entity, + body: impl Bundle, mut meshes: ResMut>, mut materials: ResMut>, -) { +) -> impl Bundle { let mesh: Mesh = Sphere::new(WHEEL_RADIUS).into(); + let wheel_material = StandardMaterial { + base_color: Color::srgb(0.01, 0.01, 0.01), + alpha_mode: AlphaMode::Opaque, + perceptual_roughness: 0.5, + ..Default::default() + }; + + let mesh = meshes.add(mesh); + let material = materials.add(wheel_material); let front_rake = Vec3::new(0.0, -1.0, -0.9).normalize(); // about 30 degrees let front_wheel_pos = FRONT_ATTACH + (front_rake * REST_DISTANCE); - - wheel_caster( - commands, - FRONT_ATTACH, - Dir3::new_unchecked(front_rake), - REST_DISTANCE, - CyberWheel::Front, - ); - wheel_mesh( - commands, - &mut meshes, - &mut materials, - front_wheel_pos, - mesh.clone(), - WheelConfig::new( - FRONT_ATTACH, - REST_DISTANCE, - SPRING_CONSTANT, - DAMPING_CONSTANT, - FRICTION_COEFF, - WHEEL_RADIUS, - ), - CyberWheel::Front, - ); - let rear_rake = Vec3::new(0.0, -1.0, 0.9).normalize(); let rear_wheel_pos = REAR_ATTACH + (rear_rake * REST_DISTANCE); - wheel_caster( - commands, - REAR_ATTACH, - Dir3::new_unchecked(rear_rake), - REST_DISTANCE, - CyberWheel::Rear, - ); - wheel_mesh( - commands, - &mut meshes, - &mut materials, - rear_wheel_pos, - mesh, - WheelConfig::new( - REAR_ATTACH, + children!( + body, + wheel_caster( + parent, + FRONT_ATTACH, + Dir3::new_unchecked(front_rake), REST_DISTANCE, - SPRING_CONSTANT, - DAMPING_CONSTANT, - FRICTION_COEFF, - WHEEL_RADIUS, + CyberWheel::Front, ), - CyberWheel::Rear, - ); + wheel_mesh( + mesh.clone(), + material.clone(), + front_wheel_pos, + WheelConfig::new( + FRONT_ATTACH, + REST_DISTANCE, + SPRING_CONSTANT, + DAMPING_CONSTANT, + FRICTION_COEFF, + WHEEL_RADIUS, + ), + CyberWheel::Front, + ), + wheel_caster( + parent, + REAR_ATTACH, + Dir3::new_unchecked(rear_rake), + REST_DISTANCE, + CyberWheel::Rear, + ), + wheel_mesh( + mesh, + material, + rear_wheel_pos, + WheelConfig::new( + REAR_ATTACH, + REST_DISTANCE, + SPRING_CONSTANT, + DAMPING_CONSTANT, + FRICTION_COEFF, + WHEEL_RADIUS, + ), + CyberWheel::Rear, + ), + ) } //-************************************************************************ @@ -185,36 +198,27 @@ fn spawn_wheels( //-************************************************************************ fn wheel_caster( - commands: &mut EntityCommands, + parent: Entity, origin: Vec3, direction: Dir3, rest_dist: Scalar, wheel: CyberWheel, -) { +) -> impl Bundle { let caster = RayCaster::new(origin, direction) .with_max_distance(rest_dist) .with_max_hits(1) - .with_query_filter(SpatialQueryFilter::from_excluded_entities([commands.id()])); + .with_query_filter(SpatialQueryFilter::from_excluded_entities([parent])); - commands.insert(children![(caster, wheel)]); + (caster, wheel) } fn wheel_mesh( - commands: &mut EntityCommands, - meshes: &mut ResMut>, - materials: &mut ResMut>, + mesh: Handle, + material: Handle, position: Vec3, - tire_mesh: Mesh, config: WheelConfig, wheel: CyberWheel, -) { - let wheel_material = &StandardMaterial { - base_color: Color::srgb(0.01, 0.01, 0.01), - alpha_mode: AlphaMode::Opaque, - perceptual_roughness: 0.5, - ..Default::default() - }; - +) -> impl Bundle { let xform = Transform::from_translation(position); let name = match wheel { @@ -222,18 +226,18 @@ fn wheel_mesh( CyberWheel::Rear => "rear tire", }; - commands.insert(children![( + ( Name::new(name), config, - Mesh3d(meshes.add(tire_mesh)), - MeshMaterial3d(materials.add(wheel_material.clone())), + Mesh3d(mesh), + MeshMaterial3d(material), xform, Collider::sphere(WHEEL_RADIUS), ColliderDensity(0.5), CollisionLayers::NONE, TransformInterpolation, wheel, - )]); + ) } pub struct CyberBikePlugin;