03 Stage
In this chapter, we will add PreviewStage and draw the 10 temporary panels.
Stage Archetype
First, create guide/preview/stage.py and set up PreviewStage, a subclass of PreviewArchetype, as follows:
python
from sonolus.script.archetype import PreviewArchetype
from guide.lib import archetype_names
class PreviewStage(PreviewArchetype):
name = archetype_names.STAGEUsing the same archetype name as play mode lets PreviewStage handle the Stage entity already present in the level.
Then register it in the archetypes list in guide/preview/mode.py:
python
from guide.preview.stage import PreviewStage
preview_mode = PreviewMode(
archetypes=[
PreviewInitialization,
PreviewStage,
],
skin=Skin,
)Declaring
Even though the stage in play mode has only a judgment line, it is best to draw lanes and borders in preview so players can visualize each panel. Map fields in the shared Skin class to stage sprites from the StandardSprite class. In guide/lib/skin.py, add these fields to the existing Skin class. Keep all fields added in the Play and Watch sections. These fields reuse standard resources supplied by the selected skin, so no new image assets are needed:
python
from sonolus.script.sprite import StandardSprite, skin
@skin
class Skin:
# ...
stage_middle: StandardSprite.STAGE_MIDDLE
stage_left_border: StandardSprite.STAGE_LEFT_BORDER
stage_right_border: StandardSprite.STAGE_RIGHT_BORDERDrawing
Preview calls each entity's render callback. In guide/preview/stage.py, add render and keep the panel loop in a separate render_panels method. Each loop iteration offsets one panel by PANEL_WIDTH. The lane occupies the middle 3 units and the borders sit on its left and right edges:
python
from sonolus.script.archetype import PreviewArchetype
from sonolus.script.quad import Rect
from sonolus.script.vec import Vec2
from guide.lib.skin import Skin
from guide.preview.chart import PANEL_COUNT, PANEL_HEIGHT, PANEL_WIDTH
class PreviewStage(PreviewArchetype):
def render(self):
self.render_panels()
def render_panels(self):
for i in range(PANEL_COUNT):
x = i * PANEL_WIDTH
middle = Rect(l=-1.5, r=1.5, b=0, t=PANEL_HEIGHT).translate(Vec2(x, 0))
left_border = Rect(l=-1.75, r=-1.5, b=0, t=PANEL_HEIGHT).translate(Vec2(x, 0))
right_border = Rect(l=1.5, r=1.75, b=0, t=PANEL_HEIGHT).translate(Vec2(x, 0))
Skin.stage_middle.draw(middle, z=0)
Skin.stage_left_border.draw(left_border, z=0)
Skin.stage_right_border.draw(right_border, z=0)Checkpoint
Refresh Preview in the Sonolus app. You should be able to scroll horizontally through 10 panels. Each panel should contain the 3-unit-wide lane between two borders.