Skip to main content

Scena

Creative graphics and 2D games in Python, made for learning to program.
Easy to begin. Space to grow.

Tutorial · API Guide · Examples · Changelog

Naves: a space shooter from the tutorial. A red ship fires at a breathing fleet, enemies explode, and a plasma shield catches the enemy fire.

Scena is a Python framework for drawing, animating and making games, written for people who are learning to program. You write what is on the screen and what should happen; Scena runs the loop, draws every frame, moves the animations, checks the collisions and cleans up after you. It draws with Skia (the engine behind Chrome and Android), so even a first program looks good.

A whole game, one screen of code

from random import uniform
from scena import *

init(width=800, height=600, title="Catch the stars")
Wallpaper("dark navy")

st.score = 0
label = Text(text="", top_left=(20, 580), font_size=22)
label["text"] @= lambda: f"Stars: {st.score}"

paddle = Sprite("k-rolling-ball/button_blue.png", width=90, center=(400, 50), group="paddle")


@every(0.5)
def drop_star():
    star = Sprite("k-rolling-ball/star.png", size=36, center=(uniform(40, 760), 580), group="stars")
    star.glow = True


def update(dt):
    if keyp("LEFT"):
        paddle.move_by(-420 * dt, 0)
    if keyp("RIGHT"):
        paddle.move_by(420 * dt, 0)
    group["stars"].move_by(0, -180 * dt)


@collide("paddle", "stars")
def catch(paddle, star):
    star.destroy()
    st.score += 1
    paddle.pop(scale=1.25)


@leave_playfield("stars")
def missed(star):
    star.destroy()


run()

The program above running: stars fall, the paddle catches them, the score counts up.

No game loop to write, no event queue to poll, no list of objects to draw or to clean up. The label is a formula (@=): it keeps up with the score by itself.

Why Scena

  • Made for learning. The first program is a few lines; the concepts arrive one at a time, in the order a learner needs them. Speed is the framework's job, not the beginner's.
  • Simple things are simple. Circle() draws a circle. Sprite("ship.png") shows a ship. No setup, no boilerplate, no classes to inherit before anything appears.
  • Easy to begin, space to grow. Parameters are gradual: start with Circle(), then Circle(center=(200, 150), radius=40), then circle.visual = Neon("cyan"). Add detail only when you want it.
  • Say what should happen. @collide, @when, @every and @click read like the rules of the game. A formula (label["text"] @= lambda: ...) is written once and stays true.
  • No magic. Code does what it looks like it does. Scena never adds behavior or content you did not ask for: it gives you rich vocabulary, and the scene is yours.
  • Mistakes explain themselves. A misspelled key, color or parameter gets a message that says what was wrong and suggests the closest right name.
  • Batteries included. Collision, animation, effects, camera, layers, UI widgets, sound and a level editor are in the box, and they work together.

What's in the box

Shapes and sprites. Circles, rectangles, polygons, lines, text, images and sprite sheets. Every one draws with nothing but defaults, and takes more when you want more.

ball = Circle()                          # a circle in the middle of the window
ball.color = "coral"
ball.visual = Neon("cyan")               # one of 30+ looks
ship = Sprite("space/playerShip1_red.png", height=45, center=(400, 60))
ship.glow = True

Events that read like rules. Collisions, timers, clicks, conditions and objects leaving the screen, each one a decorator.

@collide("shots", "enemies")
def hit(shot, enemy):
    canvas.burst_at(enemy, radius=40)
    shot.destroy()
    enemy.destroy()


@when(lambda: st.score >= 10)
def level_up():
    st.speed *= 1.5

Formulas. Link a value to others once; Scena keeps it up to date.

a = Circle(center=(200, 300), radius=8)
b = Circle(center=(600, 300), radius=8)
bridge = Line(p1=lambda: a.center, p2=lambda: b.center)   # follows a and b

Animation in one line. Move, turn, scale and fade over time, with easing, loops and yoyo. Effects such as pop, flash, dissolve_out and explosion_at clean up after themselves.

