import numpy as np
from pybevy.prelude import *
@component
class Marker(Component):
class FPSCounter:
def __init__(self) -> None:
self.last_time: float = 0.0
self.frame_count: int = 0
COUNT = 20_000_000
def spawn_entities(world: World) -> None:
print(f"Spawning {COUNT:,} entities...")
grid_size = int(COUNT ** (1.0 / 3.0))
i = np.arange(COUNT, dtype=np.float32)
x = (i % grid_size) * 0.5
y = ((i // grid_size) % grid_size) * 0.5
z = (i // (grid_size * grid_size)) * 0.5
positions = np.stack([x, y, z], axis=1)
batch = Transform.from_numpy(translation=positions)
entities = world.commands().spawn_batch(batch, Marker())
print(f"Spawned {len(entities):,} entities.")
def update_positions(
time: Res[Time],
view: View[Mut[Transform], With[Marker]],
) -> None:
t = time.elapsed_secs()
transform = view.column_mut(Transform)
transform.translation.y = (
transform.translation.y + (transform.translation.x * 0.01 + t).sin() * 0.1
)
def print_stats(
time: Res[Time],
fps_counter: Local[FPSCounter],
) -> None:
current_time = time.elapsed_secs()
fps_counter.frame_count += 1
time_since_last = current_time - fps_counter.last_time
if time_since_last >= 1.0:
fps = fps_counter.frame_count / time_since_last
print(f"Frame at {current_time:.1f}s | FPS: {fps:.1f}")
fps_counter.last_time = current_time
fps_counter.frame_count = 0
@entrypoint
def main(app: App) -> App:
return (
app.add_plugins(MinimalPlugins)
.add_systems(Startup, spawn_entities)
.add_systems(Update, (update_positions, print_stats))
)
if __name__ == "__main__":
main().run()