Skip to content

03 Initialization

This chapter introduces the initialization pattern and how engines use it.

Initialization Pattern

A level often has global values that need to be calculated once and made available to other entities.

For example, the stage area may change with the screen's aspect ratio. Instead of calculating it every time it is needed, we can calculate it once and store it in shared data.

The Initialization archetype runs the level's one-time setup. Its preprocess callback runs when the level loads, before any entity spawns. The Initialization entity later enters the spawn queue first and despawns so the remaining entities can become active.

The project template already implements this pattern. Open guide/play/initialization.py to follow along with the code in this chapter.

Spawning Logic

The spawning logic for our Initialization entity is simple: it needs to spawn before every other entity.

To put it first, its spawn_order callback returns a value lower than the value returned by every other entity. We use -10 for Initialization:

python
class Initialization(PlayArchetype):
    # ...

    def spawn_order(self) -> float:
        return -10

    # ...

Initialization Workload

Use preprocess for setup that runs while the level loads. The update_sequential callback runs later while the entity is active. The template uses it only to schedule the Initialization entity's despawn.

We will use preprocess to set up the engine coordinate system, gameplay UI, scoring, and life before the level starts.

Open guide/lib/ui.py. The project template keeps runtime UI setup in the shared init_ui helper so that each mode can reuse it. The helper initially configures only the menu button, which allows us to exit the development level:

python
from sonolus.script.runtime import HorizontalAlign, runtime_ui, safe_area
from sonolus.script.vec import Vec2


def init_ui():
    ui = runtime_ui()
    ui.menu.update(
        anchor=safe_area().tl + Vec2(0.05, -0.05),
        pivot=Vec2(0, 1),
        dimensions=Vec2(0.15, 0.15) * ui.menu_config.scale,
        rotation=0,
        alpha=ui.menu_config.alpha,
        horizontal_align=HorizontalAlign.CENTER,
        background=True,
    )

Initialization.preprocess already calls this helper in guide/play/initialization.py. Later chapters will extend init_ui as they introduce more UI elements. Watch, Preview, and Tutorial will reuse the completed layouts:

python
from guide.lib.ui import init_ui


class Initialization(PlayArchetype):
    def preprocess(self):
        init_ui()

    # ...

Despawning

An entity is scheduled to despawn at the end of the current frame by assigning True to self.despawn.

For Initialization, we do this in update_sequential:

python
class Initialization(PlayArchetype):
    # ...

    def update_sequential(self):
        self.despawn = True