Skip to content

About

Convert a MakeCode Arcade block game into a picogame game for the PicoPad — reads the block tree, emits readable picogame Python plus a generated art module.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

11 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

picogame-makecode

Convert a MakeCode Arcade game into a picogame game that runs on a PicoPad, a Fruit Jam, or any other CircuitPython board picogame supports.

It reads the block tree a MakeCode project is really made of and emits readable picogame Python plus a generated art module. No shim, no interpreter, no runtime dependency on anything MakeCode: what comes out is an ordinary picogame game you can open and edit.

python3 mkcd/mkcd_import.py https://arcade.makecode.com/S08257-52975-47680-29942 -o mygame
python3 ../picogame/sim/run.py mygame/code.py --backend pygame     # play it on the desktop

The converter itself needs nothing but Python 3.8+. The second line does, because the simulator lives in the picogame repository rather than here:

git clone https://github.com/MakerClassCZ/picogame ../picogame
pip install pygame          # only for the windowed simulator
pip install pillow          # only to run the gate (stage 4 reads screenshots)

Converting from a share link needs the network; point it at a directory to work offline.

The input can be a share link, a share id, or a directory holding main.blocks and the project's .jres assets. Output is code.py, <name>_art.py and IMPORT.md - read that last one, it says what did not come across.

How well does it work

Measured on a random sample of 80 real MakeCode block games harvested from GitHub (projects that ship their assets, so the picture on screen means something):

converts and reaches its frame loop 100 %
survives a scripted play session with no exception 89 % (±7)
converts with no reported gap at all 32 %

On real hardware (PicoPad, RP2040, CircuitPython 10.3.0) the reference games run at 27-31 fps with a flat heap - no fragmentation over a 1560-frame soak on the tightest of them. The same converted code runs unchanged on an RP2350 Fruit Jam.

"Runs" is not "plays the same." The numbers above say a game does not crash and is visibly alive; they do not say it feels like the original. Play a port before you trust it.

What does not come across

IMPORT.md lists every gap by name, and flags the ones that are fatal rather than leaving you to weigh a count - measured on the corpus, a project with zero gaps is playable 72 % of the time while ten unconverted blocks can be the entire game.

Known limits, by class:

  • Raw TypeScript blocks (typescript_statement, typescript_expression) are not the block language and cannot be translated. A project where they carry the data model will not run; the report says so explicitly above 6 % of blocks.
  • Per-pixel image drawing (Image.getPixel/setPixel/drawLine) - picogame keeps art in flash as read-only bytes, and copying every touched image onto the heap is not something an RP2040 has room for.
  • Browser-only APIs (browserEvents, mouse input).
  • Particle spawn PATTERNS - each named effect's rate, lifespan, speed, acceleration and palette come from particleeffects.ts, and the four shaped effects (hearts, smiles, rings, clouds) draw pxt's own bitmaps; what is approximated is where each particle starts and how the factory spreads them.
  • Sound expressions keep the wave shape, the frequency sweep and the volume contour; the interpolation curve and the tremolo/warble effects have no synthio equivalent.
  • Text sprite decoration (icons, outlines, borders) from arcade-text.
  • Extensions outside the supported set are reported by name rather than guessed at.

Layout

mkcd/mkcd_import.py       entry point: fetch, assets, the IMPORT.md report
mkcd/mkcd_blocks.py       Blockly XML  -> Arcade Python
mkcd/mkcd_ts.py           TypeScript   -> Arcade Python (the blocks subset only)
mkcd/mkcd_picogame.py     Arcade Python -> picogame Python
mkcd/helpers/*.py         the runtime the converter writes INTO the game, one file per helper
mkcd/mkcd_blockmap.json   blockId -> API, scraped from MakeCode's own //% blockId= annotations
tests/run_gate.py         the regression gate - run it before every commit
tests/fixtures/           the projects the gate converts (see fixtures/PROVENANCE.md)
tests/anim_cases/         generated animation vectors, the decoder's test data
tests/anim_codec.py       encodes mkcd-animation the way MakeCode does, derived from pxt sources
tests/device_api.json     what the DEVICE's builtins accept, read out of the firmware sources
tools/extract_device_api.py  regenerates that table from a CircuitPython checkout

Arcade Python is the shared middle layer: both front ends emit it, and one back end lowers it.

Contributing

Run the gate. Converter changes break other games routinely - that is the normal case, not an unlucky one - and the gate is what tells you which game and how.

python3 tests/run_gate.py --sim ../picogame

See docs/GATE.md for what each stage checks and why, and docs/HOW-IT-WORKS.md for the pipeline.

Third-party content

MIT licensed. MakeCode Arcade is a Microsoft project; this tool reads its file formats and is not affiliated with it.

The test fixtures are not our work: all eleven are the MakeCode Arcade Block Games gallery, MIT, Copyright (c) Microsoft Corporation, redistributed under that licence. tests/fixtures/PROVENANCE.md tabulates every one with its share link, so any of them can be re-fetched and diffed against what ships here.

About

Convert a MakeCode Arcade block game into a picogame game for the PicoPad — reads the block tree, emits readable picogame Python plus a generated art module.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages