pub struct Time { /* private fields */ }Expand description
Frame timing and a simple named-event scheduler. Available as ctx.time.
// Fire an event called "spawn" every 2.5 seconds of game time.
ctx.time.every("spawn", 2.5);
// ...later, in update():
if ctx.time.fired("spawn") {
ctx.speech.speak("A new enemy appears");
}Implementations§
Source§impl Time
impl Time
Sourcepub fn delta(&self) -> f32
pub fn delta(&self) -> f32
Seconds of game time since the previous frame (affected by Time::set_scale).
Multiply speeds by this to make movement frame rate independent:
position.x += speed * ctx.time.delta();
Examples found in repository?
228 fn update(&mut self, ctx: &mut Context) {
229 if self.over {
230 if ctx.ui.closed("over") {
231 ctx.switch_scene(Title);
232 }
233 return;
234 }
235 if ctx.pressed(Key::Escape) {
236 ctx.switch_scene(Title);
237 return;
238 }
239 if ctx.pressed(Key::S) {
240 ctx.speak(format!("{} bells, {} lives", self.score, self.lives));
241 }
242 for (key, step) in [(Key::Left, -1), (Key::Right, 1)] {
243 if ctx.input.repeating(key, 0.3, 0.15) {
244 let lane = (self.lane + step).clamp(-LANES, LANES);
245 if lane == self.lane {
246 ctx.play("edge");
247 } else {
248 self.lane = lane;
249 ctx.audio.sound("step").at(vec3(step as f32 * 0.5, 0.0, 0.0)).random_pitch(0.9, 1.1).play();
250 }
251 }
252 }
253
254 let dt = ctx.time.delta();
255 if self.left < 0.0 {
256 self.left += dt;
257 if self.left >= 0.0 {
258 self.drop_bell();
259 }
260 return;
261 }
262 self.left -= dt;
263 self.next_ring -= dt;
264 if self.left <= 0.0 {
265 self.land(ctx);
266 } else if self.next_ring <= 0.0 {
267 self.ring(ctx);
268 }
269 }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 real_delta(&self) -> f32
pub fn real_delta(&self) -> f32
Like Time::delta but ignores the time scale. Useful for menus while the game is paused.
Sourcepub fn elapsed(&self) -> f64
pub fn elapsed(&self) -> f64
Seconds of game time since the game started.
Examples found in repository?
14 fn update(&mut self, ctx: &mut Context) {
15 if ctx.input.pressed(Key::Space) {
16 // A pitch that rises over time, so every beep sounds different.
17 let pitch = 300.0 + (ctx.time.elapsed() as f32 * 50.0) % 900.0;
18 ctx.audio.play_tone(pitch.round(), 0.15);
19 }
20 if ctx.input.pressed(Key::F1) {
21 ctx.speech.repeat_last();
22 }
23 if ctx.input.pressed(Key::Escape) {
24 ctx.quit();
25 }
26 }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 real_elapsed(&self) -> Duration
pub fn real_elapsed(&self) -> Duration
Wall clock time since the engine started, ignoring the time scale.
Sourcepub fn set_scale(&mut self, scale: f32)
pub fn set_scale(&mut self, scale: f32)
Speeds up (> 1.0), slows down (< 1.0) or pauses (0.0) game time.
Physics, the scheduler and Time::delta all follow the scale.
Sourcepub fn after(&mut self, name: impl Into<String>, seconds: f32)
pub fn after(&mut self, name: impl Into<String>, seconds: f32)
Schedules a one-shot event named name that fires after seconds of game time.
Scheduling a name that is already pending replaces it.
Examples found in repository?
8fn main() -> audio_code::Result<()> {
9 let mut score = 0;
10
11 audio_code::run("Clicker", move |ctx| {
12 if ctx.once("intro") {
13 let best: u32 = ctx.storage.get_or("best", 0);
14 ctx.speak(format!("Press space as often as you can in ten seconds. Your best is {best}. Go!"));
15 ctx.time.after("end", 10.0);
16 }
17
18 if ctx.time.is_scheduled("end") && ctx.pressed(Key::Space) {
19 score += 1;
20 ctx.audio.play_tone(300.0 + score as f32 * 15.0, 0.05);
21 }
22
23 if ctx.time.fired("end") {
24 let best: u32 = ctx.storage.get_or("best", 0);
25 if score > best {
26 ctx.storage.set("best", score);
27 ctx.ui.message("result", format!("{score} presses. New record!"));
28 } else {
29 ctx.ui.message("result", format!("{score} presses. Your best is {best}."));
30 }
31 }
32
33 if ctx.ui.closed("result") || ctx.pressed(Key::Escape) {
34 ctx.quit();
35 }
36 })
37}Sourcepub fn every(&mut self, name: impl Into<String>, seconds: f32)
pub fn every(&mut self, name: impl Into<String>, seconds: f32)
Schedules a repeating event named name that fires every seconds of game time.
Scheduling a name that is already pending replaces it.
Sourcepub fn cancel(&mut self, name: &str)
pub fn cancel(&mut self, name: &str)
Cancels a scheduled event. Does nothing if it does not exist.
Sourcepub fn is_scheduled(&self, name: &str) -> bool
pub fn is_scheduled(&self, name: &str) -> bool
Whether an event with this name is waiting to fire.
Examples found in repository?
8fn main() -> audio_code::Result<()> {
9 let mut score = 0;
10
11 audio_code::run("Clicker", move |ctx| {
12 if ctx.once("intro") {
13 let best: u32 = ctx.storage.get_or("best", 0);
14 ctx.speak(format!("Press space as often as you can in ten seconds. Your best is {best}. Go!"));
15 ctx.time.after("end", 10.0);
16 }
17
18 if ctx.time.is_scheduled("end") && ctx.pressed(Key::Space) {
19 score += 1;
20 ctx.audio.play_tone(300.0 + score as f32 * 15.0, 0.05);
21 }
22
23 if ctx.time.fired("end") {
24 let best: u32 = ctx.storage.get_or("best", 0);
25 if score > best {
26 ctx.storage.set("best", score);
27 ctx.ui.message("result", format!("{score} presses. New record!"));
28 } else {
29 ctx.ui.message("result", format!("{score} presses. Your best is {best}."));
30 }
31 }
32
33 if ctx.ui.closed("result") || ctx.pressed(Key::Escape) {
34 ctx.quit();
35 }
36 })
37}Sourcepub fn remaining(&self, name: &str) -> Option<f32>
pub fn remaining(&self, name: &str) -> Option<f32>
Seconds until the named event fires, or None if it is not scheduled.
Sourcepub fn fired(&self, name: &str) -> bool
pub fn fired(&self, name: &str) -> bool
Returns true during the frame in which the named event fired.
Examples found in repository?
8fn main() -> audio_code::Result<()> {
9 let mut score = 0;
10
11 audio_code::run("Clicker", move |ctx| {
12 if ctx.once("intro") {
13 let best: u32 = ctx.storage.get_or("best", 0);
14 ctx.speak(format!("Press space as often as you can in ten seconds. Your best is {best}. Go!"));
15 ctx.time.after("end", 10.0);
16 }
17
18 if ctx.time.is_scheduled("end") && ctx.pressed(Key::Space) {
19 score += 1;
20 ctx.audio.play_tone(300.0 + score as f32 * 15.0, 0.05);
21 }
22
23 if ctx.time.fired("end") {
24 let best: u32 = ctx.storage.get_or("best", 0);
25 if score > best {
26 ctx.storage.set("best", score);
27 ctx.ui.message("result", format!("{score} presses. New record!"));
28 } else {
29 ctx.ui.message("result", format!("{score} presses. Your best is {best}."));
30 }
31 }
32
33 if ctx.ui.closed("result") || ctx.pressed(Key::Escape) {
34 ctx.quit();
35 }
36 })
37}Sourcepub fn fired_events(&self) -> impl Iterator<Item = &str>
pub fn fired_events(&self) -> impl Iterator<Item = &str>
All events that fired this frame.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for Time
impl RefUnwindSafe for Time
impl Send for Time
impl Sync for Time
impl Unpin for Time
impl UnsafeUnpin for Time
impl UnwindSafe for Time
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> 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.