← Quick Reference
08

QUICK REFERENCE

Scene

Package setup, updates, and input into reusable menus, levels, or application states.
  • Lifecycle
  • Activation
  • Input
  • State changes
01

Defining a Scene

Subclass Scene to keep the objects and input behavior for one application state together. start() creates that state's Screen contents after the Scene has been activated.

class MyScene(Scene)

Define a reusable Screen state by subclassing Scene.

scene.start()

Initialize objects and state when the Scene is activated.

scene.screen()

Return the Screen currently bound to the Scene, or None before activation.

Example
class MenuScene(Scene):
    def start(self):
        screen = self.screen()
        self.title = Text(
            screen, "My game",
            screen.center(), size=32
        )
        self.title.center(screen.center())
Scene state
class GameScene(Scene):
    def __init__(self):
        super().__init__()
        self.score = 0

    def start(self):
        self.player = Rectangle(
            self.screen(), 40, 40, 50, 50,
            Color("blue")
        )
02

Activation lifecycle

Applying a Scene stops and clears the previous state, binds the new Scene, registers its input methods, and calls start(). The Screen then calls update() once per frame until another Scene is requested.

screen.scene(scene)

Reset the Screen and activate a Scene instance.

screen.scene()

Return the currently active Scene, or None when no Scene has been applied.

scene.start()

Build objects and initialize state once when the Scene becomes active.

scene.update() · scene.update(dt)

Advance one frame, optionally receiving elapsed seconds since the previous frame.

scene.stop()

Clean up once before the Scene is detached and its Screen objects are removed.

Example
menu = MenuScene()
screen.scene(menu)

print(screen.scene() is menu)  # True
screen.loop()
Lifecycle hooks
class LevelScene(Scene):
    def start(self):
        self.player = Rectangle(
            self.screen(), 40, 40, 50, 50,
            Color("blue")
        )

    def update(self):
        self.player.rotate(1)

    def stop(self):
        print("Level complete")
03

Scene input

Input handlers become methods on the Scene. screen.scene(...) registers them automatically, so an activated Scene does not call screen.listen() itself.

scene.keydown(key) · scene.keyup(key)

Handle normalized keyboard presses and releases.

scene.mousedown(location, button) · scene.mouseup(location, button)

Handle pointer-button presses and releases.

scene.mousedrag(location, button) · scene.mousemove(location)

Handle pointer movement with or without a held button.

Example
class GameScene(Scene):
    def start(self):
        self.player = Rectangle(
            self.screen(), 40, 40, 50, 50,
            Color("blue")
        )

    def keydown(self, key):
        if key == "left":
            self.player.move(-5, 0)
        elif key == "right":
            self.player.move(5, 0)

    def mousedown(self, location, button):
        if button == 1:
            self.player.center(location)
04

Switching scenes

Request another Scene to move between menus, levels, and results screens. Transitions requested during input or update() wait for the safe frame boundary, so the current callback can return normally.

self.goto(NextScene())

Request a fresh Scene from an input or update method.

self.goto(existing_scene)

Reactivate an existing instance while retaining its ordinary Python attributes.

screen.scene(scene)

Apply an initial Scene or switch directly from code outside the active update.

Example
class MenuScene(Scene):
    def start(self):
        self.button = Rectangle(
            self.screen(), 220, 160, 200, 70,
            Color("green")
        )

    def mousedown(self, location, button):
        if button == 1 and self.button.contains(location):
            self.goto(GameScene())

screen.scene(MenuScene())
screen.loop()
Return to a menu
class GameScene(Scene):
    def keydown(self, key):
        if key == "escape":
            self.goto(MenuScene())
05

Animated scenes

The Screen owns the only application loop and automatically advances the active Scene. Put one frame of animation or game logic in update(); do not start another loop inside the Scene.

scene.update()

Run one frame when the Scene does not need elapsed time.

scene.update(dt)

Run one frame with elapsed seconds for frame-rate-independent motion.

screen.loop()

Process input, call the active Scene's update method, and present every frame.

Example
class GameScene(Scene):
    SPEED = 180

    def start(self):
        self.ball = Oval(
            self.screen(), 40, 100, 30, 30,
            Color("orange")
        )

    def update(self, dt):
        self.ball.move(self.SPEED * dt, 0)

screen.scene(GameScene())
screen.loop()