[{"element_type":"markdown","content":"\u003cp\u003eThis is a game about skeletons, pumpkins, and a catapult having a Spooky\nexperience under the full moon. If you've thought about\nmaking a game in CircuitPython but aren't sure where to start, this project\nmight be a useful source of ideas.\u003c/p\u003e\n","metadata":{"markdown":"This is a game about skeletons, pumpkins, and a catapult having a Spooky\nexperience under the full moon. If you've thought about\nmaking a game in CircuitPython but aren't sure where to start, this project\nmight be a useful source of ideas.\n"}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/001/261/original/title-screen.jpeg?1728485129","metadata":{"caption":""}},{"element_type":"markdown","content":"\u003ch3\u003eCharging a Pumpkin\u003c/h3\u003e\n\n\u003cp\u003eThis is how it looks when you hold the USB gamepad's A button to charge up a\npumpkin.\u003c/p\u003e\n","metadata":{"markdown":"### Charging a Pumpkin\n\nThis is how it looks when you hold the USB gamepad's A button to charge up a\npumpkin.\n"}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/001/257/original/pumpkin-power.jpeg?1728485126","metadata":{"caption":""}},{"element_type":"markdown","content":"\u003ch3\u003ePumpkin in Flight\u003c/h3\u003e\n\n\u003cp\u003eThis is how it looks when a pumpkin is about to meet a skeleton.\u003c/p\u003e\n","metadata":{"markdown":"### Pumpkin in Flight\n\nThis is how it looks when a pumpkin is about to meet a skeleton.\n"}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/001/258/original/flying-pumpkin.jpeg?1728485128","metadata":{"caption":""}},{"element_type":"markdown","content":"\u003ch3\u003eVideo Demo\u003c/h3\u003e\n\n\u003cp\u003eThere's a game play video on youtube:\u003c/p\u003e\n\n\u003cp\u003e\u003ca href=\"https://www.youtube.com/watch?v=QStcSDSYKOE\"\u003ehttps://www.youtube.com/watch?v=QStcSDSYKOE\u003c/a\u003e\u003c/p\u003e\n","metadata":{"markdown":"### Video Demo\n\nThere's a game play video on youtube:\n\nhttps://www.youtube.com/watch?v=QStcSDSYKOE\n"}},{"element_type":"embed","content":"https://www.youtube.com/watch?v=QStcSDSYKOE"},{"element_type":"markdown","content":"\u003ch2\u003eHardware\u003c/h2\u003e\n\n\u003cp\u003eThis uses the setup of ESP32-S3 Feather TFT, MAX3421E USB Host FeatherWing, and\nFeather Doubler that I've been using for previous USB gamepad projects. If you\nwant more details on the hardware and gamepad stuff, you might check out some\nof my other Adafruit Playground guides:\u003c/p\u003e\n\n\u003cul\u003e\n\u003cli\u003e\u003cp\u003e\u003ca href=\"https://adafruit-playground.com/u/SamBlenny/pages/feather-tft-gamepad-tester-with-sprites\"\u003eFeather TFT Gamepad Tester with Sprites\u003c/a\u003e\u003c/p\u003e\u003c/li\u003e\n\u003cli\u003e\u003cp\u003e\u003ca href=\"https://adafruit-playground.com/u/SamBlenny/pages/feather-tft-clock-with-gamepad-input\"\u003eFeather TFT Clock with Gamepad Input\u003c/a\u003e\u003c/p\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch3\u003eParts\u003c/h3\u003e\n","metadata":{"markdown":"## Hardware\n\nThis uses the setup of ESP32-S3 Feather TFT, MAX3421E USB Host FeatherWing, and\nFeather Doubler that I've been using for previous USB gamepad projects. If you\nwant more details on the hardware and gamepad stuff, you might check out some\nof my other Adafruit Playground guides:\n\n- [Feather TFT Gamepad Tester with Sprites](https://adafruit-playground.com/u/SamBlenny/pages/feather-tft-gamepad-tester-with-sprites)\n\n- [Feather TFT Clock with Gamepad Input](https://adafruit-playground.com/u/SamBlenny/pages/feather-tft-clock-with-gamepad-input)\n\n\n### Parts\n\n"}},{"element_type":"product","content":"https://www.adafruit.com/product/5483","metadata":{}},{"element_type":"product","content":"https://www.adafruit.com/product/5858","metadata":{}},{"element_type":"product","content":"https://www.adafruit.com/product/2890","metadata":{}},{"element_type":"parts","content":"\n  \u003cdiv class=\"parts-details\"\u003e\n    \u003cdiv\u003e\n      \u003cspan class=\"parts-quantity\"\u003e1\u003c/span\u003e\u003cspan\u003e x \u003c/span\u003e\n        \u003ca href=\"https://www.8bitdo.com/sn30-pro-usb-gamepad/\" class=\"parts-name\" target=\"_blank\"\u003e8BitDo SN30 Pro USB gamepad\u003c/a\u003e\n      \u003cdiv class=\"parts-description\"\u003ea USB gamepad\u003c/div\u003e\n    \u003c/div\u003e\n  \u003c/div\u003e\n  \u003cdiv class=\"parts-action\"\u003e\n  \u003cdiv\u003e\n      \u003ca href=\"https://www.8bitdo.com/sn30-pro-usb-gamepad/\" class=\"parts-url btn-secondary\" target=\"_blank\"\u003eBuy Now\u003c/a\u003e\n\n  \u003c/div\u003e\n\u003c/div\u003e\n\n  \u003cdiv class=\"clearfix\"\u003e\u003c/div\u003e\n","metadata":{"name":"8BitDo SN30 Pro USB gamepad","url":"https://www.8bitdo.com/sn30-pro-usb-gamepad/","description":"a USB gamepad","quantity":"1"}},{"element_type":"markdown","content":"\u003ch3\u003ePinouts\u003c/h3\u003e\n\n\u003ctable\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003cth\u003eTFT feather\u003c/th\u003e\n\u003cth\u003eUSB Host\u003c/th\u003e\n\u003cth\u003eST7789 TFT\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003eSCK\u003c/td\u003e\n\u003ctd\u003eSCK\u003c/td\u003e\n\u003ctd\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eMOSI\u003c/td\u003e\n\u003ctd\u003eMOSI\u003c/td\u003e\n\u003ctd\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eMISO\u003c/td\u003e\n\u003ctd\u003eMISO\u003c/td\u003e\n\u003ctd\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eD9\u003c/td\u003e\n\u003ctd\u003eIRQ\u003c/td\u003e\n\u003ctd\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eD10\u003c/td\u003e\n\u003ctd\u003eCS\u003c/td\u003e\n\u003ctd\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eTFT_CS\u003c/td\u003e\n\u003ctd\u003e\u003c/td\u003e\n\u003ctd\u003eCS\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eTFT_DC\u003c/td\u003e\n\u003ctd\u003e\u003c/td\u003e\n\u003ctd\u003eDC\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\n\u003ch3\u003eTools and Consumables\u003c/h3\u003e\n\n\u003cp\u003eYou will need soldering tools and solder.\u003c/p\u003e\n\n\u003ch3\u003eSoldering the Headers\u003c/h3\u003e\n\n\u003cp\u003eThe TFT Feather, USB Host FeatherWing and the Doubler all come in kit form, so\nyou will need to solder the headers.\u003c/p\u003e\n\n\u003cp\u003eIf you are unfamiliar with soldering headers, you might want to read:\u003c/p\u003e\n\n\u003cul\u003e\n\u003cli\u003e\u003cp\u003e\u003ca href=\"https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools\"\u003eAdafruit Guide To Excellent Soldering\u003c/a\u003e\u003c/p\u003e\u003c/li\u003e\n\u003cli\u003e\u003cp\u003e\u003ca href=\"https://learn.adafruit.com/how-to-solder-headers\"\u003eHow To Solder Headers\u003c/a\u003e\u003c/p\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","metadata":{"markdown":"### Pinouts\n\n| TFT feather | USB Host | ST7789 TFT |\n| ----------- | -------- | ---------- |\n|  SCK        |  SCK     |            |\n|  MOSI       |  MOSI    |            |\n|  MISO       |  MISO    |            |\n|  D9         |  IRQ     |            |\n|  D10        |  CS      |            |\n|  TFT_CS     |          |  CS        |\n|  TFT_DC     |          |  DC        |\n\n\n### Tools and Consumables\n\nYou will need soldering tools and solder.\n\n\n### Soldering the Headers\n\nThe TFT Feather, USB Host FeatherWing and the Doubler all come in kit form, so\nyou will need to solder the headers.\n\nIf you are unfamiliar with soldering headers, you might want to read:\n\n- [Adafruit Guide To Excellent Soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools)\n\n- [How To Solder Headers](https://learn.adafruit.com/how-to-solder-headers)\n\n"}},{"element_type":"markdown","content":"\u003ch2\u003eUpdating CircuitPython\u003c/h2\u003e\n\n\u003cp\u003e\u003cstrong\u003eNOTE: To update CircuitPython on the ESP32-S3 TFT Feather with 2MB PSRAM and\n4MB Flash, you need to use the .BIN file (combination bootloader and\nCircuitPython core)\u003c/strong\u003e\u003c/p\u003e\n\n\u003col\u003e\n\u003cli\u003e\u003cp\u003eDownload the CircuitPython 9.1.4 \u003cstrong\u003e.BIN\u003c/strong\u003e file from the\n\u003ca href=\"https://circuitpython.org/board/adafruit_feather_esp32s3_tft/\"\u003eFeather ESP32-S3 TFT PSRAM\u003c/a\u003e\npage on circuitpython.org\u003c/p\u003e\u003c/li\u003e\n\u003cli\u003e\u003cp\u003eFollow the instructions in the\n\u003ca href=\"https://learn.adafruit.com/circuitpython-with-esp32-quick-start/web-serial-esptool\"\u003eWeb Serial ESPTool\u003c/a\u003e\nsection of the \"CircuitPython on ESP32 Quick Start\" learn guide to update\nyour board: first erase the flash, then program the .BIN file.\u003c/p\u003e\u003c/li\u003e\n\u003c/ol\u003e\n","metadata":{"markdown":"## Updating CircuitPython\n\n**NOTE: To update CircuitPython on the ESP32-S3 TFT Feather with 2MB PSRAM and\n4MB Flash, you need to use the .BIN file (combination bootloader and\nCircuitPython core)**\n\n1. Download the CircuitPython 9.1.4 **.BIN** file from the\n   [Feather ESP32-S3 TFT PSRAM](https://circuitpython.org/board/adafruit_feather_esp32s3_tft/)\n   page on circuitpython.org\n\n2. Follow the instructions in the\n   [Web Serial ESPTool](https://learn.adafruit.com/circuitpython-with-esp32-quick-start/web-serial-esptool)\n   section of the \"CircuitPython on ESP32 Quick Start\" learn guide to update\n   your board: first erase the flash, then program the .BIN file.\n\n"}},{"element_type":"markdown","content":"\u003ch2\u003eInstalling CircuitPython Code\u003c/h2\u003e\n\n\u003cp\u003eTo copy the project bundle files to your CIRCUITPY drive:\u003c/p\u003e\n\n\u003col\u003e\n\u003cli\u003e\u003cp\u003eDownload the project bundle .zip file using the Download Project Bundle button below.\u003c/p\u003e\u003c/li\u003e\n\u003cli\u003e\u003cp\u003eExpand the zip file by opening it, or use \u003ccode class=\"inline\"\u003eunzip\u003c/code\u003e in a Terminal. The zip\narchive should expand to a folder. When you open the folder, it should\ncontain a \u003ccode class=\"inline\"\u003eREADME.txt\u003c/code\u003e file and a \u003ccode class=\"inline\"\u003eCircuitPython 9.x\u003c/code\u003e folder.\u003c/p\u003e\u003c/li\u003e\n\u003cli\u003e\u003cp\u003eOpen the CircuitPython 9.x folder and copy all of its contents to your\nCIRCUITPY drive.\u003c/p\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\n\u003cp\u003eTo learn more about copying libraries to your CIRCUITPY drive, check out the\n\u003ca href=\"https://learn.adafruit.com/welcome-to-circuitpython/circuitpython-libraries\"\u003eCircuitPython Libraries\u003c/a\u003e\nsection of the\n\u003ca href=\"https://learn.adafruit.com/welcome-to-circuitpython\"\u003eWelcome to CircuitPython!\u003c/a\u003e\nlearn guide.\u003c/p\u003e\n","metadata":{"markdown":"## Installing CircuitPython Code\n\nTo copy the project bundle files to your CIRCUITPY drive:\n\n1. Download the project bundle .zip file using the Download Project Bundle button below.\n\n2. Expand the zip file by opening it, or use `unzip` in a Terminal. The zip\n   archive should expand to a folder. When you open the folder, it should\n   contain a `README.txt` file and a `CircuitPython 9.x` folder.\n\n3. Open the CircuitPython 9.x folder and copy all of its contents to your\n   CIRCUITPY drive.\n\nTo learn more about copying libraries to your CIRCUITPY drive, check out the\n[CircuitPython Libraries](https://learn.adafruit.com/welcome-to-circuitpython/circuitpython-libraries)\nsection of the\n[Welcome to CircuitPython!](https://learn.adafruit.com/welcome-to-circuitpython)\nlearn guide.\n"}},{"element_type":"button","content":"https://github.com/samblenny/pumpkin-toss-game/releases/download/v0.1.1/pumpkin-toss-game-ba2a431.zip","metadata":{"class":"btn btn-large btn-block btn-primary","button_type":"primary","target":"_blank","zip_folder":"false"}},{"element_type":"markdown","content":"\u003ch2\u003eSprites and Background\u003c/h2\u003e\n\n\u003cp\u003eI made sprites for this project using the Pixaki app for iPad.\u003c/p\u003e\n\n\u003cp\u003eMy general workflow for making a spritesheet and background image is:\u003c/p\u003e\n\n\u003col\u003e\n\u003cli\u003e\u003cp\u003eOpen a new canvas of 120 pixels wide by 67 pixels high, with a black\nbackground and a grid with 8 pixel spacing. This lets me get a good feel for\nhow things will look on a Feather TFT screen with 2x scaling using a\n\u003ccode class=\"inline\"\u003edisplayio.Group(scale=2)\u003c/code\u003e.\u003c/p\u003e\u003c/li\u003e\n\u003cli\u003e\u003cp\u003ePick four colors for my palette (in this case black, gray, white, and orange)\nand sketch my idea for how a scene will look once the game is done. By\nseparating things into different layers, it's easier to move stuff around\nand experiment.\u003c/p\u003e\u003c/li\u003e\n\u003cli\u003e\u003cp\u003eOnce I have a scene I like, make a new layer for the spritesheet and copy\nchunks of the other layers into the spritesheet layer, aligning the tiles\ninto an 8x8 grid.\u003c/p\u003e\u003c/li\u003e\n\u003cli\u003e\u003cp\u003eHide all the other layers except the spritesheet and the background, then\nuse Pixaki's PNG export feature to export the spritesheet. Also, take a a\nscreenshot of the spritesheet layer with the 8x8 grid lines. Annotating this\nscreenshot with sprite tile numbers makes it a lot easier to write the code\nfor assembling spritesheet tiles into sprites with animation cycles.\u003c/p\u003e\u003c/li\u003e\n\u003cli\u003e\u003cp\u003eTurn the spritesheet layer off, turn the other layers back on, then take a\nscreenshot with the 8x8 grid lines. Annotating this screenshot with pixel\nnumbers for the grid lines (0, 8, 16, 24, ...) makes it easier to set the\nx= and y= arguments when I write the code to create displayio.TileGrid\nobjects for the sprites.\u003c/p\u003e\u003c/li\u003e\n\u003cli\u003e\u003cp\u003eUse AirDrop to transfer the screenshots and spritesheet PNG to my mac.\u003c/p\u003e\u003c/li\u003e\n\u003c/ol\u003e\n","metadata":{"markdown":"## Sprites and Background\n\nI made sprites for this project using the Pixaki app for iPad.\n\nMy general workflow for making a spritesheet and background image is:\n\n1. Open a new canvas of 120 pixels wide by 67 pixels high, with a black\n   background and a grid with 8 pixel spacing. This lets me get a good feel for\n   how things will look on a Feather TFT screen with 2x scaling using a\n   `displayio.Group(scale=2)`.\n\n2. Pick four colors for my palette (in this case black, gray, white, and orange)\n   and sketch my idea for how a scene will look once the game is done. By\n   separating things into different layers, it's easier to move stuff around\n   and experiment.\n\n3. Once I have a scene I like, make a new layer for the spritesheet and copy\n   chunks of the other layers into the spritesheet layer, aligning the tiles\n   into an 8x8 grid.\n\n4. Hide all the other layers except the spritesheet and the background, then\n   use Pixaki's PNG export feature to export the spritesheet. Also, take a a\n   screenshot of the spritesheet layer with the 8x8 grid lines. Annotating this\n   screenshot with sprite tile numbers makes it a lot easier to write the code\n   for assembling spritesheet tiles into sprites with animation cycles.\n\n5. Turn the spritesheet layer off, turn the other layers back on, then take a\n   screenshot with the 8x8 grid lines. Annotating this screenshot with pixel\n   numbers for the grid lines (0, 8, 16, 24, ...) makes it easier to set the\n   x= and y= arguments when I write the code to create displayio.TileGrid\n   objects for the sprites.\n\n7. Use AirDrop to transfer the screenshots and spritesheet PNG to my mac.\n\n\n"}},{"element_type":"markdown","content":"\u003ch3\u003eBackground\u003c/h3\u003e\n","metadata":{"markdown":"### Background\n\n"}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/001/259/original/bkgnd-with-grid.jpeg?1728485128","metadata":{"caption":""}},{"element_type":"markdown","content":"\u003ch3\u003eSpritesheet\u003c/h3\u003e\n","metadata":{"markdown":"### Spritesheet\n\n"}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/001/260/original/sprites-with-grid.jpeg?1728485129","metadata":{"caption":""}},{"element_type":"markdown","content":"\u003ch2\u003ePumpkin Flight Physics\u003c/h2\u003e\n\n\u003cp\u003eInitially, I wanted to try accurately modelling pumpkin flight, including drag.\nThat got messy because the Feather TFT screen is very small, with a wide aspect\nratio, such that it's hard to show realistic trajectories for Earth gravity.\u003c/p\u003e\n\n\u003cp\u003eEventually, I just started making up velocity and acceleration numbers that, in\nmy subjective opinion, \"looked good\". The math works by evaluating (x, y)\ndisplacement for each animation frame time interval. The horizontal velocity\ngets updated each animation frame with acceleration from \"drag\", and the\nvertical velocity gets updated with acceleration from \"gravity\". If those\ndrag and gravity numbers are in any way realistic, it's purely by accident. I\njust made them up. The goal here is entertainment though, so it's fine.\u003c/p\u003e\n\n\u003cp\u003eThat said, if you want to read about accurate pumpkin flight math, some\npotentially useful search terms include: rigid body dynamics, projectile\nmotion, classical mechanics, drag coefficient, drag equation, and ballistic\nflight.\u003c/p\u003e\n\n\u003cp\u003eThe most readily useable references I found for calculating displacement as a\nfunction of time and initial velocity were from NASA's Glenn Research Center:\u003c/p\u003e\n\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://www1.grc.nasa.gov/beginners-guide-to-aeronautics/fltcalc/\"\u003eBallistic Flight Calculator\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www1.grc.nasa.gov/beginners-guide-to-aeronautics/ballistic-flight-equations/\"\u003eBallistic Flight Equations\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www1.grc.nasa.gov/beginners-guide-to-aeronautics/flight-equations-with-drag/\"\u003eFlight Equations with Drag\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","metadata":{"markdown":"## Pumpkin Flight Physics\n\nInitially, I wanted to try accurately modelling pumpkin flight, including drag.\nThat got messy because the Feather TFT screen is very small, with a wide aspect\nratio, such that it's hard to show realistic trajectories for Earth gravity.\n\nEventually, I just started making up velocity and acceleration numbers that, in\nmy subjective opinion, \"looked good\". The math works by evaluating (x, y)\ndisplacement for each animation frame time interval. The horizontal velocity\ngets updated each animation frame with acceleration from \"drag\", and the\nvertical velocity gets updated with acceleration from \"gravity\". If those\ndrag and gravity numbers are in any way realistic, it's purely by accident. I\njust made them up. The goal here is entertainment though, so it's fine.\n\nThat said, if you want to read about accurate pumpkin flight math, some\npotentially useful search terms include: rigid body dynamics, projectile\nmotion, classical mechanics, drag coefficient, drag equation, and ballistic\nflight.\n\nThe most readily useable references I found for calculating displacement as a\nfunction of time and initial velocity were from NASA's Glenn Research Center:\n- [Ballistic Flight Calculator](https://www1.grc.nasa.gov/beginners-guide-to-aeronautics/fltcalc/)\n- [Ballistic Flight Equations](https://www1.grc.nasa.gov/beginners-guide-to-aeronautics/ballistic-flight-equations/)\n- [Flight Equations with Drag](https://www1.grc.nasa.gov/beginners-guide-to-aeronautics/flight-equations-with-drag/)\n\n\n"}},{"element_type":"markdown","content":"\u003ch2\u003eCode\u003c/h2\u003e\n\n\u003cp\u003eFor this project, I made a tiny game engine from scratch in CircuitPython using\nmostly built-in CircuitPython libraries. For sprites, I used \u003ccode class=\"inline\"\u003edisplayio.TileGrid\u003c/code\u003e\nand \u003ccode class=\"inline\"\u003eadafruit_imageload\u003c/code\u003e. For the gamepad, I used \u003ccode class=\"inline\"\u003eusb.core\u003c/code\u003e and \u003ccode class=\"inline\"\u003emax3421e.Max3421E\u003c/code\u003e.\nFor timing to regulate the frame rate, I used \u003ccode class=\"inline\"\u003esupervisor.ticks_ms\u003c/code\u003e.\u003c/p\u003e\n\n\u003cp\u003eThe techniques I used are mostly pretty straightforward intermediate level stuff. Some of it was\ntedious to keep track of, but there's nothing all that esoteric going on. One\nof the big challenges for a project like this is to stay organized so the\ncoordinates and sprite tile numbers don't get mixed up. To help keep sprite\ntile stuff from cluttering up the rest of the code, I made two classes just for\nmanaging sprite animation cycles: \u003ccode class=\"inline\"\u003ecatapult.Catapult\u003c/code\u003e and \u003ccode class=\"inline\"\u003eskeletons.Skeletons\u003c/code\u003e.\u003c/p\u003e\n\n\u003cp\u003eTo understand how the code works, I recommend that you start by reading through\n\u003ccode class=\"inline\"\u003ecode.py\u003c/code\u003e. It has extensive comments to help explain the rationale of how I\nstructured the code and the strategy I used to keep the frame rate smooth.\u003c/p\u003e\n","metadata":{"markdown":"## Code\n\nFor this project, I made a tiny game engine from scratch in CircuitPython using\nmostly built-in CircuitPython libraries. For sprites, I used `displayio.TileGrid`\nand `adafruit_imageload`. For the gamepad, I used `usb.core` and `max3421e.Max3421E`.\nFor timing to regulate the frame rate, I used `supervisor.ticks_ms`.\n\nThe techniques I used are mostly pretty straightforward intermediate level stuff. Some of it was\ntedious to keep track of, but there's nothing all that esoteric going on. One\nof the big challenges for a project like this is to stay organized so the\ncoordinates and sprite tile numbers don't get mixed up. To help keep sprite\ntile stuff from cluttering up the rest of the code, I made two classes just for\nmanaging sprite animation cycles: `catapult.Catapult` and `skeletons.Skeletons`.\n\nTo understand how the code works, I recommend that you start by reading through\n`code.py`. It has extensive comments to help explain the rationale of how I\nstructured the code and the strategy I used to keep the frame rate smooth.\n"}},{"element_type":"markdown","content":"\u003ch3\u003eCIRCUITPY/code.py\u003c/h3\u003e\n","metadata":{"markdown":"### CIRCUITPY/code.py"}},{"element_type":"embed","content":"https://github.com/samblenny/pumpkin-toss-game/blob/v0.1.1/code.py"},{"element_type":"markdown","content":"\u003ch3\u003eCIRCUITPY/catapult.py\u003c/h3\u003e\n","metadata":{"markdown":"### CIRCUITPY/catapult.py"}},{"element_type":"embed","content":"https://github.com/samblenny/pumpkin-toss-game/blob/v0.1.1/catapult.py"},{"element_type":"markdown","content":"\u003ch3\u003eCIRCUITPY/skeletons.py\u003c/h3\u003e\n","metadata":{"markdown":"### CIRCUITPY/skeletons.py"}},{"element_type":"embed","content":"https://github.com/samblenny/pumpkin-toss-game/blob/v0.1.1/skeletons.py"},{"element_type":"markdown","content":"\u003ch3\u003eCIRCUITPY/statemachine.py\u003c/h3\u003e\n","metadata":{"markdown":"### CIRCUITPY/statemachine.py"}},{"element_type":"embed","content":"https://github.com/samblenny/pumpkin-toss-game/blob/v0.1.1/statemachine.py"},{"element_type":"markdown","content":"\u003ch3\u003eCIRCUITPY/gamepad.py\u003c/h3\u003e\n","metadata":{"markdown":"### CIRCUITPY/gamepad.py"}},{"element_type":"embed","content":"https://github.com/samblenny/pumpkin-toss-game/blob/v0.1.1/gamepad.py"}]