PyBevy is in an early and experimental stage. The API is incomplete, subject to breaking changes without notice, and you should expect bugs. Many features are still under development.
Timers and Time
Use timers for cooldowns, spawning, and control game time with pause and slow motion.
Introduction
Most games need time-based logic: cooldowns, spawn rates, delayed actions. pybevy
provides Timer and Stopwatch for tracking durations, and virtual time controls
for pausing and slow motion.
This example spawns a cube every 2 seconds using a repeating timer, and lets you pause/unpause the game with the Space bar.
from pybevy.prelude import *
from pybevy.time import Timer, TimerMode, TimeVirtualThe Spawn Timer
We store our timer inside a Resource so it persists across frames.
TimerMode.REPEATING makes it reset automatically each time it finishes.
@resource
class SpawnTimer(Resource):
def __init__(self):
self.timer = Timer.from_seconds(2.0, TimerMode.REPEATING)Setup
We spawn a camera, a light, and insert our timer resource.
def setup(commands: Commands):
commands.spawn(Camera3d(), Transform.from_xyz(0.0, 10.0, 20.0).looking_at(Vec3.ZERO, Vec3.Y))
commands.spawn(DirectionalLight(illuminance=5000.0), Transform.IDENTITY.looking_at(Vec3(-1.0, -1.0, -1.0), Vec3.Y))
commands.insert_resource(SpawnTimer())Spawning on a Timer
Every frame, we advance (tick) the timer by the frame's delta time.
When the timer finishes, just_finished() returns True for exactly
one frame, and we spawn a new cube.
cube_count = 0
def spawn_cubes(
commands: Commands,
time: Res[Time],
spawn_timer: ResMut[SpawnTimer],
meshes: ResMut[Assets[Mesh]],
materials: ResMut[Assets[StandardMaterial]],
):
global cube_count
spawn_timer.timer.tick(time.delta())
if spawn_timer.timer.just_finished():
# Place cubes in a row
x = (cube_count % 10 - 5) * 1.5
z = (cube_count // 10) * -1.5
commands.spawn(
Mesh3d(meshes.add(Cuboid.from_length(1.0))),
MeshMaterial3d(materials.add(Color.srgb(0.2, 0.6, 0.8))),
Transform.from_xyz(x, 0.5, z),
)
cube_count += 1Pause and Slow Motion
TimeVirtual lets you pause or change the speed of game time.
When paused, time.delta() returns zero, so timers stop advancing.
- Space: Toggle pause
- 1: Normal speed
- 2: Half speed (slow motion)
- 3: Double speed
def time_controls(
keyboard: Res[ButtonInput],
time_virtual: ResMut[TimeVirtual],
):
if keyboard.just_pressed(KeyCode.Space):
if time_virtual.is_paused():
time_virtual.unpause()
else:
time_virtual.pause()
if keyboard.just_pressed(KeyCode.Digit1):
time_virtual.set_relative_speed(1.0)
if keyboard.just_pressed(KeyCode.Digit2):
time_virtual.set_relative_speed(0.5)
if keyboard.just_pressed(KeyCode.Digit3):
time_virtual.set_relative_speed(2.0)Running the App
@entrypoint
def main(app: App) -> App:
return (
app
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.add_systems(Update, (spawn_cubes, time_controls))
)
if __name__ == "__main__":
main().run()