pub struct World { /* private fields */ }Expand description
The physics world. Reach it through ctx.physics.
Implementations§
Source§impl World
impl World
Sourcepub fn build_level(&mut self, map: &str, tile_size: f32) -> Level
pub fn build_level(&mut self, map: &str, tile_size: f32) -> Level
Creates walls from a text map. See the level module.
Examples found in repository?
32 fn new(ctx: &mut Context) -> Self {
33 ctx.audio.register("step", Synth::noise().length(0.08).decay(60.0));
34 ctx.audio.register("wall", Synth::sine(90.0).length(0.15).decay(25.0).volume(0.8));
35 ctx.audio.register("beacon", Synth::sine(1320.0).length(0.08).then(Synth::silence(0.04)).then(Synth::sine(1320.0).length(0.08)).then(Synth::silence(0.8)));
36 ctx.audio.register("found", Synth::sine(440.0).sweep_to(1200.0).length(0.6).decay(4.0).volume(0.3));
37
38 // Every character is a 2 meter tile: walls, the player start and three beacons.
39 let level = ctx.physics.build_level(MAP, 2.0);
40 let player = ctx.physics.add(Body::kinematic(level.point('P').unwrap()).with_sphere(0.4).with_tag("player"));
41 ctx.follow(player); // the ears go wherever the player goes and face where it faces
42
43 let mut beacons = Vec::new();
44 for spot in level.points('B') {
45 let beacon = ctx.physics.add(Body::sensor(spot).with_sphere(0.8).with_tag("beacon"));
46 ctx.loop_on(beacon, "beacon"); // stops by itself when the beacon is removed
47 beacons.push(beacon);
48 }
49 Self { player, beacons, clock: Timer::new() }
50 }More examples
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 }Source§impl World
impl World
Sourcepub fn set_gravity(&mut self, gravity: Vec3)
pub fn set_gravity(&mut self, gravity: Vec3)
Sets gravity, e.g. EARTH_GRAVITY. Default is no gravity, which suits top down
games. Also available as Engine::gravity.
Sourcepub fn add(&mut self, body: Body) -> BodyId
pub fn add(&mut self, body: Body) -> BodyId
Adds a body and returns its id.
Examples found in repository?
32 fn new(ctx: &mut Context) -> Self {
33 ctx.audio.register("step", Synth::noise().length(0.08).decay(60.0));
34 ctx.audio.register("wall", Synth::sine(90.0).length(0.15).decay(25.0).volume(0.8));
35 ctx.audio.register("beacon", Synth::sine(1320.0).length(0.08).then(Synth::silence(0.04)).then(Synth::sine(1320.0).length(0.08)).then(Synth::silence(0.8)));
36 ctx.audio.register("found", Synth::sine(440.0).sweep_to(1200.0).length(0.6).decay(4.0).volume(0.3));
37
38 // Every character is a 2 meter tile: walls, the player start and three beacons.
39 let level = ctx.physics.build_level(MAP, 2.0);
40 let player = ctx.physics.add(Body::kinematic(level.point('P').unwrap()).with_sphere(0.4).with_tag("player"));
41 ctx.follow(player); // the ears go wherever the player goes and face where it faces
42
43 let mut beacons = Vec::new();
44 for spot in level.points('B') {
45 let beacon = ctx.physics.add(Body::sensor(spot).with_sphere(0.8).with_tag("beacon"));
46 ctx.loop_on(beacon, "beacon"); // stops by itself when the beacon is removed
47 beacons.push(beacon);
48 }
49 Self { player, beacons, clock: Timer::new() }
50 }More examples
31 fn new(ctx: &mut Context) -> Self {
32 ctx.audio.register("bird", Synth::sine(2200.0).sweep_to(3200.0).length(0.07).then(Synth::silence(0.05)).then(Synth::sine(2600.0).length(0.06)).then(Synth::silence(0.7)));
33 ctx.audio.register("hum", Synth::saw(70.0).length(1.0).volume(0.08));
34 ctx.audio.register("bump", Synth::sine(80.0).length(0.15).decay(25.0).volume(0.8));
35 ctx.audio.register("found", Synth::triangle(660.0).sweep_to(1320.0).length(0.4).decay(6.0).volume(0.3));
36
37 // A hall of 40 x 40 meters and 16 meters high: floor, roof and four walls.
38 // A box is given by its center and its full width (x), depth (y) and height (z).
39 let physics = &mut ctx.physics;
40 physics.add(Body::fixed(vec3(0.0, 0.0, -0.5)).with_box(40.0, 40.0, 1.0).with_tag("floor"));
41 physics.add(Body::fixed(vec3(0.0, 0.0, 16.5)).with_box(40.0, 40.0, 1.0).with_tag("roof"));
42 physics.add(Body::fixed(vec3(0.0, 20.5, 8.0)).with_box(40.0, 1.0, 16.0).with_tag("north wall"));
43 physics.add(Body::fixed(vec3(0.0, -20.5, 8.0)).with_box(40.0, 1.0, 16.0).with_tag("south wall"));
44 physics.add(Body::fixed(vec3(20.5, 0.0, 8.0)).with_box(1.0, 40.0, 16.0).with_tag("east wall"));
45 physics.add(Body::fixed(vec3(-20.5, 0.0, 8.0)).with_box(1.0, 40.0, 16.0).with_tag("west wall"));
46
47 // The drone starts in the middle, 2 meters above the floor. No gravity: it hovers.
48 let drone = ctx.physics.add(Body::kinematic(vec3(0.0, 0.0, 2.0)).with_sphere(0.5).with_tag("drone"));
49 ctx.follow(drone); // the ears use the drone's position, facing and pitch
50 ctx.audio.play_looped("hum");
51
52 for spot in BIRDS {
53 let bird = ctx.physics.add(Body::sensor(spot).with_sphere(1.0).with_tag("bird"));
54 ctx.loop_on(bird, "bird");
55 }
56 Self { drone, birds: BIRDS.len(), blocked: false }
57 }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 }19 fn new(ctx: &mut Context) -> Self {
20 let audio = &mut ctx.audio;
21 audio.register("jump", Synth::square(300.0).sweep_to(700.0).length(0.15).decay(10.0).volume(0.2));
22 audio.register("land", Synth::noise().length(0.1).decay(40.0).with(Synth::sine(90.0).length(0.1).decay(30.0)));
23 audio.register("coin", Synth::triangle(988.0).length(0.08).then(Synth::triangle(1319.0).length(0.17).decay(15.0)));
24 audio.register("run", Synth::noise().length(0.06).decay(60.0).volume(0.3).then(Synth::silence(0.09)));
25 audio.register("lift", Synth::saw(55.0).length(1.0).volume(0.1));
26 audio.register("push", Synth::noise().length(0.3).volume(0.15));
27
28 let physics = &mut ctx.physics;
29 physics.add(Body::fixed(vec3(0.0, 0.0, -0.5)).with_box(200.0, 4.0, 1.0).with_tag("ground"));
30 for (x, z) in [(8.0, 2.0), (14.0, 4.0), (20.0, 2.5)] {
31 physics.add(Body::fixed(vec3(x, 0.0, z)).with_box(4.0, 4.0, 0.5).with_tag("platform"));
32 }
33 // A lift going up and down at x = 40, and a heavy crate at x = 30.
34 let lift = physics.add(Body::kinematic(vec3(40.0, 0.0, 0.0)).with_box(3.0, 4.0, 0.5).with_tag("lift"));
35 physics.add(Body::dynamic(vec3(30.0, 0.0, 0.5)).with_box(1.0, 1.0, 1.0).with_mass(5.0).with_tag("crate"));
36 // Facing north, so x maps to left and right in the ears.
37 let player = physics
38 .add(Body::dynamic(vec3(0.0, 0.0, 1.0)).with_box(0.8, 0.8, 1.6).with_max_speed(25.0).with_tag("player"));
39
40 ctx.follow(player);
41 ctx.loop_on(lift, "lift");
42 // Coins are sensors with a looping sound, so you can hear where they are.
43 for (x, z) in [(5.0, 1.0), (14.0, 5.5), (25.0, 1.0), (40.0, 8.0)] {
44 let coin = ctx.physics.add(Body::sensor(vec3(x, 0.0, z)).with_sphere(0.6).with_tag("coin"));
45 ctx.loop_on(coin, "coin").set_volume(0.3);
46 }
47
48 let run_sound = ctx.audio.sound("run").looped().volume(0.0).play();
49 Self { player, lift, run_sound, score: 0 }
50 }Sourcepub fn remove(&mut self, id: BodyId) -> Option<Body>
pub fn remove(&mut self, id: BodyId) -> Option<Body>
Removes a body. Returns it if it existed.
Examples found in repository?
58 fn update(&mut self, ctx: &mut Context) {
59 if ctx.pressed(Key::Escape) {
60 ctx.quit();
61 }
62
63 // The lift goes up for 4 seconds and down for 4 seconds.
64 let lift_up = (ctx.time.elapsed() % 8.0) < 4.0;
65 ctx.physics.set_velocity(self.lift, vec3(0.0, 0.0, if lift_up { 2.0 } else { -2.0 }));
66
67 let run = ctx.input.axis(Key::Left, Key::Right);
68 let mut velocity = ctx.physics.velocity(self.player);
69 velocity.x = run * 6.0;
70 ctx.physics.set_velocity(self.player, velocity);
71 if ctx.pressed(Key::Space) && ctx.physics.jump(self.player, 2.5) {
72 ctx.play("jump");
73 }
74 let running = ctx.physics.on_ground(self.player) && run != 0.0;
75 self.run_sound.set_volume(if running { 0.6 } else { 0.0 });
76
77 if let Some(speed) = ctx.physics.landed(self.player) {
78 ctx.audio.sound("land").volume((speed / 12.0).clamp(0.2, 1.0)).play();
79 if speed > 15.0 {
80 ctx.speak("Ouch!");
81 }
82 }
83 if let Some((other, _)) = ctx.physics.collided(self.player)
84 && ctx.physics.tag(other) == "crate"
85 {
86 ctx.play_on(other, "push");
87 }
88 if let Some(coin) = ctx.physics.entered_tag(self.player, "coin") {
89 ctx.physics.remove(coin); // its looping sound stops by itself
90 self.score += 1;
91 ctx.audio.sound("coin").pitch(1.5).play();
92 ctx.speak(format!("{} of {COINS} coins", self.score));
93 if self.score == COINS {
94 ctx.ui.message("won", "You collected every coin! Press enter to quit.");
95 }
96 }
97 if ctx.ui.closed("won") {
98 ctx.quit();
99 }
100
101 if ctx.pressed(Key::S) {
102 let x = ctx.physics.position(self.player).x;
103 ctx.speak(format!("Score {}, position {x:.0}", self.score));
104 }
105 }More examples
58 fn update(&mut self, ctx: &mut Context) {
59 if ctx.pressed(Key::Escape) {
60 ctx.push_scene(Pause);
61 }
62 if ctx.pressed(Key::Left) || ctx.pressed(Key::Right) {
63 let degrees = if ctx.pressed(Key::Left) { -45.0 } else { 45.0 };
64 let facing = ctx.physics.turn(self.player, degrees);
65 ctx.speak(math::direction_name(facing));
66 }
67
68 let forward = ctx.input.repeating(Key::Up, 0.35, 0.35);
69 let backward = ctx.input.repeating(Key::Down, 0.35, 0.35);
70 if forward || backward {
71 let step = if forward { 1.0 } else { -1.0 };
72 if ctx.physics.move_forward(self.player, step).blocked {
73 ctx.play("wall");
74 } else {
75 ctx.audio.sound("step").random_pitch(0.85, 1.15).play();
76 }
77 }
78
79 if ctx.pressed(Key::C) {
80 let position = ctx.physics.position(self.player);
81 match ctx.physics.nearest_with_tag(position, "beacon") {
82 Some(beacon) => {
83 let text = ctx.physics.describe(self.player, beacon);
84 ctx.speak(text);
85 }
86 None => ctx.speak("No beacons left"),
87 }
88 }
89 if ctx.pressed(Key::F) {
90 let facing = ctx.physics.facing(self.player);
91 ctx.speak(format!("Facing {}", math::direction_name(facing)));
92 }
93
94 if let Some(beacon) = ctx.physics.entered_tag(self.player, "beacon") {
95 ctx.physics.remove(beacon);
96 self.beacons.retain(|b| *b != beacon);
97 ctx.play("found");
98 if self.beacons.is_empty() {
99 self.finish(ctx);
100 } else {
101 ctx.speak(format!("Beacon found! {} left.", self.beacons.len()));
102 }
103 }
104 if ctx.ui.closed("done") {
105 ctx.quit();
106 }
107 }75 fn update(&mut self, ctx: &mut Context) {
76 if ctx.pressed(Key::Escape) {
77 ctx.quit();
78 }
79 if ctx.pressed(Key::Left) || ctx.pressed(Key::Right) {
80 let facing = ctx.physics.turn(self.drone, if ctx.pressed(Key::Left) { -30.0 } else { 30.0 });
81 ctx.speak(math::direction_name(facing));
82 }
83 if ctx.pressed(Key::PageUp) || ctx.pressed(Key::PageDown) {
84 let pitch = ctx.physics.tilt(self.drone, if ctx.pressed(Key::PageUp) { 30.0 } else { -30.0 });
85 ctx.speak(describe_pitch(pitch));
86 }
87
88 // Smooth flight: 4 meters per second while a key is held.
89 let speed = 4.0 * ctx.time.delta();
90 let forward = ctx.input.axis(Key::Down, Key::Up);
91 if forward != 0.0 {
92 let result = ctx.physics.move_forward(self.drone, forward * speed);
93 self.fly(ctx, result);
94 }
95 let rise = ctx.input.axis(Key::Q, Key::E);
96 if rise != 0.0 {
97 let result = ctx.physics.move_up(self.drone, rise * speed);
98 self.fly(ctx, result);
99 }
100
101 if ctx.pressed(Key::C) {
102 let position = ctx.physics.position(self.drone);
103 match ctx.physics.nearest_with_tag(position, "bird") {
104 Some(bird) => {
105 let text = ctx.physics.describe(self.drone, bird); // e.g. "2 o'clock, 9 meters, 6 meters above"
106 ctx.speak(text);
107 }
108 None => ctx.speak("No birds left"),
109 }
110 }
111 if ctx.pressed(Key::F) {
112 let (facing, pitch) = (ctx.physics.facing(self.drone), ctx.physics.pitch(self.drone));
113 ctx.speak(format!("Facing {}, {}", math::direction_name(facing), describe_pitch(pitch)));
114 }
115 if ctx.pressed(Key::H) {
116 let height = ctx.physics.position(self.drone).z;
117 ctx.speak(format!("{height:.0} meters high"));
118 }
119
120 if let Some(bird) = ctx.physics.entered_tag(self.drone, "bird") {
121 ctx.physics.remove(bird);
122 self.birds -= 1;
123 ctx.play("found");
124 if self.birds == 0 {
125 ctx.ui.message("done", "You found every bird!");
126 } else {
127 ctx.speak(format!("Bird found! {} left.", self.birds));
128 }
129 }
130 if ctx.ui.closed("done") {
131 ctx.quit();
132 }
133 }Sourcepub fn position(&self, id: BodyId) -> Vec3
pub fn position(&self, id: BodyId) -> Vec3
Position of a body (zero if it does not exist).
Examples found in repository?
58 fn update(&mut self, ctx: &mut Context) {
59 if ctx.pressed(Key::Escape) {
60 ctx.quit();
61 }
62
63 // The lift goes up for 4 seconds and down for 4 seconds.
64 let lift_up = (ctx.time.elapsed() % 8.0) < 4.0;
65 ctx.physics.set_velocity(self.lift, vec3(0.0, 0.0, if lift_up { 2.0 } else { -2.0 }));
66
67 let run = ctx.input.axis(Key::Left, Key::Right);
68 let mut velocity = ctx.physics.velocity(self.player);
69 velocity.x = run * 6.0;
70 ctx.physics.set_velocity(self.player, velocity);
71 if ctx.pressed(Key::Space) && ctx.physics.jump(self.player, 2.5) {
72 ctx.play("jump");
73 }
74 let running = ctx.physics.on_ground(self.player) && run != 0.0;
75 self.run_sound.set_volume(if running { 0.6 } else { 0.0 });
76
77 if let Some(speed) = ctx.physics.landed(self.player) {
78 ctx.audio.sound("land").volume((speed / 12.0).clamp(0.2, 1.0)).play();
79 if speed > 15.0 {
80 ctx.speak("Ouch!");
81 }
82 }
83 if let Some((other, _)) = ctx.physics.collided(self.player)
84 && ctx.physics.tag(other) == "crate"
85 {
86 ctx.play_on(other, "push");
87 }
88 if let Some(coin) = ctx.physics.entered_tag(self.player, "coin") {
89 ctx.physics.remove(coin); // its looping sound stops by itself
90 self.score += 1;
91 ctx.audio.sound("coin").pitch(1.5).play();
92 ctx.speak(format!("{} of {COINS} coins", self.score));
93 if self.score == COINS {
94 ctx.ui.message("won", "You collected every coin! Press enter to quit.");
95 }
96 }
97 if ctx.ui.closed("won") {
98 ctx.quit();
99 }
100
101 if ctx.pressed(Key::S) {
102 let x = ctx.physics.position(self.player).x;
103 ctx.speak(format!("Score {}, position {x:.0}", self.score));
104 }
105 }More examples
58 fn update(&mut self, ctx: &mut Context) {
59 if ctx.pressed(Key::Escape) {
60 ctx.push_scene(Pause);
61 }
62 if ctx.pressed(Key::Left) || ctx.pressed(Key::Right) {
63 let degrees = if ctx.pressed(Key::Left) { -45.0 } else { 45.0 };
64 let facing = ctx.physics.turn(self.player, degrees);
65 ctx.speak(math::direction_name(facing));
66 }
67
68 let forward = ctx.input.repeating(Key::Up, 0.35, 0.35);
69 let backward = ctx.input.repeating(Key::Down, 0.35, 0.35);
70 if forward || backward {
71 let step = if forward { 1.0 } else { -1.0 };
72 if ctx.physics.move_forward(self.player, step).blocked {
73 ctx.play("wall");
74 } else {
75 ctx.audio.sound("step").random_pitch(0.85, 1.15).play();
76 }
77 }
78
79 if ctx.pressed(Key::C) {
80 let position = ctx.physics.position(self.player);
81 match ctx.physics.nearest_with_tag(position, "beacon") {
82 Some(beacon) => {
83 let text = ctx.physics.describe(self.player, beacon);
84 ctx.speak(text);
85 }
86 None => ctx.speak("No beacons left"),
87 }
88 }
89 if ctx.pressed(Key::F) {
90 let facing = ctx.physics.facing(self.player);
91 ctx.speak(format!("Facing {}", math::direction_name(facing)));
92 }
93
94 if let Some(beacon) = ctx.physics.entered_tag(self.player, "beacon") {
95 ctx.physics.remove(beacon);
96 self.beacons.retain(|b| *b != beacon);
97 ctx.play("found");
98 if self.beacons.is_empty() {
99 self.finish(ctx);
100 } else {
101 ctx.speak(format!("Beacon found! {} left.", self.beacons.len()));
102 }
103 }
104 if ctx.ui.closed("done") {
105 ctx.quit();
106 }
107 }75 fn update(&mut self, ctx: &mut Context) {
76 if ctx.pressed(Key::Escape) {
77 ctx.quit();
78 }
79 if ctx.pressed(Key::Left) || ctx.pressed(Key::Right) {
80 let facing = ctx.physics.turn(self.drone, if ctx.pressed(Key::Left) { -30.0 } else { 30.0 });
81 ctx.speak(math::direction_name(facing));
82 }
83 if ctx.pressed(Key::PageUp) || ctx.pressed(Key::PageDown) {
84 let pitch = ctx.physics.tilt(self.drone, if ctx.pressed(Key::PageUp) { 30.0 } else { -30.0 });
85 ctx.speak(describe_pitch(pitch));
86 }
87
88 // Smooth flight: 4 meters per second while a key is held.
89 let speed = 4.0 * ctx.time.delta();
90 let forward = ctx.input.axis(Key::Down, Key::Up);
91 if forward != 0.0 {
92 let result = ctx.physics.move_forward(self.drone, forward * speed);
93 self.fly(ctx, result);
94 }
95 let rise = ctx.input.axis(Key::Q, Key::E);
96 if rise != 0.0 {
97 let result = ctx.physics.move_up(self.drone, rise * speed);
98 self.fly(ctx, result);
99 }
100
101 if ctx.pressed(Key::C) {
102 let position = ctx.physics.position(self.drone);
103 match ctx.physics.nearest_with_tag(position, "bird") {
104 Some(bird) => {
105 let text = ctx.physics.describe(self.drone, bird); // e.g. "2 o'clock, 9 meters, 6 meters above"
106 ctx.speak(text);
107 }
108 None => ctx.speak("No birds left"),
109 }
110 }
111 if ctx.pressed(Key::F) {
112 let (facing, pitch) = (ctx.physics.facing(self.drone), ctx.physics.pitch(self.drone));
113 ctx.speak(format!("Facing {}, {}", math::direction_name(facing), describe_pitch(pitch)));
114 }
115 if ctx.pressed(Key::H) {
116 let height = ctx.physics.position(self.drone).z;
117 ctx.speak(format!("{height:.0} meters high"));
118 }
119
120 if let Some(bird) = ctx.physics.entered_tag(self.drone, "bird") {
121 ctx.physics.remove(bird);
122 self.birds -= 1;
123 ctx.play("found");
124 if self.birds == 0 {
125 ctx.ui.message("done", "You found every bird!");
126 } else {
127 ctx.speak(format!("Bird found! {} left.", self.birds));
128 }
129 }
130 if ctx.ui.closed("done") {
131 ctx.quit();
132 }
133 }Sourcepub fn set_position(&mut self, id: BodyId, position: Vec3)
pub fn set_position(&mut self, id: BodyId, position: Vec3)
Teleports a body without collision checks.
Sourcepub fn velocity(&self, id: BodyId) -> Vec3
pub fn velocity(&self, id: BodyId) -> Vec3
Velocity of a body (zero if it does not exist).
Examples found in repository?
58 fn update(&mut self, ctx: &mut Context) {
59 if ctx.pressed(Key::Escape) {
60 ctx.quit();
61 }
62
63 // The lift goes up for 4 seconds and down for 4 seconds.
64 let lift_up = (ctx.time.elapsed() % 8.0) < 4.0;
65 ctx.physics.set_velocity(self.lift, vec3(0.0, 0.0, if lift_up { 2.0 } else { -2.0 }));
66
67 let run = ctx.input.axis(Key::Left, Key::Right);
68 let mut velocity = ctx.physics.velocity(self.player);
69 velocity.x = run * 6.0;
70 ctx.physics.set_velocity(self.player, velocity);
71 if ctx.pressed(Key::Space) && ctx.physics.jump(self.player, 2.5) {
72 ctx.play("jump");
73 }
74 let running = ctx.physics.on_ground(self.player) && run != 0.0;
75 self.run_sound.set_volume(if running { 0.6 } else { 0.0 });
76
77 if let Some(speed) = ctx.physics.landed(self.player) {
78 ctx.audio.sound("land").volume((speed / 12.0).clamp(0.2, 1.0)).play();
79 if speed > 15.0 {
80 ctx.speak("Ouch!");
81 }
82 }
83 if let Some((other, _)) = ctx.physics.collided(self.player)
84 && ctx.physics.tag(other) == "crate"
85 {
86 ctx.play_on(other, "push");
87 }
88 if let Some(coin) = ctx.physics.entered_tag(self.player, "coin") {
89 ctx.physics.remove(coin); // its looping sound stops by itself
90 self.score += 1;
91 ctx.audio.sound("coin").pitch(1.5).play();
92 ctx.speak(format!("{} of {COINS} coins", self.score));
93 if self.score == COINS {
94 ctx.ui.message("won", "You collected every coin! Press enter to quit.");
95 }
96 }
97 if ctx.ui.closed("won") {
98 ctx.quit();
99 }
100
101 if ctx.pressed(Key::S) {
102 let x = ctx.physics.position(self.player).x;
103 ctx.speak(format!("Score {}, position {x:.0}", self.score));
104 }
105 }Sourcepub fn set_velocity(&mut self, id: BodyId, velocity: Vec3)
pub fn set_velocity(&mut self, id: BodyId, velocity: Vec3)
Sets the velocity of a body.
Examples found in repository?
58 fn update(&mut self, ctx: &mut Context) {
59 if ctx.pressed(Key::Escape) {
60 ctx.quit();
61 }
62
63 // The lift goes up for 4 seconds and down for 4 seconds.
64 let lift_up = (ctx.time.elapsed() % 8.0) < 4.0;
65 ctx.physics.set_velocity(self.lift, vec3(0.0, 0.0, if lift_up { 2.0 } else { -2.0 }));
66
67 let run = ctx.input.axis(Key::Left, Key::Right);
68 let mut velocity = ctx.physics.velocity(self.player);
69 velocity.x = run * 6.0;
70 ctx.physics.set_velocity(self.player, velocity);
71 if ctx.pressed(Key::Space) && ctx.physics.jump(self.player, 2.5) {
72 ctx.play("jump");
73 }
74 let running = ctx.physics.on_ground(self.player) && run != 0.0;
75 self.run_sound.set_volume(if running { 0.6 } else { 0.0 });
76
77 if let Some(speed) = ctx.physics.landed(self.player) {
78 ctx.audio.sound("land").volume((speed / 12.0).clamp(0.2, 1.0)).play();
79 if speed > 15.0 {
80 ctx.speak("Ouch!");
81 }
82 }
83 if let Some((other, _)) = ctx.physics.collided(self.player)
84 && ctx.physics.tag(other) == "crate"
85 {
86 ctx.play_on(other, "push");
87 }
88 if let Some(coin) = ctx.physics.entered_tag(self.player, "coin") {
89 ctx.physics.remove(coin); // its looping sound stops by itself
90 self.score += 1;
91 ctx.audio.sound("coin").pitch(1.5).play();
92 ctx.speak(format!("{} of {COINS} coins", self.score));
93 if self.score == COINS {
94 ctx.ui.message("won", "You collected every coin! Press enter to quit.");
95 }
96 }
97 if ctx.ui.closed("won") {
98 ctx.quit();
99 }
100
101 if ctx.pressed(Key::S) {
102 let x = ctx.physics.position(self.player).x;
103 ctx.speak(format!("Score {}, position {x:.0}", self.score));
104 }
105 }Sourcepub fn apply_impulse(&mut self, id: BodyId, impulse: Vec3)
pub fn apply_impulse(&mut self, id: BodyId, impulse: Vec3)
Adds impulse (meters per second) to the velocity at once, regardless of mass,
e.g. a kick or knockback: apply_impulse(ball, vec3(0.0, 10.0, 0.0)).
Sourcepub fn apply_force(&mut self, id: BodyId, force: Vec3)
pub fn apply_force(&mut self, id: BodyId, force: Vec3)
Pushes a body with a force in newtons during the next physics step, e.g. wind,
a conveyor belt or a rocket. Each second, a force adds force / mass meters per
second to the velocity, so 20 N speed up a 1 kg body by 20 m/s per second and a
10 kg body by 2 m/s per second. Call it every frame for a continuous force.
Sourcepub fn jump(&mut self, id: BodyId, height: f32) -> bool
pub fn jump(&mut self, id: BodyId, height: f32) -> bool
Makes a dynamic body standing on the ground jump so that it reaches height meters
above where it stands, taking the current gravity into account. Returns false (and
does nothing) while in the air, without gravity, or for other body kinds.
if ctx.input.pressed(Key::Space) && ctx.physics.jump(player, 1.5) {
ctx.audio.play("jump");
}Examples found in repository?
58 fn update(&mut self, ctx: &mut Context) {
59 if ctx.pressed(Key::Escape) {
60 ctx.quit();
61 }
62
63 // The lift goes up for 4 seconds and down for 4 seconds.
64 let lift_up = (ctx.time.elapsed() % 8.0) < 4.0;
65 ctx.physics.set_velocity(self.lift, vec3(0.0, 0.0, if lift_up { 2.0 } else { -2.0 }));
66
67 let run = ctx.input.axis(Key::Left, Key::Right);
68 let mut velocity = ctx.physics.velocity(self.player);
69 velocity.x = run * 6.0;
70 ctx.physics.set_velocity(self.player, velocity);
71 if ctx.pressed(Key::Space) && ctx.physics.jump(self.player, 2.5) {
72 ctx.play("jump");
73 }
74 let running = ctx.physics.on_ground(self.player) && run != 0.0;
75 self.run_sound.set_volume(if running { 0.6 } else { 0.0 });
76
77 if let Some(speed) = ctx.physics.landed(self.player) {
78 ctx.audio.sound("land").volume((speed / 12.0).clamp(0.2, 1.0)).play();
79 if speed > 15.0 {
80 ctx.speak("Ouch!");
81 }
82 }
83 if let Some((other, _)) = ctx.physics.collided(self.player)
84 && ctx.physics.tag(other) == "crate"
85 {
86 ctx.play_on(other, "push");
87 }
88 if let Some(coin) = ctx.physics.entered_tag(self.player, "coin") {
89 ctx.physics.remove(coin); // its looping sound stops by itself
90 self.score += 1;
91 ctx.audio.sound("coin").pitch(1.5).play();
92 ctx.speak(format!("{} of {COINS} coins", self.score));
93 if self.score == COINS {
94 ctx.ui.message("won", "You collected every coin! Press enter to quit.");
95 }
96 }
97 if ctx.ui.closed("won") {
98 ctx.quit();
99 }
100
101 if ctx.pressed(Key::S) {
102 let x = ctx.physics.position(self.player).x;
103 ctx.speak(format!("Score {}, position {x:.0}", self.score));
104 }
105 }Sourcepub fn on_ground(&self, id: BodyId) -> bool
pub fn on_ground(&self, id: BodyId) -> bool
Whether a dynamic body stands on something (always false for other kinds).
Examples found in repository?
58 fn update(&mut self, ctx: &mut Context) {
59 if ctx.pressed(Key::Escape) {
60 ctx.quit();
61 }
62
63 // The lift goes up for 4 seconds and down for 4 seconds.
64 let lift_up = (ctx.time.elapsed() % 8.0) < 4.0;
65 ctx.physics.set_velocity(self.lift, vec3(0.0, 0.0, if lift_up { 2.0 } else { -2.0 }));
66
67 let run = ctx.input.axis(Key::Left, Key::Right);
68 let mut velocity = ctx.physics.velocity(self.player);
69 velocity.x = run * 6.0;
70 ctx.physics.set_velocity(self.player, velocity);
71 if ctx.pressed(Key::Space) && ctx.physics.jump(self.player, 2.5) {
72 ctx.play("jump");
73 }
74 let running = ctx.physics.on_ground(self.player) && run != 0.0;
75 self.run_sound.set_volume(if running { 0.6 } else { 0.0 });
76
77 if let Some(speed) = ctx.physics.landed(self.player) {
78 ctx.audio.sound("land").volume((speed / 12.0).clamp(0.2, 1.0)).play();
79 if speed > 15.0 {
80 ctx.speak("Ouch!");
81 }
82 }
83 if let Some((other, _)) = ctx.physics.collided(self.player)
84 && ctx.physics.tag(other) == "crate"
85 {
86 ctx.play_on(other, "push");
87 }
88 if let Some(coin) = ctx.physics.entered_tag(self.player, "coin") {
89 ctx.physics.remove(coin); // its looping sound stops by itself
90 self.score += 1;
91 ctx.audio.sound("coin").pitch(1.5).play();
92 ctx.speak(format!("{} of {COINS} coins", self.score));
93 if self.score == COINS {
94 ctx.ui.message("won", "You collected every coin! Press enter to quit.");
95 }
96 }
97 if ctx.ui.closed("won") {
98 ctx.quit();
99 }
100
101 if ctx.pressed(Key::S) {
102 let x = ctx.physics.position(self.player).x;
103 ctx.speak(format!("Score {}, position {x:.0}", self.score));
104 }
105 }Sourcepub fn tag(&self, id: BodyId) -> &str
pub fn tag(&self, id: BodyId) -> &str
The tag of a body (“” if it does not exist).
Examples found in repository?
More examples
58 fn update(&mut self, ctx: &mut Context) {
59 if ctx.pressed(Key::Escape) {
60 ctx.quit();
61 }
62
63 // The lift goes up for 4 seconds and down for 4 seconds.
64 let lift_up = (ctx.time.elapsed() % 8.0) < 4.0;
65 ctx.physics.set_velocity(self.lift, vec3(0.0, 0.0, if lift_up { 2.0 } else { -2.0 }));
66
67 let run = ctx.input.axis(Key::Left, Key::Right);
68 let mut velocity = ctx.physics.velocity(self.player);
69 velocity.x = run * 6.0;
70 ctx.physics.set_velocity(self.player, velocity);
71 if ctx.pressed(Key::Space) && ctx.physics.jump(self.player, 2.5) {
72 ctx.play("jump");
73 }
74 let running = ctx.physics.on_ground(self.player) && run != 0.0;
75 self.run_sound.set_volume(if running { 0.6 } else { 0.0 });
76
77 if let Some(speed) = ctx.physics.landed(self.player) {
78 ctx.audio.sound("land").volume((speed / 12.0).clamp(0.2, 1.0)).play();
79 if speed > 15.0 {
80 ctx.speak("Ouch!");
81 }
82 }
83 if let Some((other, _)) = ctx.physics.collided(self.player)
84 && ctx.physics.tag(other) == "crate"
85 {
86 ctx.play_on(other, "push");
87 }
88 if let Some(coin) = ctx.physics.entered_tag(self.player, "coin") {
89 ctx.physics.remove(coin); // its looping sound stops by itself
90 self.score += 1;
91 ctx.audio.sound("coin").pitch(1.5).play();
92 ctx.speak(format!("{} of {COINS} coins", self.score));
93 if self.score == COINS {
94 ctx.ui.message("won", "You collected every coin! Press enter to quit.");
95 }
96 }
97 if ctx.ui.closed("won") {
98 ctx.quit();
99 }
100
101 if ctx.pressed(Key::S) {
102 let x = ctx.physics.position(self.player).x;
103 ctx.speak(format!("Score {}, position {x:.0}", self.score));
104 }
105 }Sourcepub fn with_tag<'a>(&'a self, tag: &'a str) -> impl Iterator<Item = BodyId> + 'a
pub fn with_tag<'a>(&'a self, tag: &'a str) -> impl Iterator<Item = BodyId> + 'a
All bodies with a tag.
Sourcepub fn events(&self) -> &[PhysicsEvent]
pub fn events(&self) -> &[PhysicsEvent]
Events from the physics steps of this frame.
Sourcepub fn sensors_of(&self, body: BodyId) -> Vec<BodyId>
pub fn sensors_of(&self, body: BodyId) -> Vec<BodyId>
Sensors body is currently inside.
Sourcepub fn in_radius(&self, center: Vec3, radius: f32) -> Vec<BodyId>
pub fn in_radius(&self, center: Vec3, radius: f32) -> Vec<BodyId>
Bodies whose center lies within radius of center, nearest first.
Sourcepub fn nearest_with_tag(&self, center: Vec3, tag: &str) -> Option<BodyId>
pub fn nearest_with_tag(&self, center: Vec3, tag: &str) -> Option<BodyId>
Nearest body with the given tag.
Examples found in repository?
58 fn update(&mut self, ctx: &mut Context) {
59 if ctx.pressed(Key::Escape) {
60 ctx.push_scene(Pause);
61 }
62 if ctx.pressed(Key::Left) || ctx.pressed(Key::Right) {
63 let degrees = if ctx.pressed(Key::Left) { -45.0 } else { 45.0 };
64 let facing = ctx.physics.turn(self.player, degrees);
65 ctx.speak(math::direction_name(facing));
66 }
67
68 let forward = ctx.input.repeating(Key::Up, 0.35, 0.35);
69 let backward = ctx.input.repeating(Key::Down, 0.35, 0.35);
70 if forward || backward {
71 let step = if forward { 1.0 } else { -1.0 };
72 if ctx.physics.move_forward(self.player, step).blocked {
73 ctx.play("wall");
74 } else {
75 ctx.audio.sound("step").random_pitch(0.85, 1.15).play();
76 }
77 }
78
79 if ctx.pressed(Key::C) {
80 let position = ctx.physics.position(self.player);
81 match ctx.physics.nearest_with_tag(position, "beacon") {
82 Some(beacon) => {
83 let text = ctx.physics.describe(self.player, beacon);
84 ctx.speak(text);
85 }
86 None => ctx.speak("No beacons left"),
87 }
88 }
89 if ctx.pressed(Key::F) {
90 let facing = ctx.physics.facing(self.player);
91 ctx.speak(format!("Facing {}", math::direction_name(facing)));
92 }
93
94 if let Some(beacon) = ctx.physics.entered_tag(self.player, "beacon") {
95 ctx.physics.remove(beacon);
96 self.beacons.retain(|b| *b != beacon);
97 ctx.play("found");
98 if self.beacons.is_empty() {
99 self.finish(ctx);
100 } else {
101 ctx.speak(format!("Beacon found! {} left.", self.beacons.len()));
102 }
103 }
104 if ctx.ui.closed("done") {
105 ctx.quit();
106 }
107 }More examples
75 fn update(&mut self, ctx: &mut Context) {
76 if ctx.pressed(Key::Escape) {
77 ctx.quit();
78 }
79 if ctx.pressed(Key::Left) || ctx.pressed(Key::Right) {
80 let facing = ctx.physics.turn(self.drone, if ctx.pressed(Key::Left) { -30.0 } else { 30.0 });
81 ctx.speak(math::direction_name(facing));
82 }
83 if ctx.pressed(Key::PageUp) || ctx.pressed(Key::PageDown) {
84 let pitch = ctx.physics.tilt(self.drone, if ctx.pressed(Key::PageUp) { 30.0 } else { -30.0 });
85 ctx.speak(describe_pitch(pitch));
86 }
87
88 // Smooth flight: 4 meters per second while a key is held.
89 let speed = 4.0 * ctx.time.delta();
90 let forward = ctx.input.axis(Key::Down, Key::Up);
91 if forward != 0.0 {
92 let result = ctx.physics.move_forward(self.drone, forward * speed);
93 self.fly(ctx, result);
94 }
95 let rise = ctx.input.axis(Key::Q, Key::E);
96 if rise != 0.0 {
97 let result = ctx.physics.move_up(self.drone, rise * speed);
98 self.fly(ctx, result);
99 }
100
101 if ctx.pressed(Key::C) {
102 let position = ctx.physics.position(self.drone);
103 match ctx.physics.nearest_with_tag(position, "bird") {
104 Some(bird) => {
105 let text = ctx.physics.describe(self.drone, bird); // e.g. "2 o'clock, 9 meters, 6 meters above"
106 ctx.speak(text);
107 }
108 None => ctx.speak("No birds left"),
109 }
110 }
111 if ctx.pressed(Key::F) {
112 let (facing, pitch) = (ctx.physics.facing(self.drone), ctx.physics.pitch(self.drone));
113 ctx.speak(format!("Facing {}, {}", math::direction_name(facing), describe_pitch(pitch)));
114 }
115 if ctx.pressed(Key::H) {
116 let height = ctx.physics.position(self.drone).z;
117 ctx.speak(format!("{height:.0} meters high"));
118 }
119
120 if let Some(bird) = ctx.physics.entered_tag(self.drone, "bird") {
121 ctx.physics.remove(bird);
122 self.birds -= 1;
123 ctx.play("found");
124 if self.birds == 0 {
125 ctx.ui.message("done", "You found every bird!");
126 } else {
127 ctx.speak(format!("Bird found! {} left.", self.birds));
128 }
129 }
130 if ctx.ui.closed("done") {
131 ctx.quit();
132 }
133 }Sourcepub fn raycast(
&self,
origin: Vec3,
direction: Vec3,
max_distance: f32,
ignore: Option<BodyId>,
) -> Option<RayHit>
pub fn raycast( &self, origin: Vec3, direction: Vec3, max_distance: f32, ignore: Option<BodyId>, ) -> Option<RayHit>
Sends a straight line from origin in direction (any length) and returns the first
solid body hit within max_distance meters. ignore is skipped: pass the caster
itself, otherwise the ray hits it first. Sensors are ignored.
Sourcepub fn move_by(&mut self, id: BodyId, delta: Vec3) -> MoveResult
pub fn move_by(&mut self, id: BodyId, delta: Vec3) -> MoveResult
Moves a body by delta meters right now, sliding along and stopping at solid bodies,
and pushing dynamic bodies out of the way. This is the easiest way to move a player:
walls block, and you learn what was hit. Sensor events are updated at once;
PhysicsEvent::CollisionStarted is not created.
Source§impl World
Convenience helpers for typical audio game code.
impl World
Convenience helpers for typical audio game code.
Sourcepub fn facing(&self, id: BodyId) -> f32
pub fn facing(&self, id: BodyId) -> f32
Compass direction a body faces (0 if it does not exist).
Examples found in repository?
58 fn update(&mut self, ctx: &mut Context) {
59 if ctx.pressed(Key::Escape) {
60 ctx.push_scene(Pause);
61 }
62 if ctx.pressed(Key::Left) || ctx.pressed(Key::Right) {
63 let degrees = if ctx.pressed(Key::Left) { -45.0 } else { 45.0 };
64 let facing = ctx.physics.turn(self.player, degrees);
65 ctx.speak(math::direction_name(facing));
66 }
67
68 let forward = ctx.input.repeating(Key::Up, 0.35, 0.35);
69 let backward = ctx.input.repeating(Key::Down, 0.35, 0.35);
70 if forward || backward {
71 let step = if forward { 1.0 } else { -1.0 };
72 if ctx.physics.move_forward(self.player, step).blocked {
73 ctx.play("wall");
74 } else {
75 ctx.audio.sound("step").random_pitch(0.85, 1.15).play();
76 }
77 }
78
79 if ctx.pressed(Key::C) {
80 let position = ctx.physics.position(self.player);
81 match ctx.physics.nearest_with_tag(position, "beacon") {
82 Some(beacon) => {
83 let text = ctx.physics.describe(self.player, beacon);
84 ctx.speak(text);
85 }
86 None => ctx.speak("No beacons left"),
87 }
88 }
89 if ctx.pressed(Key::F) {
90 let facing = ctx.physics.facing(self.player);
91 ctx.speak(format!("Facing {}", math::direction_name(facing)));
92 }
93
94 if let Some(beacon) = ctx.physics.entered_tag(self.player, "beacon") {
95 ctx.physics.remove(beacon);
96 self.beacons.retain(|b| *b != beacon);
97 ctx.play("found");
98 if self.beacons.is_empty() {
99 self.finish(ctx);
100 } else {
101 ctx.speak(format!("Beacon found! {} left.", self.beacons.len()));
102 }
103 }
104 if ctx.ui.closed("done") {
105 ctx.quit();
106 }
107 }More examples
75 fn update(&mut self, ctx: &mut Context) {
76 if ctx.pressed(Key::Escape) {
77 ctx.quit();
78 }
79 if ctx.pressed(Key::Left) || ctx.pressed(Key::Right) {
80 let facing = ctx.physics.turn(self.drone, if ctx.pressed(Key::Left) { -30.0 } else { 30.0 });
81 ctx.speak(math::direction_name(facing));
82 }
83 if ctx.pressed(Key::PageUp) || ctx.pressed(Key::PageDown) {
84 let pitch = ctx.physics.tilt(self.drone, if ctx.pressed(Key::PageUp) { 30.0 } else { -30.0 });
85 ctx.speak(describe_pitch(pitch));
86 }
87
88 // Smooth flight: 4 meters per second while a key is held.
89 let speed = 4.0 * ctx.time.delta();
90 let forward = ctx.input.axis(Key::Down, Key::Up);
91 if forward != 0.0 {
92 let result = ctx.physics.move_forward(self.drone, forward * speed);
93 self.fly(ctx, result);
94 }
95 let rise = ctx.input.axis(Key::Q, Key::E);
96 if rise != 0.0 {
97 let result = ctx.physics.move_up(self.drone, rise * speed);
98 self.fly(ctx, result);
99 }
100
101 if ctx.pressed(Key::C) {
102 let position = ctx.physics.position(self.drone);
103 match ctx.physics.nearest_with_tag(position, "bird") {
104 Some(bird) => {
105 let text = ctx.physics.describe(self.drone, bird); // e.g. "2 o'clock, 9 meters, 6 meters above"
106 ctx.speak(text);
107 }
108 None => ctx.speak("No birds left"),
109 }
110 }
111 if ctx.pressed(Key::F) {
112 let (facing, pitch) = (ctx.physics.facing(self.drone), ctx.physics.pitch(self.drone));
113 ctx.speak(format!("Facing {}, {}", math::direction_name(facing), describe_pitch(pitch)));
114 }
115 if ctx.pressed(Key::H) {
116 let height = ctx.physics.position(self.drone).z;
117 ctx.speak(format!("{height:.0} meters high"));
118 }
119
120 if let Some(bird) = ctx.physics.entered_tag(self.drone, "bird") {
121 ctx.physics.remove(bird);
122 self.birds -= 1;
123 ctx.play("found");
124 if self.birds == 0 {
125 ctx.ui.message("done", "You found every bird!");
126 } else {
127 ctx.speak(format!("Bird found! {} left.", self.birds));
128 }
129 }
130 if ctx.ui.closed("done") {
131 ctx.quit();
132 }
133 }Sourcepub fn set_facing(&mut self, id: BodyId, degrees: f32)
pub fn set_facing(&mut self, id: BodyId, degrees: f32)
Sets the compass direction a body faces.
Sourcepub fn turn(&mut self, id: BodyId, degrees: f32) -> f32
pub fn turn(&mut self, id: BodyId, degrees: f32) -> f32
Turns a body by degrees (positive = clockwise / right, negative = left) and returns
the new facing, 0.0 to 360.0.
Examples found in repository?
58 fn update(&mut self, ctx: &mut Context) {
59 if ctx.pressed(Key::Escape) {
60 ctx.push_scene(Pause);
61 }
62 if ctx.pressed(Key::Left) || ctx.pressed(Key::Right) {
63 let degrees = if ctx.pressed(Key::Left) { -45.0 } else { 45.0 };
64 let facing = ctx.physics.turn(self.player, degrees);
65 ctx.speak(math::direction_name(facing));
66 }
67
68 let forward = ctx.input.repeating(Key::Up, 0.35, 0.35);
69 let backward = ctx.input.repeating(Key::Down, 0.35, 0.35);
70 if forward || backward {
71 let step = if forward { 1.0 } else { -1.0 };
72 if ctx.physics.move_forward(self.player, step).blocked {
73 ctx.play("wall");
74 } else {
75 ctx.audio.sound("step").random_pitch(0.85, 1.15).play();
76 }
77 }
78
79 if ctx.pressed(Key::C) {
80 let position = ctx.physics.position(self.player);
81 match ctx.physics.nearest_with_tag(position, "beacon") {
82 Some(beacon) => {
83 let text = ctx.physics.describe(self.player, beacon);
84 ctx.speak(text);
85 }
86 None => ctx.speak("No beacons left"),
87 }
88 }
89 if ctx.pressed(Key::F) {
90 let facing = ctx.physics.facing(self.player);
91 ctx.speak(format!("Facing {}", math::direction_name(facing)));
92 }
93
94 if let Some(beacon) = ctx.physics.entered_tag(self.player, "beacon") {
95 ctx.physics.remove(beacon);
96 self.beacons.retain(|b| *b != beacon);
97 ctx.play("found");
98 if self.beacons.is_empty() {
99 self.finish(ctx);
100 } else {
101 ctx.speak(format!("Beacon found! {} left.", self.beacons.len()));
102 }
103 }
104 if ctx.ui.closed("done") {
105 ctx.quit();
106 }
107 }More examples
75 fn update(&mut self, ctx: &mut Context) {
76 if ctx.pressed(Key::Escape) {
77 ctx.quit();
78 }
79 if ctx.pressed(Key::Left) || ctx.pressed(Key::Right) {
80 let facing = ctx.physics.turn(self.drone, if ctx.pressed(Key::Left) { -30.0 } else { 30.0 });
81 ctx.speak(math::direction_name(facing));
82 }
83 if ctx.pressed(Key::PageUp) || ctx.pressed(Key::PageDown) {
84 let pitch = ctx.physics.tilt(self.drone, if ctx.pressed(Key::PageUp) { 30.0 } else { -30.0 });
85 ctx.speak(describe_pitch(pitch));
86 }
87
88 // Smooth flight: 4 meters per second while a key is held.
89 let speed = 4.0 * ctx.time.delta();
90 let forward = ctx.input.axis(Key::Down, Key::Up);
91 if forward != 0.0 {
92 let result = ctx.physics.move_forward(self.drone, forward * speed);
93 self.fly(ctx, result);
94 }
95 let rise = ctx.input.axis(Key::Q, Key::E);
96 if rise != 0.0 {
97 let result = ctx.physics.move_up(self.drone, rise * speed);
98 self.fly(ctx, result);
99 }
100
101 if ctx.pressed(Key::C) {
102 let position = ctx.physics.position(self.drone);
103 match ctx.physics.nearest_with_tag(position, "bird") {
104 Some(bird) => {
105 let text = ctx.physics.describe(self.drone, bird); // e.g. "2 o'clock, 9 meters, 6 meters above"
106 ctx.speak(text);
107 }
108 None => ctx.speak("No birds left"),
109 }
110 }
111 if ctx.pressed(Key::F) {
112 let (facing, pitch) = (ctx.physics.facing(self.drone), ctx.physics.pitch(self.drone));
113 ctx.speak(format!("Facing {}, {}", math::direction_name(facing), describe_pitch(pitch)));
114 }
115 if ctx.pressed(Key::H) {
116 let height = ctx.physics.position(self.drone).z;
117 ctx.speak(format!("{height:.0} meters high"));
118 }
119
120 if let Some(bird) = ctx.physics.entered_tag(self.drone, "bird") {
121 ctx.physics.remove(bird);
122 self.birds -= 1;
123 ctx.play("found");
124 if self.birds == 0 {
125 ctx.ui.message("done", "You found every bird!");
126 } else {
127 ctx.speak(format!("Bird found! {} left.", self.birds));
128 }
129 }
130 if ctx.ui.closed("done") {
131 ctx.quit();
132 }
133 }Sourcepub fn pitch(&self, id: BodyId) -> f32
pub fn pitch(&self, id: BodyId) -> f32
How far a body looks up (positive) or down (negative) in degrees (0 if it does not exist).
Examples found in repository?
75 fn update(&mut self, ctx: &mut Context) {
76 if ctx.pressed(Key::Escape) {
77 ctx.quit();
78 }
79 if ctx.pressed(Key::Left) || ctx.pressed(Key::Right) {
80 let facing = ctx.physics.turn(self.drone, if ctx.pressed(Key::Left) { -30.0 } else { 30.0 });
81 ctx.speak(math::direction_name(facing));
82 }
83 if ctx.pressed(Key::PageUp) || ctx.pressed(Key::PageDown) {
84 let pitch = ctx.physics.tilt(self.drone, if ctx.pressed(Key::PageUp) { 30.0 } else { -30.0 });
85 ctx.speak(describe_pitch(pitch));
86 }
87
88 // Smooth flight: 4 meters per second while a key is held.
89 let speed = 4.0 * ctx.time.delta();
90 let forward = ctx.input.axis(Key::Down, Key::Up);
91 if forward != 0.0 {
92 let result = ctx.physics.move_forward(self.drone, forward * speed);
93 self.fly(ctx, result);
94 }
95 let rise = ctx.input.axis(Key::Q, Key::E);
96 if rise != 0.0 {
97 let result = ctx.physics.move_up(self.drone, rise * speed);
98 self.fly(ctx, result);
99 }
100
101 if ctx.pressed(Key::C) {
102 let position = ctx.physics.position(self.drone);
103 match ctx.physics.nearest_with_tag(position, "bird") {
104 Some(bird) => {
105 let text = ctx.physics.describe(self.drone, bird); // e.g. "2 o'clock, 9 meters, 6 meters above"
106 ctx.speak(text);
107 }
108 None => ctx.speak("No birds left"),
109 }
110 }
111 if ctx.pressed(Key::F) {
112 let (facing, pitch) = (ctx.physics.facing(self.drone), ctx.physics.pitch(self.drone));
113 ctx.speak(format!("Facing {}, {}", math::direction_name(facing), describe_pitch(pitch)));
114 }
115 if ctx.pressed(Key::H) {
116 let height = ctx.physics.position(self.drone).z;
117 ctx.speak(format!("{height:.0} meters high"));
118 }
119
120 if let Some(bird) = ctx.physics.entered_tag(self.drone, "bird") {
121 ctx.physics.remove(bird);
122 self.birds -= 1;
123 ctx.play("found");
124 if self.birds == 0 {
125 ctx.ui.message("done", "You found every bird!");
126 } else {
127 ctx.speak(format!("Bird found! {} left.", self.birds));
128 }
129 }
130 if ctx.ui.closed("done") {
131 ctx.quit();
132 }
133 }Sourcepub fn set_pitch(&mut self, id: BodyId, degrees: f32)
pub fn set_pitch(&mut self, id: BodyId, degrees: f32)
Sets how far a body looks up or down in degrees, clamped to -90..=90.
Sourcepub fn tilt(&mut self, id: BodyId, degrees: f32) -> f32
pub fn tilt(&mut self, id: BodyId, degrees: f32) -> f32
Tilts a body’s view up (positive degrees) or down (negative) and returns the new
pitch, -90.0 to 90.0. Together with World::turn this aims in any 3D direction.
Examples found in repository?
75 fn update(&mut self, ctx: &mut Context) {
76 if ctx.pressed(Key::Escape) {
77 ctx.quit();
78 }
79 if ctx.pressed(Key::Left) || ctx.pressed(Key::Right) {
80 let facing = ctx.physics.turn(self.drone, if ctx.pressed(Key::Left) { -30.0 } else { 30.0 });
81 ctx.speak(math::direction_name(facing));
82 }
83 if ctx.pressed(Key::PageUp) || ctx.pressed(Key::PageDown) {
84 let pitch = ctx.physics.tilt(self.drone, if ctx.pressed(Key::PageUp) { 30.0 } else { -30.0 });
85 ctx.speak(describe_pitch(pitch));
86 }
87
88 // Smooth flight: 4 meters per second while a key is held.
89 let speed = 4.0 * ctx.time.delta();
90 let forward = ctx.input.axis(Key::Down, Key::Up);
91 if forward != 0.0 {
92 let result = ctx.physics.move_forward(self.drone, forward * speed);
93 self.fly(ctx, result);
94 }
95 let rise = ctx.input.axis(Key::Q, Key::E);
96 if rise != 0.0 {
97 let result = ctx.physics.move_up(self.drone, rise * speed);
98 self.fly(ctx, result);
99 }
100
101 if ctx.pressed(Key::C) {
102 let position = ctx.physics.position(self.drone);
103 match ctx.physics.nearest_with_tag(position, "bird") {
104 Some(bird) => {
105 let text = ctx.physics.describe(self.drone, bird); // e.g. "2 o'clock, 9 meters, 6 meters above"
106 ctx.speak(text);
107 }
108 None => ctx.speak("No birds left"),
109 }
110 }
111 if ctx.pressed(Key::F) {
112 let (facing, pitch) = (ctx.physics.facing(self.drone), ctx.physics.pitch(self.drone));
113 ctx.speak(format!("Facing {}, {}", math::direction_name(facing), describe_pitch(pitch)));
114 }
115 if ctx.pressed(Key::H) {
116 let height = ctx.physics.position(self.drone).z;
117 ctx.speak(format!("{height:.0} meters high"));
118 }
119
120 if let Some(bird) = ctx.physics.entered_tag(self.drone, "bird") {
121 ctx.physics.remove(bird);
122 self.birds -= 1;
123 ctx.play("found");
124 if self.birds == 0 {
125 ctx.ui.message("done", "You found every bird!");
126 } else {
127 ctx.speak(format!("Bird found! {} left.", self.birds));
128 }
129 }
130 if ctx.ui.closed("done") {
131 ctx.quit();
132 }
133 }Sourcepub fn look_at(&mut self, id: BodyId, point: Vec3)
pub fn look_at(&mut self, id: BodyId, point: Vec3)
Turns a body so that it faces point: sets both the facing and the pitch.
Sourcepub fn move_forward(&mut self, id: BodyId, distance: f32) -> MoveResult
pub fn move_forward(&mut self, id: BodyId, distance: f32) -> MoveResult
Moves a body distance meters in the direction it faces (negative = backwards),
sliding along walls. The pitch counts too: a body looking 30° up also rises. With the
default pitch of 0 it moves level. See World::move_by.
Examples found in repository?
58 fn update(&mut self, ctx: &mut Context) {
59 if ctx.pressed(Key::Escape) {
60 ctx.push_scene(Pause);
61 }
62 if ctx.pressed(Key::Left) || ctx.pressed(Key::Right) {
63 let degrees = if ctx.pressed(Key::Left) { -45.0 } else { 45.0 };
64 let facing = ctx.physics.turn(self.player, degrees);
65 ctx.speak(math::direction_name(facing));
66 }
67
68 let forward = ctx.input.repeating(Key::Up, 0.35, 0.35);
69 let backward = ctx.input.repeating(Key::Down, 0.35, 0.35);
70 if forward || backward {
71 let step = if forward { 1.0 } else { -1.0 };
72 if ctx.physics.move_forward(self.player, step).blocked {
73 ctx.play("wall");
74 } else {
75 ctx.audio.sound("step").random_pitch(0.85, 1.15).play();
76 }
77 }
78
79 if ctx.pressed(Key::C) {
80 let position = ctx.physics.position(self.player);
81 match ctx.physics.nearest_with_tag(position, "beacon") {
82 Some(beacon) => {
83 let text = ctx.physics.describe(self.player, beacon);
84 ctx.speak(text);
85 }
86 None => ctx.speak("No beacons left"),
87 }
88 }
89 if ctx.pressed(Key::F) {
90 let facing = ctx.physics.facing(self.player);
91 ctx.speak(format!("Facing {}", math::direction_name(facing)));
92 }
93
94 if let Some(beacon) = ctx.physics.entered_tag(self.player, "beacon") {
95 ctx.physics.remove(beacon);
96 self.beacons.retain(|b| *b != beacon);
97 ctx.play("found");
98 if self.beacons.is_empty() {
99 self.finish(ctx);
100 } else {
101 ctx.speak(format!("Beacon found! {} left.", self.beacons.len()));
102 }
103 }
104 if ctx.ui.closed("done") {
105 ctx.quit();
106 }
107 }More examples
75 fn update(&mut self, ctx: &mut Context) {
76 if ctx.pressed(Key::Escape) {
77 ctx.quit();
78 }
79 if ctx.pressed(Key::Left) || ctx.pressed(Key::Right) {
80 let facing = ctx.physics.turn(self.drone, if ctx.pressed(Key::Left) { -30.0 } else { 30.0 });
81 ctx.speak(math::direction_name(facing));
82 }
83 if ctx.pressed(Key::PageUp) || ctx.pressed(Key::PageDown) {
84 let pitch = ctx.physics.tilt(self.drone, if ctx.pressed(Key::PageUp) { 30.0 } else { -30.0 });
85 ctx.speak(describe_pitch(pitch));
86 }
87
88 // Smooth flight: 4 meters per second while a key is held.
89 let speed = 4.0 * ctx.time.delta();
90 let forward = ctx.input.axis(Key::Down, Key::Up);
91 if forward != 0.0 {
92 let result = ctx.physics.move_forward(self.drone, forward * speed);
93 self.fly(ctx, result);
94 }
95 let rise = ctx.input.axis(Key::Q, Key::E);
96 if rise != 0.0 {
97 let result = ctx.physics.move_up(self.drone, rise * speed);
98 self.fly(ctx, result);
99 }
100
101 if ctx.pressed(Key::C) {
102 let position = ctx.physics.position(self.drone);
103 match ctx.physics.nearest_with_tag(position, "bird") {
104 Some(bird) => {
105 let text = ctx.physics.describe(self.drone, bird); // e.g. "2 o'clock, 9 meters, 6 meters above"
106 ctx.speak(text);
107 }
108 None => ctx.speak("No birds left"),
109 }
110 }
111 if ctx.pressed(Key::F) {
112 let (facing, pitch) = (ctx.physics.facing(self.drone), ctx.physics.pitch(self.drone));
113 ctx.speak(format!("Facing {}, {}", math::direction_name(facing), describe_pitch(pitch)));
114 }
115 if ctx.pressed(Key::H) {
116 let height = ctx.physics.position(self.drone).z;
117 ctx.speak(format!("{height:.0} meters high"));
118 }
119
120 if let Some(bird) = ctx.physics.entered_tag(self.drone, "bird") {
121 ctx.physics.remove(bird);
122 self.birds -= 1;
123 ctx.play("found");
124 if self.birds == 0 {
125 ctx.ui.message("done", "You found every bird!");
126 } else {
127 ctx.speak(format!("Bird found! {} left.", self.birds));
128 }
129 }
130 if ctx.ui.closed("done") {
131 ctx.quit();
132 }
133 }Sourcepub fn move_up(&mut self, id: BodyId, distance: f32) -> MoveResult
pub fn move_up(&mut self, id: BodyId, distance: f32) -> MoveResult
Moves a body distance meters straight up (negative = down), sliding along walls,
e.g. to fly, swim, climb a ladder or take a lift. “Up” is +z, or against gravity if
gravity points elsewhere. See World::move_by.
Examples found in repository?
75 fn update(&mut self, ctx: &mut Context) {
76 if ctx.pressed(Key::Escape) {
77 ctx.quit();
78 }
79 if ctx.pressed(Key::Left) || ctx.pressed(Key::Right) {
80 let facing = ctx.physics.turn(self.drone, if ctx.pressed(Key::Left) { -30.0 } else { 30.0 });
81 ctx.speak(math::direction_name(facing));
82 }
83 if ctx.pressed(Key::PageUp) || ctx.pressed(Key::PageDown) {
84 let pitch = ctx.physics.tilt(self.drone, if ctx.pressed(Key::PageUp) { 30.0 } else { -30.0 });
85 ctx.speak(describe_pitch(pitch));
86 }
87
88 // Smooth flight: 4 meters per second while a key is held.
89 let speed = 4.0 * ctx.time.delta();
90 let forward = ctx.input.axis(Key::Down, Key::Up);
91 if forward != 0.0 {
92 let result = ctx.physics.move_forward(self.drone, forward * speed);
93 self.fly(ctx, result);
94 }
95 let rise = ctx.input.axis(Key::Q, Key::E);
96 if rise != 0.0 {
97 let result = ctx.physics.move_up(self.drone, rise * speed);
98 self.fly(ctx, result);
99 }
100
101 if ctx.pressed(Key::C) {
102 let position = ctx.physics.position(self.drone);
103 match ctx.physics.nearest_with_tag(position, "bird") {
104 Some(bird) => {
105 let text = ctx.physics.describe(self.drone, bird); // e.g. "2 o'clock, 9 meters, 6 meters above"
106 ctx.speak(text);
107 }
108 None => ctx.speak("No birds left"),
109 }
110 }
111 if ctx.pressed(Key::F) {
112 let (facing, pitch) = (ctx.physics.facing(self.drone), ctx.physics.pitch(self.drone));
113 ctx.speak(format!("Facing {}, {}", math::direction_name(facing), describe_pitch(pitch)));
114 }
115 if ctx.pressed(Key::H) {
116 let height = ctx.physics.position(self.drone).z;
117 ctx.speak(format!("{height:.0} meters high"));
118 }
119
120 if let Some(bird) = ctx.physics.entered_tag(self.drone, "bird") {
121 ctx.physics.remove(bird);
122 self.birds -= 1;
123 ctx.play("found");
124 if self.birds == 0 {
125 ctx.ui.message("done", "You found every bird!");
126 } else {
127 ctx.speak(format!("Bird found! {} left.", self.birds));
128 }
129 }
130 if ctx.ui.closed("done") {
131 ctx.quit();
132 }
133 }Sourcepub fn strafe(&mut self, id: BodyId, distance: f32) -> MoveResult
pub fn strafe(&mut self, id: BodyId, distance: f32) -> MoveResult
Moves a body sideways, distance meters to its right (negative = left).
Sourcepub fn distance(&self, a: BodyId, b: BodyId) -> f32
pub fn distance(&self, a: BodyId, b: BodyId) -> f32
Distance between two bodies’ centers (infinity if one does not exist).
Sourcepub fn describe(&self, from: BodyId, target: BodyId) -> String
pub fn describe(&self, from: BodyId, target: BodyId) -> String
Where target is from the point of view of from, ready to speak:
"3 o'clock, 12 meters". Uses the facing of from: 12 o’clock is straight ahead,
3 o’clock to the right, 6 o’clock behind. A height difference of a meter or more is
added ("12 o'clock, 11 meters, 4 meters above"), and a target straight above or
below is "directly above, 5 meters". See math::describe_position.
ctx.speak(ctx.physics.describe(player, beacon));Examples found in repository?
58 fn update(&mut self, ctx: &mut Context) {
59 if ctx.pressed(Key::Escape) {
60 ctx.push_scene(Pause);
61 }
62 if ctx.pressed(Key::Left) || ctx.pressed(Key::Right) {
63 let degrees = if ctx.pressed(Key::Left) { -45.0 } else { 45.0 };
64 let facing = ctx.physics.turn(self.player, degrees);
65 ctx.speak(math::direction_name(facing));
66 }
67
68 let forward = ctx.input.repeating(Key::Up, 0.35, 0.35);
69 let backward = ctx.input.repeating(Key::Down, 0.35, 0.35);
70 if forward || backward {
71 let step = if forward { 1.0 } else { -1.0 };
72 if ctx.physics.move_forward(self.player, step).blocked {
73 ctx.play("wall");
74 } else {
75 ctx.audio.sound("step").random_pitch(0.85, 1.15).play();
76 }
77 }
78
79 if ctx.pressed(Key::C) {
80 let position = ctx.physics.position(self.player);
81 match ctx.physics.nearest_with_tag(position, "beacon") {
82 Some(beacon) => {
83 let text = ctx.physics.describe(self.player, beacon);
84 ctx.speak(text);
85 }
86 None => ctx.speak("No beacons left"),
87 }
88 }
89 if ctx.pressed(Key::F) {
90 let facing = ctx.physics.facing(self.player);
91 ctx.speak(format!("Facing {}", math::direction_name(facing)));
92 }
93
94 if let Some(beacon) = ctx.physics.entered_tag(self.player, "beacon") {
95 ctx.physics.remove(beacon);
96 self.beacons.retain(|b| *b != beacon);
97 ctx.play("found");
98 if self.beacons.is_empty() {
99 self.finish(ctx);
100 } else {
101 ctx.speak(format!("Beacon found! {} left.", self.beacons.len()));
102 }
103 }
104 if ctx.ui.closed("done") {
105 ctx.quit();
106 }
107 }More examples
75 fn update(&mut self, ctx: &mut Context) {
76 if ctx.pressed(Key::Escape) {
77 ctx.quit();
78 }
79 if ctx.pressed(Key::Left) || ctx.pressed(Key::Right) {
80 let facing = ctx.physics.turn(self.drone, if ctx.pressed(Key::Left) { -30.0 } else { 30.0 });
81 ctx.speak(math::direction_name(facing));
82 }
83 if ctx.pressed(Key::PageUp) || ctx.pressed(Key::PageDown) {
84 let pitch = ctx.physics.tilt(self.drone, if ctx.pressed(Key::PageUp) { 30.0 } else { -30.0 });
85 ctx.speak(describe_pitch(pitch));
86 }
87
88 // Smooth flight: 4 meters per second while a key is held.
89 let speed = 4.0 * ctx.time.delta();
90 let forward = ctx.input.axis(Key::Down, Key::Up);
91 if forward != 0.0 {
92 let result = ctx.physics.move_forward(self.drone, forward * speed);
93 self.fly(ctx, result);
94 }
95 let rise = ctx.input.axis(Key::Q, Key::E);
96 if rise != 0.0 {
97 let result = ctx.physics.move_up(self.drone, rise * speed);
98 self.fly(ctx, result);
99 }
100
101 if ctx.pressed(Key::C) {
102 let position = ctx.physics.position(self.drone);
103 match ctx.physics.nearest_with_tag(position, "bird") {
104 Some(bird) => {
105 let text = ctx.physics.describe(self.drone, bird); // e.g. "2 o'clock, 9 meters, 6 meters above"
106 ctx.speak(text);
107 }
108 None => ctx.speak("No birds left"),
109 }
110 }
111 if ctx.pressed(Key::F) {
112 let (facing, pitch) = (ctx.physics.facing(self.drone), ctx.physics.pitch(self.drone));
113 ctx.speak(format!("Facing {}, {}", math::direction_name(facing), describe_pitch(pitch)));
114 }
115 if ctx.pressed(Key::H) {
116 let height = ctx.physics.position(self.drone).z;
117 ctx.speak(format!("{height:.0} meters high"));
118 }
119
120 if let Some(bird) = ctx.physics.entered_tag(self.drone, "bird") {
121 ctx.physics.remove(bird);
122 self.birds -= 1;
123 ctx.play("found");
124 if self.birds == 0 {
125 ctx.ui.message("done", "You found every bird!");
126 } else {
127 ctx.speak(format!("Bird found! {} left.", self.birds));
128 }
129 }
130 if ctx.ui.closed("done") {
131 ctx.quit();
132 }
133 }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 landed(&self, body: BodyId) -> Option<f32>
pub fn landed(&self, body: BodyId) -> Option<f32>
If body landed on something this frame: the falling speed in meters per second.
With earth gravity, a 1 m fall lands at about 4.4 m/s, a 3 m fall at 7.7 m/s.
Examples found in repository?
58 fn update(&mut self, ctx: &mut Context) {
59 if ctx.pressed(Key::Escape) {
60 ctx.quit();
61 }
62
63 // The lift goes up for 4 seconds and down for 4 seconds.
64 let lift_up = (ctx.time.elapsed() % 8.0) < 4.0;
65 ctx.physics.set_velocity(self.lift, vec3(0.0, 0.0, if lift_up { 2.0 } else { -2.0 }));
66
67 let run = ctx.input.axis(Key::Left, Key::Right);
68 let mut velocity = ctx.physics.velocity(self.player);
69 velocity.x = run * 6.0;
70 ctx.physics.set_velocity(self.player, velocity);
71 if ctx.pressed(Key::Space) && ctx.physics.jump(self.player, 2.5) {
72 ctx.play("jump");
73 }
74 let running = ctx.physics.on_ground(self.player) && run != 0.0;
75 self.run_sound.set_volume(if running { 0.6 } else { 0.0 });
76
77 if let Some(speed) = ctx.physics.landed(self.player) {
78 ctx.audio.sound("land").volume((speed / 12.0).clamp(0.2, 1.0)).play();
79 if speed > 15.0 {
80 ctx.speak("Ouch!");
81 }
82 }
83 if let Some((other, _)) = ctx.physics.collided(self.player)
84 && ctx.physics.tag(other) == "crate"
85 {
86 ctx.play_on(other, "push");
87 }
88 if let Some(coin) = ctx.physics.entered_tag(self.player, "coin") {
89 ctx.physics.remove(coin); // its looping sound stops by itself
90 self.score += 1;
91 ctx.audio.sound("coin").pitch(1.5).play();
92 ctx.speak(format!("{} of {COINS} coins", self.score));
93 if self.score == COINS {
94 ctx.ui.message("won", "You collected every coin! Press enter to quit.");
95 }
96 }
97 if ctx.ui.closed("won") {
98 ctx.quit();
99 }
100
101 if ctx.pressed(Key::S) {
102 let x = ctx.physics.position(self.player).x;
103 ctx.speak(format!("Score {}, position {x:.0}", self.score));
104 }
105 }Sourcepub fn collided(&self, body: BodyId) -> Option<(BodyId, f32)>
pub fn collided(&self, body: BodyId) -> Option<(BodyId, f32)>
If body started touching another solid body this frame: that body and the impact
speed.
Examples found in repository?
58 fn update(&mut self, ctx: &mut Context) {
59 if ctx.pressed(Key::Escape) {
60 ctx.quit();
61 }
62
63 // The lift goes up for 4 seconds and down for 4 seconds.
64 let lift_up = (ctx.time.elapsed() % 8.0) < 4.0;
65 ctx.physics.set_velocity(self.lift, vec3(0.0, 0.0, if lift_up { 2.0 } else { -2.0 }));
66
67 let run = ctx.input.axis(Key::Left, Key::Right);
68 let mut velocity = ctx.physics.velocity(self.player);
69 velocity.x = run * 6.0;
70 ctx.physics.set_velocity(self.player, velocity);
71 if ctx.pressed(Key::Space) && ctx.physics.jump(self.player, 2.5) {
72 ctx.play("jump");
73 }
74 let running = ctx.physics.on_ground(self.player) && run != 0.0;
75 self.run_sound.set_volume(if running { 0.6 } else { 0.0 });
76
77 if let Some(speed) = ctx.physics.landed(self.player) {
78 ctx.audio.sound("land").volume((speed / 12.0).clamp(0.2, 1.0)).play();
79 if speed > 15.0 {
80 ctx.speak("Ouch!");
81 }
82 }
83 if let Some((other, _)) = ctx.physics.collided(self.player)
84 && ctx.physics.tag(other) == "crate"
85 {
86 ctx.play_on(other, "push");
87 }
88 if let Some(coin) = ctx.physics.entered_tag(self.player, "coin") {
89 ctx.physics.remove(coin); // its looping sound stops by itself
90 self.score += 1;
91 ctx.audio.sound("coin").pitch(1.5).play();
92 ctx.speak(format!("{} of {COINS} coins", self.score));
93 if self.score == COINS {
94 ctx.ui.message("won", "You collected every coin! Press enter to quit.");
95 }
96 }
97 if ctx.ui.closed("won") {
98 ctx.quit();
99 }
100
101 if ctx.pressed(Key::S) {
102 let x = ctx.physics.position(self.player).x;
103 ctx.speak(format!("Score {}, position {x:.0}", self.score));
104 }
105 }Sourcepub fn entered(&self, body: BodyId) -> Option<BodyId>
pub fn entered(&self, body: BodyId) -> Option<BodyId>
If body walked into a sensor this frame: the sensor.
Sourcepub fn entered_tag(&self, body: BodyId, tag: &str) -> Option<BodyId>
pub fn entered_tag(&self, body: BodyId, tag: &str) -> Option<BodyId>
If body walked into a sensor with this tag this frame: the sensor.
if let Some(coin) = ctx.physics.entered_tag(player, "coin") {
ctx.physics.remove(coin); // sounds attached with ctx.loop_on stop by themselves
ctx.play("pickup");
}Examples found in repository?
58 fn update(&mut self, ctx: &mut Context) {
59 if ctx.pressed(Key::Escape) {
60 ctx.quit();
61 }
62
63 // The lift goes up for 4 seconds and down for 4 seconds.
64 let lift_up = (ctx.time.elapsed() % 8.0) < 4.0;
65 ctx.physics.set_velocity(self.lift, vec3(0.0, 0.0, if lift_up { 2.0 } else { -2.0 }));
66
67 let run = ctx.input.axis(Key::Left, Key::Right);
68 let mut velocity = ctx.physics.velocity(self.player);
69 velocity.x = run * 6.0;
70 ctx.physics.set_velocity(self.player, velocity);
71 if ctx.pressed(Key::Space) && ctx.physics.jump(self.player, 2.5) {
72 ctx.play("jump");
73 }
74 let running = ctx.physics.on_ground(self.player) && run != 0.0;
75 self.run_sound.set_volume(if running { 0.6 } else { 0.0 });
76
77 if let Some(speed) = ctx.physics.landed(self.player) {
78 ctx.audio.sound("land").volume((speed / 12.0).clamp(0.2, 1.0)).play();
79 if speed > 15.0 {
80 ctx.speak("Ouch!");
81 }
82 }
83 if let Some((other, _)) = ctx.physics.collided(self.player)
84 && ctx.physics.tag(other) == "crate"
85 {
86 ctx.play_on(other, "push");
87 }
88 if let Some(coin) = ctx.physics.entered_tag(self.player, "coin") {
89 ctx.physics.remove(coin); // its looping sound stops by itself
90 self.score += 1;
91 ctx.audio.sound("coin").pitch(1.5).play();
92 ctx.speak(format!("{} of {COINS} coins", self.score));
93 if self.score == COINS {
94 ctx.ui.message("won", "You collected every coin! Press enter to quit.");
95 }
96 }
97 if ctx.ui.closed("won") {
98 ctx.quit();
99 }
100
101 if ctx.pressed(Key::S) {
102 let x = ctx.physics.position(self.player).x;
103 ctx.speak(format!("Score {}, position {x:.0}", self.score));
104 }
105 }More examples
58 fn update(&mut self, ctx: &mut Context) {
59 if ctx.pressed(Key::Escape) {
60 ctx.push_scene(Pause);
61 }
62 if ctx.pressed(Key::Left) || ctx.pressed(Key::Right) {
63 let degrees = if ctx.pressed(Key::Left) { -45.0 } else { 45.0 };
64 let facing = ctx.physics.turn(self.player, degrees);
65 ctx.speak(math::direction_name(facing));
66 }
67
68 let forward = ctx.input.repeating(Key::Up, 0.35, 0.35);
69 let backward = ctx.input.repeating(Key::Down, 0.35, 0.35);
70 if forward || backward {
71 let step = if forward { 1.0 } else { -1.0 };
72 if ctx.physics.move_forward(self.player, step).blocked {
73 ctx.play("wall");
74 } else {
75 ctx.audio.sound("step").random_pitch(0.85, 1.15).play();
76 }
77 }
78
79 if ctx.pressed(Key::C) {
80 let position = ctx.physics.position(self.player);
81 match ctx.physics.nearest_with_tag(position, "beacon") {
82 Some(beacon) => {
83 let text = ctx.physics.describe(self.player, beacon);
84 ctx.speak(text);
85 }
86 None => ctx.speak("No beacons left"),
87 }
88 }
89 if ctx.pressed(Key::F) {
90 let facing = ctx.physics.facing(self.player);
91 ctx.speak(format!("Facing {}", math::direction_name(facing)));
92 }
93
94 if let Some(beacon) = ctx.physics.entered_tag(self.player, "beacon") {
95 ctx.physics.remove(beacon);
96 self.beacons.retain(|b| *b != beacon);
97 ctx.play("found");
98 if self.beacons.is_empty() {
99 self.finish(ctx);
100 } else {
101 ctx.speak(format!("Beacon found! {} left.", self.beacons.len()));
102 }
103 }
104 if ctx.ui.closed("done") {
105 ctx.quit();
106 }
107 }75 fn update(&mut self, ctx: &mut Context) {
76 if ctx.pressed(Key::Escape) {
77 ctx.quit();
78 }
79 if ctx.pressed(Key::Left) || ctx.pressed(Key::Right) {
80 let facing = ctx.physics.turn(self.drone, if ctx.pressed(Key::Left) { -30.0 } else { 30.0 });
81 ctx.speak(math::direction_name(facing));
82 }
83 if ctx.pressed(Key::PageUp) || ctx.pressed(Key::PageDown) {
84 let pitch = ctx.physics.tilt(self.drone, if ctx.pressed(Key::PageUp) { 30.0 } else { -30.0 });
85 ctx.speak(describe_pitch(pitch));
86 }
87
88 // Smooth flight: 4 meters per second while a key is held.
89 let speed = 4.0 * ctx.time.delta();
90 let forward = ctx.input.axis(Key::Down, Key::Up);
91 if forward != 0.0 {
92 let result = ctx.physics.move_forward(self.drone, forward * speed);
93 self.fly(ctx, result);
94 }
95 let rise = ctx.input.axis(Key::Q, Key::E);
96 if rise != 0.0 {
97 let result = ctx.physics.move_up(self.drone, rise * speed);
98 self.fly(ctx, result);
99 }
100
101 if ctx.pressed(Key::C) {
102 let position = ctx.physics.position(self.drone);
103 match ctx.physics.nearest_with_tag(position, "bird") {
104 Some(bird) => {
105 let text = ctx.physics.describe(self.drone, bird); // e.g. "2 o'clock, 9 meters, 6 meters above"
106 ctx.speak(text);
107 }
108 None => ctx.speak("No birds left"),
109 }
110 }
111 if ctx.pressed(Key::F) {
112 let (facing, pitch) = (ctx.physics.facing(self.drone), ctx.physics.pitch(self.drone));
113 ctx.speak(format!("Facing {}, {}", math::direction_name(facing), describe_pitch(pitch)));
114 }
115 if ctx.pressed(Key::H) {
116 let height = ctx.physics.position(self.drone).z;
117 ctx.speak(format!("{height:.0} meters high"));
118 }
119
120 if let Some(bird) = ctx.physics.entered_tag(self.drone, "bird") {
121 ctx.physics.remove(bird);
122 self.birds -= 1;
123 ctx.play("found");
124 if self.birds == 0 {
125 ctx.ui.message("done", "You found every bird!");
126 } else {
127 ctx.speak(format!("Bird found! {} left.", self.birds));
128 }
129 }
130 if ctx.ui.closed("done") {
131 ctx.quit();
132 }
133 }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 left(&self, body: BodyId) -> Option<BodyId>
pub fn left(&self, body: BodyId) -> Option<BodyId>
If body left a sensor this frame: the sensor.
Sourcepub fn vehicle(&self, id: BodyId) -> Option<&Vehicle>
pub fn vehicle(&self, id: BodyId) -> Option<&Vehicle>
The vehicle part of a body, if it is a car or truck.
if let Some(v) = ctx.physics.vehicle(car) {
let text = v.describe_speed();
ctx.speak(text);
}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 vehicle_mut(&mut self, id: BodyId) -> Option<&mut Vehicle>
pub fn vehicle_mut(&mut self, id: BodyId) -> Option<&mut Vehicle>
Mutable access to the vehicle part of a body: pedals, steering, load, fuel, settings.
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 weight(&self, id: BodyId) -> f32
pub fn weight(&self, id: BodyId) -> f32
Total weight of a body in kilograms: its mass plus the load of its vehicle (0 if the body does not exist).
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 speed(&self, id: BodyId) -> f32
pub fn speed(&self, id: BodyId) -> f32
How fast a body moves in meters per second: the length of its velocity. For
vehicles this is their driving speed. Kinematic bodies moved with move_by have no
velocity, so they report 0.
Sourcepub fn crashed(&self, vehicle: BodyId) -> Option<(BodyId, f32)>
pub fn crashed(&self, vehicle: BodyId) -> Option<(BodyId, f32)>
If vehicle crashed into something this frame: what it hit and the speed lost in
meters per second.
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 gear_changed(&self, vehicle: BodyId) -> Option<i32>
pub fn gear_changed(&self, vehicle: BodyId) -> Option<i32>
If vehicle changed gear this frame: the new gear (-1 reverse, 0 neutral, 1 and up).
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§
Auto Trait Implementations§
impl Freeze for World
impl RefUnwindSafe for World
impl Send for World
impl Sync for World
impl Unpin for World
impl UnsafeUnpin for World
impl UnwindSafe for World
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.