Skip to content

02 Screen

In this chapter, we will define the panel dimensions and configure the preview coordinate system and canvas.

Panels

In vertical scrolling rhythm games, preview is typically rendered as many vertical panels laid out horizontally from left to right.

Create guide/preview/chart.py and add the panel parameters. Each panel is 7 local units wide: 3 units for the lanes and 2 units of padding on each side. PANEL_HEIGHT is both the panel's height in local coordinates and the number of seconds it displays. A value of 2 therefore makes each panel 2 seconds tall. Later, we will calculate the panel count from the visible events in the level. Use 10 panels for now.

python
PANEL_WIDTH = 7
PANEL_HEIGHT = 2

PANEL_COUNT = 10

Preview Coordinate System

As in play mode, we should transform the coordinate system used to draw skin sprites. This does not change the screen coordinates returned by screen(). Sonolus.py provides Transform2d for composing these transforms.

Move the origin to the center-bottom of the first panel. One local x unit will be 1/20 of the screen height. Scaling the y axis by screen().h / PANEL_HEIGHT makes the full local height of one panel fill the screen, so one local y unit also represents one second of gameplay. Call the shared init_ui helper so preview uses the same UI layouts as the other modes.

The canvas is the scrollable preview area. It scrolls from left to right. Its size along that direction is the width of all 10 temporary panels, converted to screen coordinates with the x-axis scale.

Replace guide/preview/initialization.py with this complete implementation:

python
from sonolus.script.archetype import PreviewArchetype
from sonolus.script.runtime import ScrollDirection, canvas, screen, set_skin_transform
from sonolus.script.transform import Transform2d
from sonolus.script.vec import Vec2

from guide.lib import archetype_names
from guide.lib.ui import init_ui
from guide.preview.chart import PANEL_COUNT, PANEL_HEIGHT, PANEL_WIDTH


class PreviewInitialization(PreviewArchetype):
    name = archetype_names.INITIALIZATION

    def preprocess(self):
        init_ui()

        transform = (
            Transform2d.new()
            .translate(Vec2(PANEL_WIDTH / 2, 0))
            .scale(Vec2(screen().h / 20, screen().h / PANEL_HEIGHT))
            .translate(screen().bl)
        )
        set_skin_transform(transform)

        canvas().update(
            scroll_direction=ScrollDirection.LEFT_TO_RIGHT,
            size=PANEL_COUNT * PANEL_WIDTH * screen().h / 20,
        )

Checkpoint

Reload Preview in Sonolus. The canvas is still blank because the next chapter adds the stage panels.