Errors and constants

When things go wrong

VS2 tries to fail at the line that caused the problem, during build(), rather than rendering something wrong later. These are the errors you will actually meet.

exception vs2.SceneSealedError[source]

Bases: RuntimeError

A structural call was made outside Scene.build().

Creating layers and drawables is only legal while build() runs. Once it returns the scene is sealed, and calling Layer.sprite() or any other factory from update(), a timer, or teardown() raises this instead of quietly growing the display graph mid-game.

It is also raised when a drawable that outlived its scene is written to, which is how a stale handle kept across scene entries surfaces.

exception vs2.ResourceLimitError[source]

Bases: RuntimeError

A scene asked for more sprites, tilemaps or layers than the target has.

The message carries a per-layer census so the offending budget is obvious:

sprite 101/100 in Vixeous (world: 62, hud: 39); reduce the sprite budget

Because every structural call happens during Scene.build(), this is always raised the first time the scene is entered rather than mid-game.

exception vs2.AssetLimitError[source]

Bases: ResourceLimitError

The loaded asset pack holds more image strips than the target supports.

exception vs2.AssetNotFoundError[source]

Bases: LookupError

An image name is not present in the scene’s asset pack.

Usually a typo, or a PNG that is not in the game’s images/ folder.

exception vs2.FrameError[source]

Bases: ValueError

A frame index falls outside its image’s frame count.

Raised at the assignment, so an out-of-range frame is reported at the line that set it instead of rendering garbage pixels.

Reading the messages

Error

Usual cause

What to do

AssetNotFoundError: image 'ships.png' is not in alecu.my_game

A typo, or the PNG is not in the game’s images/ folder. The name is the image’s id, which defaults to its filename.

Fix the name or add the image.

FrameError: ship.png has 4 frames; frame must be 0..3

A frame out of range.

Use sprite.image.frames instead of a hard-coded count.

ResourceLimitError: sprite 101/100 in Vixeous (world: 62, hud: 39)

Over a budget. The census shows which layer is largest.

Shrink a pool, or move text from sprites to a Label. See Budgets.

SceneSealedError: sprite() is only allowed while MyGame.build() runs

A drawable was created from update() or a timer.

Create it in build(), usually as a SpritePool.

SceneSealedError: cannot change x on a sprite from a closed V2 scene

A drawable handle outlived its scene, often one stored in __init__.

Create drawables in build(), not __init__.

Constants

Projections

Passed to Scene.layer as projection=, and decide how a layer maps Y to LEDs. The tutorial’s circular display chapter explains them with examples.

vs2.TUNNEL = 1

Perspective. Y is depth, 0..255, from the outermost ring to the centre. The usual choice for a game world.

vs2.HUD = 2

Flat, no perspective. Y is a direct LED index, 0..53, so y = 0 is the outermost LED. The usual choice for scores and overlays, which are most legible at low Y.

vs2.FULLSCREEN = 0

One centred image, for planets, backdrops and cloud cover. y = 0 fills all 54 LEDs and larger Y contracts it toward the centre. Sprites only — creating a tilemap or label on a FULLSCREEN layer raises during build().

Tiles and pools

vs2.EMPTY_TILE = 255

A tilemap cell that draws nothing. Newly allocated cell buffers are filled with it, and Label.write pads with it.

vs2.TRANSPARENT = 255

The palette index the renderer treats as see-through.

vs2.RECYCLE

Passed as on_empty= to Layer.sprite_pool. An exhausted pool then reuses its oldest live sprite instead of returning None — the right default for explosions and particles, where dropping one is worse than cutting another short.