ship.move_to(400, 300, time=1.5, ease="ease_in_out")
enemy.scale_to(1.08, time=0.45, loops="forever", yoyo=True)

Looks, effects and backgrounds. Visuals for shapes, screen effects, animated backgrounds and one-shot explosions, all composable.

A circle with the Flame look
visual = Flame()
A circle with the ElectricField look
visual = ElectricField()
A swirling portal
Portal()
Fireworks over a picture
canvas.fireworks_at(x, y)
An aurora background
Borealis()
A ship dissolving
ship.dissolve_out(0.5)

And more. A camera, layers and endless scrolling worlds; boxes, grids and geometry (intersections, midpoints, tangents); sliders, buttons, menus and check boxes; sound effects, music and the microphone; acts for menus and levels; and scena-editor, a level editor whose files a game reads with Level.

Every clip below is a program from examples/, played and recorded by the computer (nothing is edited by hand). Each one is the last step of a tutorial.

Naves
Naves: a space shooter with lives, explosions and a shield
Plane
Plane: fly between pillars over an endless, layered landscape
Spinning bars
Spinning bars: recursion you can watch
Oscilloscope
Oscilloscope: two circles make a curve
Midpoint
Midpoint: a compass-and-ruler construction you can drag
Balls
Balls: twenty balls bounce off the walls and each other

Install

Scena needs Python 3.12 or newer, on Windows, macOS or Linux.

pip install scena

To try the examples, get a copy of this repository and run one:

git clone https://github.com/accmota/Scena.git
cd Scena
pip install -e .
python examples/naves_escudo.py

Then, in any script: from scena import *.

Learn

  • Tutorial: from the first shapes to a space shooter, bouncing balls and a side-scrolling plane. Each one ends in a file in examples/.
  • API Guide: every class, function and effect, with a live picture of each look.

The tutorial and the Guide are in Portuguese today; the English version is in progress. The API itself (every name you type) is in English.

Is Scena for you?

Scena is a good fit for learning to program, small 2D games and creative coding. It is not trying to be a professional engine: it is 2D only, runs on the desktop (not in the browser or on phones), and is made for scenes with tens to hundreds of objects. Simple games stay simple, even if that means less power for very large ones.

License

Scena's code and documentation are under the MIT license. The images and sounds in examples/media/ come from other artists under their own licenses (mostly CC0). A few sounds ask for credit; the lines to copy are in examples/media/CREDITS.md.

Contributions are welcome under the same license: see CONTRIBUTING.md.


By André Mota. For my sons, with much love.

Metadata

Release files for scena 0.7.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for scena 0.7.0
File Size Uploaded
scena-0.7.0.tar.gz 2.1 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for scena 0.7.0
File Interpreter ABI Platform
scena-0.7.0-py3-none-any.whl Python 3 none any Details

Total release size: 3.3 MB

Release files / scena-0.7.0.tar.gz

Download URL scena-0.7.0.tar.gz
Size 2.1 MB
Tags Source
SHA-256 checksum
How to use checksums
6895db526cdf6326108bf6ba3b9ebee40f391f9e72f329611b5429f12d3a82eb
BLAKE2b-256 checksum
How to use checksums
4f04c0a9b8bc22ee2c87cd53c9e1c3c3c4a443673281faffec58d14b22553b3e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / scena-0.7.0-py3-none-any.whl

Download URL scena-0.7.0-py3-none-any.whl
Size 1.2 MB
Tags Python 3
SHA-256 checksum
How to use checksums
787a50cf3959bd48741f8288e104bb50111710d48f9ebfc6e372736f963a9568
BLAKE2b-256 checksum
How to use checksums
abebfa78429736366bc2eec9d500d3b9bfafc3ae1d210e7d701f03a76865e527
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release history Release notifications | RSS feed

0.8.1

2 release files

0.8.0

2 release files

0.7.1

2 release files

This release

0.7.0 This release

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page