Skip to content

Add the Pixel Demolition stress test example - #2931

Merged
pvcraven merged 1 commit into
developmentfrom
examples/pixel-demolition
Oct 7, 2026
Merged

pvcraven merged 1 commit into
developmentfrom
examples/pixel-demolition

Conversation

@pvcraven

@pvcraven pvcraven commented Oct 6, 2026

Copy link
Copy Markdown
Member

Summary

A new stress-test example meant for showing off: Pixel Demolition.

Pixel Demolition

Every pixel of the Arcade logo is a sprite: about 28,000 by default, or 71,000 with 2 px pixels. A turret fires up to 240 bullets a second. Each bullet explodes on impact, and every pixel in the blast flies off as debris, thousands at a time. With auto fire on (the default), the logo is rebuilt once it's gone, so it can run unattended for a video.

What it shows:

  • Drawing: all the pixels are in one SpriteList, drawn with a single call. 60,000 sprites draw in about 3 ms.
  • Collisions: the pixels are in a spatial hash with spatial_hash_cell_size=16, close to the sprite size, so each bullet and each blast only checks nearby pixels. The comments explain why the default of 128 would be slow here.
  • Removal: hit pixels are simply removed. Many removals per frame are applied in one pass, thanks to Apply SpriteList removals in one pass when many are removed #2930.
  • Debris, two ways (press G):
    • Python sprites: a SpriteList updated every frame.
    • GPU: each piece is written once to an instanced buffer (a 28-byte record in a ring buffer), and a vertex shader computes its arc and spin from its launch time. The shader uses Arcade's WindowBlock projection, so the debris lines up exactly with the sprites.

Controls: the mouse aims and fires (and turns off auto fire). A toggles auto fire, G switches debris mode, 1/2/3 set the pixel size, +/- change the fire rate, and R rebuilds the logo. The on-screen display shows FPS, update and draw times, and the sprite, debris and bullet counts.

Measured

Measured on my desktop in the real event loop, with the window hidden. Samples within 1.5 s of a logo rebuild are skipped, since building 71,000 sprites takes about a second:

Pixels, debris mode Peak debris Lowest FPS 10th percentile Median
3 px, GPU 7,400 60 60 60
3 px, Python 6,800 38 49 60
2 px, GPU 15,500 60 60 60
2 px, Python 14,500 10 19 52

So pressing G mid-demolition shows the difference live.

Example checklist

  • Example code in arcade/examples/sprite_pixel_demolition.py, with the python -m arcade.examples.sprite_pixel_demolition line.
  • Doc page doc/example_code/sprite_pixel_demolition.rst, with the screenshot and the code.
  • Gallery entry in doc/example_code/index.rst, under Stress Tests.
  • Full-size screenshot committed. The thumbnail is generated by the docs build.

Checks

  • The examples test runs it (in test mode, arcade.run() does one update and one draw).
  • Full suite: 1645 passed.
  • Docs built with sphinx-build -W: the page builds, and the gallery links to it.
  • Ruff is clean.

The changelog has an entry under Unreleased → New Features.

🤖 Generated with Claude Code

Every pixel of the Arcade logo is a sprite (about 28,000, or 71,000
with 2 px pixels). A turret fires up to 240 bullets a second; each
explodes on impact and knocks the pixels in its blast loose as debris.

It shows off one-call SpriteList drawing, spatial hash collisions with
a cell size near the sprite size, and removing many sprites per frame.
Debris moves either as Python sprites or on the GPU, where each piece
is written to an instanced buffer once and a shader computes its arc
(press G to switch). With auto fire, the logo is rebuilt when it's gone.

Measured on a desktop: GPU debris stays at 60 FPS with 15,500 pieces
in flight on 60,000 pixel sprites; Python debris drops to 10-19 FPS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@pvcraven
pvcraven merged commit 1269142 into development Oct 7, 2026
7 checks passed
@pvcraven
pvcraven deleted the examples/pixel-demolition branch October 7, 2026 14:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant