pub struct Vehicle {Show 25 fields
pub top_speed: f32,
pub reverse_speed: f32,
pub engine_force: f32,
pub brake_force: f32,
pub grip: f32,
pub rolling_resistance: f32,
pub engine_braking: f32,
pub turn_radius: f32,
pub max_turn_rate: f32,
pub gears: u32,
pub idle_rpm: f32,
pub max_rpm: f32,
pub load: f32,
pub max_load: f32,
pub fuel_capacity: Option<f32>,
pub consumption: f32,
pub engine_sound: Option<String>,
pub horn_sound: Option<String>,
pub start_sound: Option<String>,
pub shift_sound: Option<String>,
pub crash_sound: Option<String>,
pub throttle: f32,
pub brake: f32,
pub steer: f32,
pub handbrake: bool,
/* private fields */
}Expand description
The vehicle part of a body: settings, pedals and the driving state.
Settings are public fields with with_* builder methods. Speeds are stored in meters per
second; the builders that take km/h say so in their name.
Fields§
§top_speed: f32Highest forward speed in m/s. The engine gets weaker towards it, so full throttle approaches it slowly.
reverse_speed: f32Highest reverse speed in m/s.
engine_force: f32Driving force of the engine at full throttle in newtons. Acceleration is this divided by the weight.
brake_force: f32Braking force at full brake pedal in newtons. Deceleration is this divided by the weight.
grip: f32Most acceleration or deceleration the tyres can transfer, in m/s². Caps engine, brakes and handbrake. 9 is a car on dry asphalt, 3 is a wet road, 1 is ice.
rolling_resistance: f32Speed lost per second while rolling, in m/s² (tyres, air). Always active.
engine_braking: f32Extra speed lost per second when no pedal is pressed and the engine runs, in m/s².
turn_radius: f32Radius of the tightest circle the vehicle can drive, in meters.
max_turn_rate: f32Fastest the vehicle can turn, in degrees per second.
gears: u32Number of forward gears (at least 1).
idle_rpm: f32Engine speed when idling, in revolutions per minute.
max_rpm: f32Highest engine speed, in revolutions per minute.
load: f32Cargo in kilograms, added to the body’s mass. Change it with Vehicle::set_load to
respect Vehicle::max_load.
max_load: f32Most cargo in kilograms. Default unlimited.
fuel_capacity: Option<f32>Tank size in liters, None (the default) for unlimited fuel.
consumption: f32Fuel use in liters per 100 km at full throttle with an empty vehicle. Light throttle uses less, cargo uses more.
engine_sound: Option<String>Looping engine sound, played at the vehicle while the engine runs. Its pitch follows the engine speed and its volume the throttle.
horn_sound: Option<String>Sound for Context::horn.
start_sound: Option<String>Sound for Context::start_engine.
shift_sound: Option<String>Sound played on every gear change.
crash_sound: Option<String>Sound played when the vehicle crashes into something, louder for harder crashes.
throttle: f32Gas pedal, 0.0 to 1.0. Set it every frame. While reversing it brakes.
brake: f32Brake pedal, 0.0 to 1.0. Set it every frame. Pressed while the vehicle stands still, it drives backwards (after braking to a stop, release it and press it again).
steer: f32Steering wheel, -1.0 (full left) to 1.0 (full right).
handbrake: boolHandbrake: stops the vehicle as hard as the grip allows.
Implementations§
Source§impl Vehicle
impl Vehicle
Sourcepub fn car() -> Self
pub fn car() -> Self
A car: top speed 180 km/h, 0 to 100 km/h in about 10 seconds with
Body::car’s 1300 kg, 5 gears, turns in a 5 m circle.
Examples found in repository?
29 fn new(ctx: &mut Context) -> Self {
30 // Engine: a low buzz that loops without clicks (whole cycles, no fades).
31 let engine = Synth::saw(55.0).length(1.0).attack(0.0).release(0.0).volume(0.25)
32 .with(Synth::square(110.0).length(1.0).attack(0.0).release(0.0).volume(0.08));
33 ctx.audio.register("engine", engine);
34 ctx.audio.register("horn", Synth::square(415.0).length(0.5).volume(0.25).with(Synth::square(523.0).length(0.5).volume(0.2)));
35 ctx.audio.register("shift", Synth::noise().length(0.04).decay(90.0).volume(0.3));
36 ctx.audio.register("crash", Synth::noise().length(0.4).decay(10.0).volume(0.8).with(Synth::sine(80.0).sweep_to(30.0).length(0.3)));
37 ctx.audio.register("start", Synth::saw(40.0).sweep_to(55.0).length(0.6).volume(0.3));
38 ctx.audio.register("garage", Synth::sine(880.0).length(0.15).decay(10.0));
39
40 let level = ctx.physics.build_level(MAP, 6.0);
41 let sounds = |v: Vehicle| {
42 v.with_engine_sound("engine")
43 .with_horn_sound("horn")
44 .with_shift_sound("shift")
45 .with_crash_sound("crash")
46 .with_start_sound("start")
47 };
48 let car_start = level.point('P').unwrap_or(Vec3::ZERO);
49 let car = ctx.physics.add(Body::car(car_start).with_facing(90.0).with_vehicle(sounds(Vehicle::car().with_fuel(5.0, 8.0))));
50 let truck_start = level.point('T').unwrap_or(Vec3::ZERO);
51 let truck = ctx.physics.add(
52 Body::truck(truck_start).with_facing(90.0).with_vehicle(sounds(Vehicle::truck()).engine_off()),
53 );
54 let garage_at = level.point('G').unwrap_or(Vec3::ZERO);
55 let garage = ctx.physics.add(Body::sensor(garage_at).with_box(6.0, 6.0, 3.0).with_tag("garage"));
56 ctx.loop_on(garage, "garage");
57 ctx.follow(car);
58 Self { car, truck, driving: car, garage }
59 }Sourcepub fn truck() -> Self
pub fn truck() -> Self
A truck: top speed 90 km/h, 12 gears, turns in an 11 m circle, carries up to 25 t.
With Body::truck’s 12 t it reaches 60 km/h in about
13 seconds empty and in about 50 seconds fully loaded.
Examples found in repository?
29 fn new(ctx: &mut Context) -> Self {
30 // Engine: a low buzz that loops without clicks (whole cycles, no fades).
31 let engine = Synth::saw(55.0).length(1.0).attack(0.0).release(0.0).volume(0.25)
32 .with(Synth::square(110.0).length(1.0).attack(0.0).release(0.0).volume(0.08));
33 ctx.audio.register("engine", engine);
34 ctx.audio.register("horn", Synth::square(415.0).length(0.5).volume(0.25).with(Synth::square(523.0).length(0.5).volume(0.2)));
35 ctx.audio.register("shift", Synth::noise().length(0.04).decay(90.0).volume(0.3));
36 ctx.audio.register("crash", Synth::noise().length(0.4).decay(10.0).volume(0.8).with(Synth::sine(80.0).sweep_to(30.0).length(0.3)));
37 ctx.audio.register("start", Synth::saw(40.0).sweep_to(55.0).length(0.6).volume(0.3));
38 ctx.audio.register("garage", Synth::sine(880.0).length(0.15).decay(10.0));
39
40 let level = ctx.physics.build_level(MAP, 6.0);
41 let sounds = |v: Vehicle| {
42 v.with_engine_sound("engine")
43 .with_horn_sound("horn")
44 .with_shift_sound("shift")
45 .with_crash_sound("crash")
46 .with_start_sound("start")
47 };
48 let car_start = level.point('P').unwrap_or(Vec3::ZERO);
49 let car = ctx.physics.add(Body::car(car_start).with_facing(90.0).with_vehicle(sounds(Vehicle::car().with_fuel(5.0, 8.0))));
50 let truck_start = level.point('T').unwrap_or(Vec3::ZERO);
51 let truck = ctx.physics.add(
52 Body::truck(truck_start).with_facing(90.0).with_vehicle(sounds(Vehicle::truck()).engine_off()),
53 );
54 let garage_at = level.point('G').unwrap_or(Vec3::ZERO);
55 let garage = ctx.physics.add(Body::sensor(garage_at).with_box(6.0, 6.0, 3.0).with_tag("garage"));
56 ctx.loop_on(garage, "garage");
57 ctx.follow(car);
58 Self { car, truck, driving: car, garage }
59 }Sourcepub fn with_top_speed_kmh(self, kmh: f32) -> Self
pub fn with_top_speed_kmh(self, kmh: f32) -> Self
Sets the top speed in km/h.
Sourcepub fn with_reverse_speed_kmh(self, kmh: f32) -> Self
pub fn with_reverse_speed_kmh(self, kmh: f32) -> Self
Sets the top reverse speed in km/h.
Sourcepub fn with_engine_force(self, newtons: f32) -> Self
pub fn with_engine_force(self, newtons: f32) -> Self
Sets the engine force in newtons (car 4500, truck 20000). More force, faster acceleration.
Sourcepub fn with_brake_force(self, newtons: f32) -> Self
pub fn with_brake_force(self, newtons: f32) -> Self
Sets the brake force in newtons (car 11000, truck 110000).
Sourcepub fn with_rolling_resistance(self, resistance: f32) -> Self
pub fn with_rolling_resistance(self, resistance: f32) -> Self
Sets the rolling resistance in m/s².
Sourcepub fn with_engine_braking(self, braking: f32) -> Self
pub fn with_engine_braking(self, braking: f32) -> Self
Sets the engine braking in m/s² (how fast the vehicle slows down off the gas).
Sourcepub fn with_turn_radius(self, meters: f32) -> Self
pub fn with_turn_radius(self, meters: f32) -> Self
Sets the radius of the tightest circle in meters.
Sourcepub fn with_max_turn_rate(self, degrees_per_second: f32) -> Self
pub fn with_max_turn_rate(self, degrees_per_second: f32) -> Self
Sets the fastest turn rate in degrees per second.
Sourcepub fn with_gears(self, gears: u32, idle_rpm: f32, max_rpm: f32) -> Self
pub fn with_gears(self, gears: u32, idle_rpm: f32, max_rpm: f32) -> Self
Sets the gearbox: number of forward gears, idle and highest engine speed in rpm.
Sourcepub fn with_load(self, kg: f32) -> Self
pub fn with_load(self, kg: f32) -> Self
Sets the cargo in kilograms (limited by Vehicle::max_load).
Sourcepub fn with_max_load(self, kg: f32) -> Self
pub fn with_max_load(self, kg: f32) -> Self
Sets the most cargo in kilograms.
Sourcepub fn with_fuel(self, capacity: f32, liters_per_100km: f32) -> Self
pub fn with_fuel(self, capacity: f32, liters_per_100km: f32) -> Self
Gives the vehicle a tank of capacity liters, starting full, that uses
liters_per_100km at full throttle. Without this, fuel is unlimited.
Examples found in repository?
29 fn new(ctx: &mut Context) -> Self {
30 // Engine: a low buzz that loops without clicks (whole cycles, no fades).
31 let engine = Synth::saw(55.0).length(1.0).attack(0.0).release(0.0).volume(0.25)
32 .with(Synth::square(110.0).length(1.0).attack(0.0).release(0.0).volume(0.08));
33 ctx.audio.register("engine", engine);
34 ctx.audio.register("horn", Synth::square(415.0).length(0.5).volume(0.25).with(Synth::square(523.0).length(0.5).volume(0.2)));
35 ctx.audio.register("shift", Synth::noise().length(0.04).decay(90.0).volume(0.3));
36 ctx.audio.register("crash", Synth::noise().length(0.4).decay(10.0).volume(0.8).with(Synth::sine(80.0).sweep_to(30.0).length(0.3)));
37 ctx.audio.register("start", Synth::saw(40.0).sweep_to(55.0).length(0.6).volume(0.3));
38 ctx.audio.register("garage", Synth::sine(880.0).length(0.15).decay(10.0));
39
40 let level = ctx.physics.build_level(MAP, 6.0);
41 let sounds = |v: Vehicle| {
42 v.with_engine_sound("engine")
43 .with_horn_sound("horn")
44 .with_shift_sound("shift")
45 .with_crash_sound("crash")
46 .with_start_sound("start")
47 };
48 let car_start = level.point('P').unwrap_or(Vec3::ZERO);
49 let car = ctx.physics.add(Body::car(car_start).with_facing(90.0).with_vehicle(sounds(Vehicle::car().with_fuel(5.0, 8.0))));
50 let truck_start = level.point('T').unwrap_or(Vec3::ZERO);
51 let truck = ctx.physics.add(
52 Body::truck(truck_start).with_facing(90.0).with_vehicle(sounds(Vehicle::truck()).engine_off()),
53 );
54 let garage_at = level.point('G').unwrap_or(Vec3::ZERO);
55 let garage = ctx.physics.add(Body::sensor(garage_at).with_box(6.0, 6.0, 3.0).with_tag("garage"));
56 ctx.loop_on(garage, "garage");
57 ctx.follow(car);
58 Self { car, truck, driving: car, garage }
59 }Sourcepub fn with_engine_sound(self, name: impl Into<String>) -> Self
pub fn with_engine_sound(self, name: impl Into<String>) -> Self
Sets the looping engine sound.
Examples found in repository?
29 fn new(ctx: &mut Context) -> Self {
30 // Engine: a low buzz that loops without clicks (whole cycles, no fades).
31 let engine = Synth::saw(55.0).length(1.0).attack(0.0).release(0.0).volume(0.25)
32 .with(Synth::square(110.0).length(1.0).attack(0.0).release(0.0).volume(0.08));
33 ctx.audio.register("engine", engine);
34 ctx.audio.register("horn", Synth::square(415.0).length(0.5).volume(0.25).with(Synth::square(523.0).length(0.5).volume(0.2)));
35 ctx.audio.register("shift", Synth::noise().length(0.04).decay(90.0).volume(0.3));
36 ctx.audio.register("crash", Synth::noise().length(0.4).decay(10.0).volume(0.8).with(Synth::sine(80.0).sweep_to(30.0).length(0.3)));
37 ctx.audio.register("start", Synth::saw(40.0).sweep_to(55.0).length(0.6).volume(0.3));
38 ctx.audio.register("garage", Synth::sine(880.0).length(0.15).decay(10.0));
39
40 let level = ctx.physics.build_level(MAP, 6.0);
41 let sounds = |v: Vehicle| {
42 v.with_engine_sound("engine")
43 .with_horn_sound("horn")
44 .with_shift_sound("shift")
45 .with_crash_sound("crash")
46 .with_start_sound("start")
47 };
48 let car_start = level.point('P').unwrap_or(Vec3::ZERO);
49 let car = ctx.physics.add(Body::car(car_start).with_facing(90.0).with_vehicle(sounds(Vehicle::car().with_fuel(5.0, 8.0))));
50 let truck_start = level.point('T').unwrap_or(Vec3::ZERO);
51 let truck = ctx.physics.add(
52 Body::truck(truck_start).with_facing(90.0).with_vehicle(sounds(Vehicle::truck()).engine_off()),
53 );
54 let garage_at = level.point('G').unwrap_or(Vec3::ZERO);
55 let garage = ctx.physics.add(Body::sensor(garage_at).with_box(6.0, 6.0, 3.0).with_tag("garage"));
56 ctx.loop_on(garage, "garage");
57 ctx.follow(car);
58 Self { car, truck, driving: car, garage }
59 }Sourcepub fn with_horn_sound(self, name: impl Into<String>) -> Self
pub fn with_horn_sound(self, name: impl Into<String>) -> Self
Sets the horn sound.
Examples found in repository?
29 fn new(ctx: &mut Context) -> Self {
30 // Engine: a low buzz that loops without clicks (whole cycles, no fades).
31 let engine = Synth::saw(55.0).length(1.0).attack(0.0).release(0.0).volume(0.25)
32 .with(Synth::square(110.0).length(1.0).attack(0.0).release(0.0).volume(0.08));
33 ctx.audio.register("engine", engine);
34 ctx.audio.register("horn", Synth::square(415.0).length(0.5).volume(0.25).with(Synth::square(523.0).length(0.5).volume(0.2)));
35 ctx.audio.register("shift", Synth::noise().length(0.04).decay(90.0).volume(0.3));
36 ctx.audio.register("crash", Synth::noise().length(0.4).decay(10.0).volume(0.8).with(Synth::sine(80.0).sweep_to(30.0).length(0.3)));
37 ctx.audio.register("start", Synth::saw(40.0).sweep_to(55.0).length(0.6).volume(0.3));
38 ctx.audio.register("garage", Synth::sine(880.0).length(0.15).decay(10.0));
39
40 let level = ctx.physics.build_level(MAP, 6.0);
41 let sounds = |v: Vehicle| {
42 v.with_engine_sound("engine")
43 .with_horn_sound("horn")
44 .with_shift_sound("shift")
45 .with_crash_sound("crash")
46 .with_start_sound("start")
47 };
48 let car_start = level.point('P').unwrap_or(Vec3::ZERO);
49 let car = ctx.physics.add(Body::car(car_start).with_facing(90.0).with_vehicle(sounds(Vehicle::car().with_fuel(5.0, 8.0))));
50 let truck_start = level.point('T').unwrap_or(Vec3::ZERO);
51 let truck = ctx.physics.add(
52 Body::truck(truck_start).with_facing(90.0).with_vehicle(sounds(Vehicle::truck()).engine_off()),
53 );
54 let garage_at = level.point('G').unwrap_or(Vec3::ZERO);
55 let garage = ctx.physics.add(Body::sensor(garage_at).with_box(6.0, 6.0, 3.0).with_tag("garage"));
56 ctx.loop_on(garage, "garage");
57 ctx.follow(car);
58 Self { car, truck, driving: car, garage }
59 }Sourcepub fn with_start_sound(self, name: impl Into<String>) -> Self
pub fn with_start_sound(self, name: impl Into<String>) -> Self
Sets the engine start sound.
Examples found in repository?
29 fn new(ctx: &mut Context) -> Self {
30 // Engine: a low buzz that loops without clicks (whole cycles, no fades).
31 let engine = Synth::saw(55.0).length(1.0).attack(0.0).release(0.0).volume(0.25)
32 .with(Synth::square(110.0).length(1.0).attack(0.0).release(0.0).volume(0.08));
33 ctx.audio.register("engine", engine);
34 ctx.audio.register("horn", Synth::square(415.0).length(0.5).volume(0.25).with(Synth::square(523.0).length(0.5).volume(0.2)));
35 ctx.audio.register("shift", Synth::noise().length(0.04).decay(90.0).volume(0.3));
36 ctx.audio.register("crash", Synth::noise().length(0.4).decay(10.0).volume(0.8).with(Synth::sine(80.0).sweep_to(30.0).length(0.3)));
37 ctx.audio.register("start", Synth::saw(40.0).sweep_to(55.0).length(0.6).volume(0.3));
38 ctx.audio.register("garage", Synth::sine(880.0).length(0.15).decay(10.0));
39
40 let level = ctx.physics.build_level(MAP, 6.0);
41 let sounds = |v: Vehicle| {
42 v.with_engine_sound("engine")
43 .with_horn_sound("horn")
44 .with_shift_sound("shift")
45 .with_crash_sound("crash")
46 .with_start_sound("start")
47 };
48 let car_start = level.point('P').unwrap_or(Vec3::ZERO);
49 let car = ctx.physics.add(Body::car(car_start).with_facing(90.0).with_vehicle(sounds(Vehicle::car().with_fuel(5.0, 8.0))));
50 let truck_start = level.point('T').unwrap_or(Vec3::ZERO);
51 let truck = ctx.physics.add(
52 Body::truck(truck_start).with_facing(90.0).with_vehicle(sounds(Vehicle::truck()).engine_off()),
53 );
54 let garage_at = level.point('G').unwrap_or(Vec3::ZERO);
55 let garage = ctx.physics.add(Body::sensor(garage_at).with_box(6.0, 6.0, 3.0).with_tag("garage"));
56 ctx.loop_on(garage, "garage");
57 ctx.follow(car);
58 Self { car, truck, driving: car, garage }
59 }Sourcepub fn with_shift_sound(self, name: impl Into<String>) -> Self
pub fn with_shift_sound(self, name: impl Into<String>) -> Self
Sets the gear change sound.
Examples found in repository?
29 fn new(ctx: &mut Context) -> Self {
30 // Engine: a low buzz that loops without clicks (whole cycles, no fades).
31 let engine = Synth::saw(55.0).length(1.0).attack(0.0).release(0.0).volume(0.25)
32 .with(Synth::square(110.0).length(1.0).attack(0.0).release(0.0).volume(0.08));
33 ctx.audio.register("engine", engine);
34 ctx.audio.register("horn", Synth::square(415.0).length(0.5).volume(0.25).with(Synth::square(523.0).length(0.5).volume(0.2)));
35 ctx.audio.register("shift", Synth::noise().length(0.04).decay(90.0).volume(0.3));
36 ctx.audio.register("crash", Synth::noise().length(0.4).decay(10.0).volume(0.8).with(Synth::sine(80.0).sweep_to(30.0).length(0.3)));
37 ctx.audio.register("start", Synth::saw(40.0).sweep_to(55.0).length(0.6).volume(0.3));
38 ctx.audio.register("garage", Synth::sine(880.0).length(0.15).decay(10.0));
39
40 let level = ctx.physics.build_level(MAP, 6.0);
41 let sounds = |v: Vehicle| {
42 v.with_engine_sound("engine")
43 .with_horn_sound("horn")
44 .with_shift_sound("shift")
45 .with_crash_sound("crash")
46 .with_start_sound("start")
47 };
48 let car_start = level.point('P').unwrap_or(Vec3::ZERO);
49 let car = ctx.physics.add(Body::car(car_start).with_facing(90.0).with_vehicle(sounds(Vehicle::car().with_fuel(5.0, 8.0))));
50 let truck_start = level.point('T').unwrap_or(Vec3::ZERO);
51 let truck = ctx.physics.add(
52 Body::truck(truck_start).with_facing(90.0).with_vehicle(sounds(Vehicle::truck()).engine_off()),
53 );
54 let garage_at = level.point('G').unwrap_or(Vec3::ZERO);
55 let garage = ctx.physics.add(Body::sensor(garage_at).with_box(6.0, 6.0, 3.0).with_tag("garage"));
56 ctx.loop_on(garage, "garage");
57 ctx.follow(car);
58 Self { car, truck, driving: car, garage }
59 }Sourcepub fn with_crash_sound(self, name: impl Into<String>) -> Self
pub fn with_crash_sound(self, name: impl Into<String>) -> Self
Sets the crash sound.
Examples found in repository?
29 fn new(ctx: &mut Context) -> Self {
30 // Engine: a low buzz that loops without clicks (whole cycles, no fades).
31 let engine = Synth::saw(55.0).length(1.0).attack(0.0).release(0.0).volume(0.25)
32 .with(Synth::square(110.0).length(1.0).attack(0.0).release(0.0).volume(0.08));
33 ctx.audio.register("engine", engine);
34 ctx.audio.register("horn", Synth::square(415.0).length(0.5).volume(0.25).with(Synth::square(523.0).length(0.5).volume(0.2)));
35 ctx.audio.register("shift", Synth::noise().length(0.04).decay(90.0).volume(0.3));
36 ctx.audio.register("crash", Synth::noise().length(0.4).decay(10.0).volume(0.8).with(Synth::sine(80.0).sweep_to(30.0).length(0.3)));
37 ctx.audio.register("start", Synth::saw(40.0).sweep_to(55.0).length(0.6).volume(0.3));
38 ctx.audio.register("garage", Synth::sine(880.0).length(0.15).decay(10.0));
39
40 let level = ctx.physics.build_level(MAP, 6.0);
41 let sounds = |v: Vehicle| {
42 v.with_engine_sound("engine")
43 .with_horn_sound("horn")
44 .with_shift_sound("shift")
45 .with_crash_sound("crash")
46 .with_start_sound("start")
47 };
48 let car_start = level.point('P').unwrap_or(Vec3::ZERO);
49 let car = ctx.physics.add(Body::car(car_start).with_facing(90.0).with_vehicle(sounds(Vehicle::car().with_fuel(5.0, 8.0))));
50 let truck_start = level.point('T').unwrap_or(Vec3::ZERO);
51 let truck = ctx.physics.add(
52 Body::truck(truck_start).with_facing(90.0).with_vehicle(sounds(Vehicle::truck()).engine_off()),
53 );
54 let garage_at = level.point('G').unwrap_or(Vec3::ZERO);
55 let garage = ctx.physics.add(Body::sensor(garage_at).with_box(6.0, 6.0, 3.0).with_tag("garage"));
56 ctx.loop_on(garage, "garage");
57 ctx.follow(car);
58 Self { car, truck, driving: car, garage }
59 }Sourcepub fn engine_off(self) -> Self
pub fn engine_off(self) -> Self
Starts with the engine off. Start it with Vehicle::start_engine or
Context::start_engine.
Examples found in repository?
29 fn new(ctx: &mut Context) -> Self {
30 // Engine: a low buzz that loops without clicks (whole cycles, no fades).
31 let engine = Synth::saw(55.0).length(1.0).attack(0.0).release(0.0).volume(0.25)
32 .with(Synth::square(110.0).length(1.0).attack(0.0).release(0.0).volume(0.08));
33 ctx.audio.register("engine", engine);
34 ctx.audio.register("horn", Synth::square(415.0).length(0.5).volume(0.25).with(Synth::square(523.0).length(0.5).volume(0.2)));
35 ctx.audio.register("shift", Synth::noise().length(0.04).decay(90.0).volume(0.3));
36 ctx.audio.register("crash", Synth::noise().length(0.4).decay(10.0).volume(0.8).with(Synth::sine(80.0).sweep_to(30.0).length(0.3)));
37 ctx.audio.register("start", Synth::saw(40.0).sweep_to(55.0).length(0.6).volume(0.3));
38 ctx.audio.register("garage", Synth::sine(880.0).length(0.15).decay(10.0));
39
40 let level = ctx.physics.build_level(MAP, 6.0);
41 let sounds = |v: Vehicle| {
42 v.with_engine_sound("engine")
43 .with_horn_sound("horn")
44 .with_shift_sound("shift")
45 .with_crash_sound("crash")
46 .with_start_sound("start")
47 };
48 let car_start = level.point('P').unwrap_or(Vec3::ZERO);
49 let car = ctx.physics.add(Body::car(car_start).with_facing(90.0).with_vehicle(sounds(Vehicle::car().with_fuel(5.0, 8.0))));
50 let truck_start = level.point('T').unwrap_or(Vec3::ZERO);
51 let truck = ctx.physics.add(
52 Body::truck(truck_start).with_facing(90.0).with_vehicle(sounds(Vehicle::truck()).engine_off()),
53 );
54 let garage_at = level.point('G').unwrap_or(Vec3::ZERO);
55 let garage = ctx.physics.add(Body::sensor(garage_at).with_box(6.0, 6.0, 3.0).with_tag("garage"));
56 ctx.loop_on(garage, "garage");
57 ctx.follow(car);
58 Self { car, truck, driving: car, garage }
59 }Sourcepub fn speed(&self) -> f32
pub fn speed(&self) -> f32
Speed along the facing in m/s, negative when reversing.
Examples found in repository?
71 fn update(&mut self, ctx: &mut Context) {
72 let id = self.driving;
73 ctx.drive(id);
74
75 if ctx.pressed(Key::H) {
76 ctx.horn(id);
77 }
78 if ctx.pressed(Key::E) {
79 let running = ctx.physics.vehicle(id).is_some_and(|v| v.is_engine_on());
80 if running {
81 ctx.stop_engine(id);
82 ctx.speak("Engine off");
83 } else if !ctx.start_engine(id) {
84 ctx.speak("The tank is empty");
85 }
86 }
87 if ctx.pressed(Key::Tab) {
88 if let Some(v) = ctx.physics.vehicle_mut(id) {
89 v.throttle = 0.0;
90 v.brake = 0.0;
91 v.handbrake = true;
92 }
93 self.driving = if id == self.car { self.truck } else { self.car };
94 ctx.follow(self.driving);
95 let text = format!("You switch to the {}. E starts the engine.", self.name());
96 ctx.speak(text);
97 }
98 if ctx.pressed(Key::L) && self.driving == self.truck {
99 let speed = ctx.physics.vehicle(self.truck).map_or(0.0, |v| v.speed().abs());
100 if speed > 0.5 {
101 ctx.speak("Stop first");
102 } else if let Some(v) = ctx.physics.vehicle_mut(self.truck) {
103 let load = if v.load > 0.0 { 0.0 } else { v.max_load };
104 v.set_load(load);
105 let text = format!("Load {} tons, total weight {} tons", load / 1000.0, ctx.physics.weight(self.truck) / 1000.0);
106 ctx.speak(text);
107 }
108 }
109 if ctx.pressed(Key::F)
110 && let Some(v) = ctx.physics.vehicle(id)
111 {
112 let mut text = format!("{}, gear {}", v.describe_speed(), v.gear_name());
113 if let Some(fuel) = v.fuel() {
114 text.push_str(&format!(", {fuel:.1} liters left"));
115 }
116 ctx.speak(text);
117 }
118 if ctx.pressed(Key::G) {
119 let text = ctx.physics.describe(id, self.garage);
120 ctx.speak(text);
121 }
122 if ctx.pressed(Key::F1) {
123 ctx.speak("Up gas, down brake and reverse, left and right steer, space handbrake, H horn, E engine, Tab switch vehicle, L load the truck, F speed, G garage.");
124 }
125
126 if let Some(gear) = ctx.physics.gear_changed(id)
127 && gear == -1
128 {
129 ctx.speak("Reverse");
130 }
131 if let Some((_, speed)) = ctx.physics.crashed(id)
132 && speed > 5.0
133 {
134 let text = format!("Crash at {:.0} kilometers per hour", speed * 3.6);
135 ctx.speak(text);
136 }
137 if ctx.physics.entered_tag(id, "garage").is_some() {
138 let text = format!("You parked the {} in the garage. Well done!", self.name());
139 ctx.speak(text);
140 ctx.quit();
141 }
142 if ctx.pressed(Key::Escape) {
143 ctx.quit();
144 }
145 }Sourcepub fn set_speed(&mut self, speed: f32)
pub fn set_speed(&mut self, speed: f32)
Sets the speed in m/s, e.g. to start a race already rolling. Limited to the top speeds.
Sourcepub fn describe_speed(&self) -> String
pub fn describe_speed(&self) -> String
The speed ready to speak, e.g. "54 kilometers per hour" (reversing included). Always
English; Lang::describe_speed uses the current
language.
Examples found in repository?
71 fn update(&mut self, ctx: &mut Context) {
72 let id = self.driving;
73 ctx.drive(id);
74
75 if ctx.pressed(Key::H) {
76 ctx.horn(id);
77 }
78 if ctx.pressed(Key::E) {
79 let running = ctx.physics.vehicle(id).is_some_and(|v| v.is_engine_on());
80 if running {
81 ctx.stop_engine(id);
82 ctx.speak("Engine off");
83 } else if !ctx.start_engine(id) {
84 ctx.speak("The tank is empty");
85 }
86 }
87 if ctx.pressed(Key::Tab) {
88 if let Some(v) = ctx.physics.vehicle_mut(id) {
89 v.throttle = 0.0;
90 v.brake = 0.0;
91 v.handbrake = true;
92 }
93 self.driving = if id == self.car { self.truck } else { self.car };
94 ctx.follow(self.driving);
95 let text = format!("You switch to the {}. E starts the engine.", self.name());
96 ctx.speak(text);
97 }
98 if ctx.pressed(Key::L) && self.driving == self.truck {
99 let speed = ctx.physics.vehicle(self.truck).map_or(0.0, |v| v.speed().abs());
100 if speed > 0.5 {
101 ctx.speak("Stop first");
102 } else if let Some(v) = ctx.physics.vehicle_mut(self.truck) {
103 let load = if v.load > 0.0 { 0.0 } else { v.max_load };
104 v.set_load(load);
105 let text = format!("Load {} tons, total weight {} tons", load / 1000.0, ctx.physics.weight(self.truck) / 1000.0);
106 ctx.speak(text);
107 }
108 }
109 if ctx.pressed(Key::F)
110 && let Some(v) = ctx.physics.vehicle(id)
111 {
112 let mut text = format!("{}, gear {}", v.describe_speed(), v.gear_name());
113 if let Some(fuel) = v.fuel() {
114 text.push_str(&format!(", {fuel:.1} liters left"));
115 }
116 ctx.speak(text);
117 }
118 if ctx.pressed(Key::G) {
119 let text = ctx.physics.describe(id, self.garage);
120 ctx.speak(text);
121 }
122 if ctx.pressed(Key::F1) {
123 ctx.speak("Up gas, down brake and reverse, left and right steer, space handbrake, H horn, E engine, Tab switch vehicle, L load the truck, F speed, G garage.");
124 }
125
126 if let Some(gear) = ctx.physics.gear_changed(id)
127 && gear == -1
128 {
129 ctx.speak("Reverse");
130 }
131 if let Some((_, speed)) = ctx.physics.crashed(id)
132 && speed > 5.0
133 {
134 let text = format!("Crash at {:.0} kilometers per hour", speed * 3.6);
135 ctx.speak(text);
136 }
137 if ctx.physics.entered_tag(id, "garage").is_some() {
138 let text = format!("You parked the {} in the garage. Well done!", self.name());
139 ctx.speak(text);
140 ctx.quit();
141 }
142 if ctx.pressed(Key::Escape) {
143 ctx.quit();
144 }
145 }Sourcepub fn is_reversing(&self) -> bool
pub fn is_reversing(&self) -> bool
Whether the vehicle is rolling backwards.
Sourcepub fn gear_name(&self) -> String
pub fn gear_name(&self) -> String
The gear ready to speak: "reverse", "neutral" or the number.
Examples found in repository?
71 fn update(&mut self, ctx: &mut Context) {
72 let id = self.driving;
73 ctx.drive(id);
74
75 if ctx.pressed(Key::H) {
76 ctx.horn(id);
77 }
78 if ctx.pressed(Key::E) {
79 let running = ctx.physics.vehicle(id).is_some_and(|v| v.is_engine_on());
80 if running {
81 ctx.stop_engine(id);
82 ctx.speak("Engine off");
83 } else if !ctx.start_engine(id) {
84 ctx.speak("The tank is empty");
85 }
86 }
87 if ctx.pressed(Key::Tab) {
88 if let Some(v) = ctx.physics.vehicle_mut(id) {
89 v.throttle = 0.0;
90 v.brake = 0.0;
91 v.handbrake = true;
92 }
93 self.driving = if id == self.car { self.truck } else { self.car };
94 ctx.follow(self.driving);
95 let text = format!("You switch to the {}. E starts the engine.", self.name());
96 ctx.speak(text);
97 }
98 if ctx.pressed(Key::L) && self.driving == self.truck {
99 let speed = ctx.physics.vehicle(self.truck).map_or(0.0, |v| v.speed().abs());
100 if speed > 0.5 {
101 ctx.speak("Stop first");
102 } else if let Some(v) = ctx.physics.vehicle_mut(self.truck) {
103 let load = if v.load > 0.0 { 0.0 } else { v.max_load };
104 v.set_load(load);
105 let text = format!("Load {} tons, total weight {} tons", load / 1000.0, ctx.physics.weight(self.truck) / 1000.0);
106 ctx.speak(text);
107 }
108 }
109 if ctx.pressed(Key::F)
110 && let Some(v) = ctx.physics.vehicle(id)
111 {
112 let mut text = format!("{}, gear {}", v.describe_speed(), v.gear_name());
113 if let Some(fuel) = v.fuel() {
114 text.push_str(&format!(", {fuel:.1} liters left"));
115 }
116 ctx.speak(text);
117 }
118 if ctx.pressed(Key::G) {
119 let text = ctx.physics.describe(id, self.garage);
120 ctx.speak(text);
121 }
122 if ctx.pressed(Key::F1) {
123 ctx.speak("Up gas, down brake and reverse, left and right steer, space handbrake, H horn, E engine, Tab switch vehicle, L load the truck, F speed, G garage.");
124 }
125
126 if let Some(gear) = ctx.physics.gear_changed(id)
127 && gear == -1
128 {
129 ctx.speak("Reverse");
130 }
131 if let Some((_, speed)) = ctx.physics.crashed(id)
132 && speed > 5.0
133 {
134 let text = format!("Crash at {:.0} kilometers per hour", speed * 3.6);
135 ctx.speak(text);
136 }
137 if ctx.physics.entered_tag(id, "garage").is_some() {
138 let text = format!("You parked the {} in the garage. Well done!", self.name());
139 ctx.speak(text);
140 ctx.quit();
141 }
142 if ctx.pressed(Key::Escape) {
143 ctx.quit();
144 }
145 }Sourcepub fn rpm_fraction(&self) -> f32
pub fn rpm_fraction(&self) -> f32
Engine speed from 0.0 (idle) to 1.0 (highest rpm).
Sourcepub fn engine_pitch(&self) -> f32
pub fn engine_pitch(&self) -> f32
A playback pitch for a looping engine sound recorded at idle: 0.8 at idle, 2.0 at
the highest rpm. The engine sound set with Vehicle::with_engine_sound uses it
automatically.
Sourcepub fn is_engine_on(&self) -> bool
pub fn is_engine_on(&self) -> bool
Whether the engine runs.
Examples found in repository?
71 fn update(&mut self, ctx: &mut Context) {
72 let id = self.driving;
73 ctx.drive(id);
74
75 if ctx.pressed(Key::H) {
76 ctx.horn(id);
77 }
78 if ctx.pressed(Key::E) {
79 let running = ctx.physics.vehicle(id).is_some_and(|v| v.is_engine_on());
80 if running {
81 ctx.stop_engine(id);
82 ctx.speak("Engine off");
83 } else if !ctx.start_engine(id) {
84 ctx.speak("The tank is empty");
85 }
86 }
87 if ctx.pressed(Key::Tab) {
88 if let Some(v) = ctx.physics.vehicle_mut(id) {
89 v.throttle = 0.0;
90 v.brake = 0.0;
91 v.handbrake = true;
92 }
93 self.driving = if id == self.car { self.truck } else { self.car };
94 ctx.follow(self.driving);
95 let text = format!("You switch to the {}. E starts the engine.", self.name());
96 ctx.speak(text);
97 }
98 if ctx.pressed(Key::L) && self.driving == self.truck {
99 let speed = ctx.physics.vehicle(self.truck).map_or(0.0, |v| v.speed().abs());
100 if speed > 0.5 {
101 ctx.speak("Stop first");
102 } else if let Some(v) = ctx.physics.vehicle_mut(self.truck) {
103 let load = if v.load > 0.0 { 0.0 } else { v.max_load };
104 v.set_load(load);
105 let text = format!("Load {} tons, total weight {} tons", load / 1000.0, ctx.physics.weight(self.truck) / 1000.0);
106 ctx.speak(text);
107 }
108 }
109 if ctx.pressed(Key::F)
110 && let Some(v) = ctx.physics.vehicle(id)
111 {
112 let mut text = format!("{}, gear {}", v.describe_speed(), v.gear_name());
113 if let Some(fuel) = v.fuel() {
114 text.push_str(&format!(", {fuel:.1} liters left"));
115 }
116 ctx.speak(text);
117 }
118 if ctx.pressed(Key::G) {
119 let text = ctx.physics.describe(id, self.garage);
120 ctx.speak(text);
121 }
122 if ctx.pressed(Key::F1) {
123 ctx.speak("Up gas, down brake and reverse, left and right steer, space handbrake, H horn, E engine, Tab switch vehicle, L load the truck, F speed, G garage.");
124 }
125
126 if let Some(gear) = ctx.physics.gear_changed(id)
127 && gear == -1
128 {
129 ctx.speak("Reverse");
130 }
131 if let Some((_, speed)) = ctx.physics.crashed(id)
132 && speed > 5.0
133 {
134 let text = format!("Crash at {:.0} kilometers per hour", speed * 3.6);
135 ctx.speak(text);
136 }
137 if ctx.physics.entered_tag(id, "garage").is_some() {
138 let text = format!("You parked the {} in the garage. Well done!", self.name());
139 ctx.speak(text);
140 ctx.quit();
141 }
142 if ctx.pressed(Key::Escape) {
143 ctx.quit();
144 }
145 }Sourcepub fn start_engine(&mut self) -> bool
pub fn start_engine(&mut self) -> bool
Starts the engine (silently; Context::start_engine
also plays the start sound). Returns false if the tank is empty.
Sourcepub fn stop_engine(&mut self)
pub fn stop_engine(&mut self)
Stops the engine. The vehicle rolls out.
Sourcepub fn fuel(&self) -> Option<f32>
pub fn fuel(&self) -> Option<f32>
Liters left in the tank, None for unlimited fuel.
Examples found in repository?
71 fn update(&mut self, ctx: &mut Context) {
72 let id = self.driving;
73 ctx.drive(id);
74
75 if ctx.pressed(Key::H) {
76 ctx.horn(id);
77 }
78 if ctx.pressed(Key::E) {
79 let running = ctx.physics.vehicle(id).is_some_and(|v| v.is_engine_on());
80 if running {
81 ctx.stop_engine(id);
82 ctx.speak("Engine off");
83 } else if !ctx.start_engine(id) {
84 ctx.speak("The tank is empty");
85 }
86 }
87 if ctx.pressed(Key::Tab) {
88 if let Some(v) = ctx.physics.vehicle_mut(id) {
89 v.throttle = 0.0;
90 v.brake = 0.0;
91 v.handbrake = true;
92 }
93 self.driving = if id == self.car { self.truck } else { self.car };
94 ctx.follow(self.driving);
95 let text = format!("You switch to the {}. E starts the engine.", self.name());
96 ctx.speak(text);
97 }
98 if ctx.pressed(Key::L) && self.driving == self.truck {
99 let speed = ctx.physics.vehicle(self.truck).map_or(0.0, |v| v.speed().abs());
100 if speed > 0.5 {
101 ctx.speak("Stop first");
102 } else if let Some(v) = ctx.physics.vehicle_mut(self.truck) {
103 let load = if v.load > 0.0 { 0.0 } else { v.max_load };
104 v.set_load(load);
105 let text = format!("Load {} tons, total weight {} tons", load / 1000.0, ctx.physics.weight(self.truck) / 1000.0);
106 ctx.speak(text);
107 }
108 }
109 if ctx.pressed(Key::F)
110 && let Some(v) = ctx.physics.vehicle(id)
111 {
112 let mut text = format!("{}, gear {}", v.describe_speed(), v.gear_name());
113 if let Some(fuel) = v.fuel() {
114 text.push_str(&format!(", {fuel:.1} liters left"));
115 }
116 ctx.speak(text);
117 }
118 if ctx.pressed(Key::G) {
119 let text = ctx.physics.describe(id, self.garage);
120 ctx.speak(text);
121 }
122 if ctx.pressed(Key::F1) {
123 ctx.speak("Up gas, down brake and reverse, left and right steer, space handbrake, H horn, E engine, Tab switch vehicle, L load the truck, F speed, G garage.");
124 }
125
126 if let Some(gear) = ctx.physics.gear_changed(id)
127 && gear == -1
128 {
129 ctx.speak("Reverse");
130 }
131 if let Some((_, speed)) = ctx.physics.crashed(id)
132 && speed > 5.0
133 {
134 let text = format!("Crash at {:.0} kilometers per hour", speed * 3.6);
135 ctx.speak(text);
136 }
137 if ctx.physics.entered_tag(id, "garage").is_some() {
138 let text = format!("You parked the {} in the garage. Well done!", self.name());
139 ctx.speak(text);
140 ctx.quit();
141 }
142 if ctx.pressed(Key::Escape) {
143 ctx.quit();
144 }
145 }Sourcepub fn fuel_fraction(&self) -> f32
pub fn fuel_fraction(&self) -> f32
Tank level from 0.0 (empty) to 1.0 (full); always 1.0 for unlimited fuel.
Sourcepub fn is_out_of_fuel(&self) -> bool
pub fn is_out_of_fuel(&self) -> bool
Whether the tank is empty (never with unlimited fuel).
Sourcepub fn refuel(&mut self, liters: f32) -> f32
pub fn refuel(&mut self, liters: f32) -> f32
Adds fuel in liters, up to the tank size. Returns how much was added.
Sourcepub fn set_load(&mut self, kg: f32) -> f32
pub fn set_load(&mut self, kg: f32) -> f32
Sets the cargo in kilograms, limited to 0..=Vehicle::max_load. Returns the new
load.
Examples found in repository?
71 fn update(&mut self, ctx: &mut Context) {
72 let id = self.driving;
73 ctx.drive(id);
74
75 if ctx.pressed(Key::H) {
76 ctx.horn(id);
77 }
78 if ctx.pressed(Key::E) {
79 let running = ctx.physics.vehicle(id).is_some_and(|v| v.is_engine_on());
80 if running {
81 ctx.stop_engine(id);
82 ctx.speak("Engine off");
83 } else if !ctx.start_engine(id) {
84 ctx.speak("The tank is empty");
85 }
86 }
87 if ctx.pressed(Key::Tab) {
88 if let Some(v) = ctx.physics.vehicle_mut(id) {
89 v.throttle = 0.0;
90 v.brake = 0.0;
91 v.handbrake = true;
92 }
93 self.driving = if id == self.car { self.truck } else { self.car };
94 ctx.follow(self.driving);
95 let text = format!("You switch to the {}. E starts the engine.", self.name());
96 ctx.speak(text);
97 }
98 if ctx.pressed(Key::L) && self.driving == self.truck {
99 let speed = ctx.physics.vehicle(self.truck).map_or(0.0, |v| v.speed().abs());
100 if speed > 0.5 {
101 ctx.speak("Stop first");
102 } else if let Some(v) = ctx.physics.vehicle_mut(self.truck) {
103 let load = if v.load > 0.0 { 0.0 } else { v.max_load };
104 v.set_load(load);
105 let text = format!("Load {} tons, total weight {} tons", load / 1000.0, ctx.physics.weight(self.truck) / 1000.0);
106 ctx.speak(text);
107 }
108 }
109 if ctx.pressed(Key::F)
110 && let Some(v) = ctx.physics.vehicle(id)
111 {
112 let mut text = format!("{}, gear {}", v.describe_speed(), v.gear_name());
113 if let Some(fuel) = v.fuel() {
114 text.push_str(&format!(", {fuel:.1} liters left"));
115 }
116 ctx.speak(text);
117 }
118 if ctx.pressed(Key::G) {
119 let text = ctx.physics.describe(id, self.garage);
120 ctx.speak(text);
121 }
122 if ctx.pressed(Key::F1) {
123 ctx.speak("Up gas, down brake and reverse, left and right steer, space handbrake, H horn, E engine, Tab switch vehicle, L load the truck, F speed, G garage.");
124 }
125
126 if let Some(gear) = ctx.physics.gear_changed(id)
127 && gear == -1
128 {
129 ctx.speak("Reverse");
130 }
131 if let Some((_, speed)) = ctx.physics.crashed(id)
132 && speed > 5.0
133 {
134 let text = format!("Crash at {:.0} kilometers per hour", speed * 3.6);
135 ctx.speak(text);
136 }
137 if ctx.physics.entered_tag(id, "garage").is_some() {
138 let text = format!("You parked the {} in the garage. Well done!", self.name());
139 ctx.speak(text);
140 ctx.quit();
141 }
142 if ctx.pressed(Key::Escape) {
143 ctx.quit();
144 }
145 }Trait Implementations§
impl StructuralPartialEq for Vehicle
Auto Trait Implementations§
impl Freeze for Vehicle
impl RefUnwindSafe for Vehicle
impl Send for Vehicle
impl Sync for Vehicle
impl Unpin for Vehicle
impl UnsafeUnpin for Vehicle
impl UnwindSafe for Vehicle
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.