{"id":20995396,"url":"https://github.com/todbot/circuitpython_staroids","last_synced_at":"2025-05-14T21:31:17.738Z","repository":{"id":47868761,"uuid":"394056340","full_name":"todbot/circuitpython_staroids","owner":"todbot","description":"Something like Asteroids but not really, done in CircuitPython","archived":false,"fork":false,"pushed_at":"2022-05-31T19:07:54.000Z","size":536,"stargazers_count":15,"open_issues_count":1,"forks_count":5,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-05-08T02:18:26.217Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/todbot.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-08-08T19:45:06.000Z","updated_at":"2024-12-15T13:35:51.000Z","dependencies_parsed_at":"2022-09-15T01:12:50.528Z","dependency_job_id":null,"html_url":"https://github.com/todbot/circuitpython_staroids","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/todbot%2Fcircuitpython_staroids","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/todbot%2Fcircuitpython_staroids/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/todbot%2Fcircuitpython_staroids/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/todbot%2Fcircuitpython_staroids/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/todbot","download_url":"https://codeload.github.com/todbot/circuitpython_staroids/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254230867,"owners_count":22036259,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-19T07:23:37.134Z","updated_at":"2025-05-14T21:31:12.694Z","avatar_url":"https://github.com/todbot.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# CircuitPython Staroids\n\nSomething like **Asteroids**, done in CircuitPython.\nWorks with [FunHouse](https://www.adafruit.com/product/4985),\n[MacroPad](https://www.adafruit.com/product/5128),\n[Pybadge](https://www.adafruit.com/product/4200),\n[EdgeBadge](https://www.adafruit.com/product/4400),\n[CLUE](https://www.adafruit.com/product/4500),\nand [Pygamer](https://www.adafruit.com/product/4242).\n\n\u003cimg src=\"./docs/staroids_family1.jpg\" /\u003e\n\nhttps://user-images.githubusercontent.com/274093/129097480-3be3b302-d7ba-4690-951a-0822a2933bb3.mp4\n\n(And [@jedgarpark](https://github.com/jedgarpark) modified the [Pybadge version to have sound as seen in this video](https://www.youtube.com/watch?v=sC_fLp5CfTg)!)\n\n## Game rules:\n\n- You control a spaceship in an asteroid field\n- Your ship has three controls: Turn Left, Turn Right, and Thrust/Fire\n- You get +1 point for every asteroid shot\n- You get -3 point every time an asteroid hits your ship\n- Game ends when you get bored or the boss comes walking by\n- If you hit an asteroid, LEDs flash orange. If your ship is hit, LEDs flash purply.\n- No sound by default (as many boards do not support WAV playback)\n\n## Installation\n\n- Install CircuitPython onto your board (requires CircuitPython 7.0.0-alpha.5 or better)\n- Install needed CircuitPython libraries\n- Copy entire `imgs` directory to CIRCUITPY drive\n- Copy `staroids_code.py` to your CIRCUITPY drive as `code.py`\n\nIf you have [`circup`](https://github.com/adafruit/circup) installed,\ninstallation can be done entirely via the command-line\nusing the included `requirements.txt` and a few copy commands. MacOS example below:\n\n```\n$ circup install -r ./requirements.txt\n$ cp -aX imgs /Volumes/CIRCUITPY\n$ cp -X staroids_code.py /Volumes/CIRCUITPY/code.py\n```\n\n## Code techniques demonstrated\n\nIf you're interested in how to do stuff in CircuitPython, this code does things\nthat might be useful. Those include:\n- Detecting which board is being used and adjusting I/O \u0026 game params accordingly\n- Dealing with almost all possible LED \u0026 button input techniques in CircuitPython\n- Timing without using `time.sleep()`\n- Sprite sheet animation with `displayio`\n- Smooth rotation animation with sprite sheets\n- Simple 2D physics engine (velocity \u0026 acceleration, okay enough for this game)\n\n\n## Sound effects\n\n- In general, sound effects are not part of this game. CircuitPython doesn't do sound\nas well as it does graphics, so I find the experience a little grating.\n\n- But if you have a Pybadge or Pygamer and want sounds, you can set\n`enable_sound=True` at the top of the `code.py` and copy over the\n`snds` directory to the CIRCUITPY drive to enable sounds.\n\n- The sounds were created by me from audio of [John Park's 8/12/21 livestream](https://www.youtube.com/watch?v=EYGYTlM6usc).\nSpecifically, the \"pew\" sound comes from the 6:56 mark of him saying \"pew pew\"\nand the \"exp\" sound comes from the \"x\" sound in \"AdaBox\" at 7:15.\n\n\n## Implementation notes\n\n(Notes for myself mostly)\n\n- Sprite rotation is accomplished using sprite \"sheets\" containing all possible\nrotations of the sprite. For the ship that is 36 rotation images tiles \nat 10-degrees apart. For the asteroids, that's 120 rotation image tiles\nat 3 degrees apart. The rotated images were created using ImageMagick\non a single sprite.\n\n- A simpler version of [this sprite rotation code can be found in this gist](https://gist.github.com/todbot/92373f93db9da0fca5ca4adee8d7d75b) and [this video demo](https://twitter.com/todbot/status/1423331295384399883).\n\n- Another way to do this is via `bitmaptools.rotozoom()`. This technique worked but\nseemed like it would not perform well on boards with chips with no floating-point\nhardware (RP2040, ESP32-S2). You can find that [demo rotozoom code in this gist](https://gist.github.com/todbot/8b524daba51bd84c92799a2401324521)\nand [this video demo](https://twitter.com/todbot/status/1423078302391037953).\n\n- Ship, Asteroids, Shots (`Thing` objects) are in a floating-point (x,y) space,\nwhile its corresponding `displayio.TileGrid` is integer (x,y) space. This allows\na `Thing` to accumulate its (x,y) velocity \u0026 acceleration without weird\nint-\u003efloat truncations.\n\n- Similarly, `Thing` rotation angle is floatping point but gets quantized to the\nsprite sheet's tile number.\n\n- Per-board settings is useful not just for technical differences (sprite sizes),\nbut also for gameplay params (accel_max, vmax)\n\n- Hitbox calculations are done on floating-point (x,y) of the `Thing` objects,\nbut converted to int before hitbox calculation to hopefully speed things up.\n\n- Sprite sizes (e.g. 30x30 pixels), sprite bit-depth (1-bit for these sprits),\nand quantity on screen (5 asteroids, 4 shots) greatly influences framerate.\nFor a game like Asteroids where FPS needs to be high, you have to balance this\ncarefully. To see this, try converting the ship spritesheet to a 4-bit\n(16-color) BMP and watch the framerate drop. Or you might run out of memory.\n\n\n## How the sprite sheets were made\n\n(Notes for myself mostly)\n\nGiven a set of square images named:\n- ship0.png - our spaceship coasting\n- ship1.png - our spaceship thrusting\n- roid0.png - one asteroid shape\n- roid1.png - another asteroid shape\n- roidexp.png - an exploding asteroid\n\nand you want to create the sprite sheets:\n- ship_sheet.bmp  -- two sets (coast + thrust) of 36 10-degree rotations in one palette BMP\n- roid0_sheet.bmp -- 120 3-degree rotations in one palette BMP\n- staroid1_sheet.bmp -- 120 3-degree rotations in one palette BMP\n- roidexp_sheet.bmp -- 8 45-degree rotations in one palette BMP\n\nThe entire set of ImageMagick commands to create the sprite sheet of rotations,\nas a single shell script is below.\n\nSprites were hand-drawn in Pixelmator using vague recollection of Asteroids.\nFor MacroPad, sprites were re-drawn as 12px square tile instead of 30px.\nThe were drawn with https://www.pixilart.com/art/staroids-sprites-12px-58e5853d4c2b0ef.\nFor Pybadge, 30px sprites were rescaled to 20px using ImageMagick.\n\n```shell\n# ship0 (coasting)\nfor i in $(seq -w 0 10 359) ; do\necho $i\nconvert ship0.png -distort SRT $i ship0-r$i.png\ndone\nmontage -mode concatenate -tile x1 ship0-r*png  ship0_sheet.png\nconvert ship0_sheet.png -colors 2 -type palette BMP3:ship0_sheet.bmp\n\n# ship1 (thrusting)\nfor i in $(seq -w 0 10 359) ; do\necho $i\nconvert ship1.png -distort SRT $i ship1-r$i.png\ndone\nmontage -mode concatenate -tile x1 ship1-r*png  ship1_sheet.png\nconvert ship1_sheet.png -colors 2 -type palette BMP3:ship1_sheet.bmp\n\n# combine ship0 \u0026 ship1 into one sprite sheet\nmontage -mode concatenate -tile x2 ship0_sheet.bmp ship1_sheet.bmp ship_sheet.png\nconvert ship_sheet.png -colors 2 -type palette BMP3:ship_sheet.bmp\n\n# roid0\nfor i in $(seq -w 0 3 359) ; do  \necho $i\nconvert roid0.png -distort SRT $i roid0-r$i.png \ndone\nmontage -mode concatenate -tile x1 roid0-r*png  roid0_sheet.png\nconvert roid0_sheet.png -colors 2 -type palette BMP3:roid0_sheet.bmp \n\n# roid1\nfor i in $(seq -w 0 3 359) ; do  \necho $i\nconvert roid1.png -distort SRT $i roid1-r$i.png \ndone\nmontage -mode concatenate -tile x1 roid1-r*png  roid1_sheet.png\nconvert roid1_sheet.png -colors 2 -type palette BMP3:roid1_sheet.bmp \n\n# exploding asteroid\nfor i in $(seq -w 0 45 359) ; do \necho $i\nconvert roidexp.png -distort SRT $i roidexp-r$i.png\ndone\nmontage -mode concatenate -tile x1 roidexp-r*png  roidexp_sheet.png\nconvert roidexp_sheet.png -colors 2 -type palette BMP3:roidexp_sheet.bmp\n\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftodbot%2Fcircuitpython_staroids","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftodbot%2Fcircuitpython_staroids","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftodbot%2Fcircuitpython_staroids/lists"}