Engine Lifecycle¶
ArepyEngine is the high-level entry point for creating windows, worlds, renderers, input, audio, and shared resources.
Creating an engine¶
Creating an engine is usually the first thing you do. In many cases, a title and the default settings are enough to get going.
The constructor signature is:
ArepyEngine(
title: str = "Arepy Engine",
width: int = 640,
height: int = 360,
max_frame_rate: int = 800,
fullscreen: bool = False,
vsync: bool = False,
icon_path: PathLike[str] | None = None,
)
If you want more control, you can also pass:
title: strsets the window title shown in the title barwidth: intsets the window width in pixels when the window is createdheight: intsets the window height in pixels when the window is createdmax_frame_rate: intis passed toRenderer2D.set_max_framerate(...)during engine startupfullscreen: booldecides whetherDisplay.toggle_fullscreen()is called right after the window opensvsync: boolis passed toDisplay.set_vsync(...)before the window is createdicon_path: PathLike[str] | Noneis passed toDisplay.set_window_icon(...)when you want a custom window icon
Here is a more explicit example:
from pathlib import Path
from arepy import ArepyEngine
engine = ArepyEngine(
title="Space Garden",
width=1280,
height=720,
max_frame_rate=144,
fullscreen=False,
vsync=True,
icon_path=Path("assets/icon.png"),
)
All of these values are passed as normal Python keyword arguments when you create the engine instance.
When the engine starts, it opens the window and makes these shared services available across the app:
DisplayRenderer2DRenderer3DAssetStoreInputArepyEngineAudioDeviceEventManagerImgui
That lets you create a world and start adding systems without having to wire every subsystem by hand.
Worlds¶
A world is a named container around an ECS Registry.
The methods you usually call are:
engine = ArepyEngine(title="My Game")
world = engine.create_world("main")
engine.set_current_world("main")
create_world(name: str) expects the world name as a string and returns a new World.
set_current_world(name: str) also expects the world name as a string. You pass the name of a world that was already created.
create_world(name) creates a World that can see the engine's shared services, while still keeping room for world-specific resources and callbacks.
Current frame order¶
The runtime loop implemented in ArepyEngine.run() currently works like this:
- call
on_startup()once - while the window stays open:
- process the next frame
- apply any deferred world switch
- call
on_shutdown()once
Inside a frame, the order is:
INPUTpipeline- registry
update() UPDATEpipeline- world
on_update()hooks - engine
on_update()hook RENDERpipelineRENDER_UIpipeline- world
on_render()hooks - engine
on_render()hook - ImGui backend render
- renderer buffer swap
World lifecycle hooks¶
Besides the engine-level hooks, each world can register its own lifecycle callbacks.
world = engine.create_world("main")
@world.on_startup
def load_scene() -> None:
...
@world.on_update
def update_hud() -> None:
...
@world.on_render
def draw_debug_overlay() -> None:
...
@world.on_shutdown
def release_scene() -> None:
...
These hooks are useful when you want a little world-specific setup or teardown without creating a dedicated ECS system for it.
on_startupruns when that world becomes the current worldon_updateruns once per frame after theUPDATEpipelineon_renderruns once per frame afterRENDERandRENDER_UIon_shutdownruns when you leave that world or when the engine closes
on_update and on_render are optional. They are most useful for glue code, scene orchestration, UI state, or one-off world behaviors that do not fit naturally into a regular ECS system.
Pipeline meanings¶
The enum currently defines these phases:
UPDATERENDERINPUTPHYSICSASYNC_UPDATERENDER_UI
Only the phases explicitly called by ArepyEngine are part of the default frame loop today. If you depend on an additional pipeline such as PHYSICS, you currently need to orchestrate it through your own systems or engine customization.
World switching¶
set_current_world(name) does not switch immediately. It stores the next world name and applies the change after the current frame step. When the switch happens, the previous world receives on_shutdown, and the new world receives on_startup.