Moana and the Lemon Apocalypse is an original PRG32 cartridge game. Moana is a Neapolitan 6-year-old lemon collector racing through an Ischia-inspired lemon grove before chickens and an angry rooster ruin the day.
The game is intentionally compact and readable: a single C cartridge implements the PRG32 lifecycle, game state, input, spawning, collision, drawing, sound, and Store scoring. That makes it useful both as a playable arcade cartridge and as a first-year teaching example.
No copyrighted sprites, music, level art, or sounds from commercial games are included. The committed PNG and WAV files are original generated assets, with an AI-assisted Ischia splash source and short original beep-style melodies.
This is a standalone third-party PRG32 game repository. It is not expected to live inside the PRG32 source tree.
MoanaAndTheLemonApocalypse/
|-- README.md
|-- LICENSE
|-- c/
| `-- game.c
|-- assets/
| |-- icon.png
| |-- screenshot.png
| |-- generate_assets.py
| |-- manifest.json
| |-- png/
| `-- wav/
|-- docs/
| |-- build-and-publish.md
| `-- tutorial-create-moana-lemon-apocalypse.md
|-- metadata/
| |-- colophon.json
| |-- manifest.json
| `-- metadata.json
`-- scripts/
|-- build.sh
`-- pack-store-bundle.sh
Lemons fall from active trees in pseudo-random positions and expire after a short time. Moana collects as many as possible before the screen timer runs out. Each lemon type changes the state in a different way:
| Lemon | Effect |
|---|---|
| Normal | Adds score, fills Moana's basket, and advances the screen quota |
| Magic | Adds 30 seconds, adds score, and fills the basket |
| Energetic | Temporarily makes Moana faster, adds score, and fills the basket |
| Bad | Consumes 15 seconds and does not fill the basket |
Chickens start appearing after the first screens. During normal play they chase
ordinary lemons; during escape they chase Moana. The rooster appears on later
screens and attacks Moana directly. Press A to throw a lemon from the basket
and scare him away.
When the quota is complete, a door appears on one border. Moana must reach the door while the chickens and rooster pursue her. After the final screen, the game submits the score through the PRG32 scoreboard API.
Use Joystick 1.
| Input | Action |
|---|---|
| D-pad | Move Moana |
| A | Throw a lemon from the basket |
| SELECT | Start, continue, or restart |
| ESC | Quit in emulator |
PRG32 is an educational RISC-V gaming runtime. It turns low-level programming from an abstract lecture into a visible loop: change state, rebuild a cartridge, move a sprite, and see the result.
A PRG32 cartridge exports three functions:
<prefix>_init
<prefix>_update
<prefix>_draw
init sets the initial state, update reads input and advances the model, and
draw renders the state. This cartridge uses:
| Entry prefix | Exported symbols |
|---|---|
moana_lemon_c |
moana_lemon_c_init, moana_lemon_c_update, moana_lemon_c_draw |
For a complete first-year laboratory sequence, see
docs/tutorial-create-moana-lemon-apocalypse.md.
It guides students from the code-deploy-debug cycle through gameplay changes,
asset personalization, metadata, bundle packing, and final publication.
You need two separate repositories/directories:
- this game repository;
- a cloned PRG32 repository, used as the resident runtime and cartridge tool provider.
Example layout:
mkdir -p $HOME/src
cd $HOME/src
git clone https://github.com/riscv-prg32/PRG32.git
git clone https://github.com/riscv-prg32/MoanaAndTheLemonApocalypse.gitUse the current PRG32 main branch. The game draws its characters with
portable graphics primitives, so no sprite-specific development branch is
needed.
Then tell the helper script where PRG32 is:
export PRG32_REPO=$HOME/src/PRG32
cd $HOME/src/MoanaAndTheLemonApocalypseBuild for ESP32-C6 hardware:
export PRG32_ARCHITECTURE=esp32c6
scripts/build.shThe output is:
dist/moana-lemon-apocalypse-esp32c6.prg32
Build for QEMU:
export PRG32_ARCHITECTURE=qemu
scripts/build.shThe output is:
dist/moana-lemon-apocalypse-qemu.prg32
Builds use the portable ABI required by current PRG32 main.
Upload to a PRG32 ESP32-C6 board:
PYTHONPATH="$PRG32_REPO" python3 -m prg32 esp32c6 upload \
dist/moana-lemon-apocalypse-esp32c6.prg32 \
--url http://192.168.4.1Stage the QEMU cartridge into a PRG32 QEMU flash image:
PYTHONPATH="$PRG32_REPO" python3 -m prg32 qemu upload \
dist/moana-lemon-apocalypse-qemu.prg32 \
--flash "$PRG32_REPO/build-qemu/qemu_flash.bin" \
--partitions "$PRG32_REPO/partitions_prg32.csv"Build both architecture variants, pack the flat Store bundle, then publish:
export PRG32_REPO=$HOME/src/PRG32
export PRG32_ARCHITECTURE=esp32c6
scripts/build.sh
export PRG32_ARCHITECTURE=qemu
scripts/build.sh
scripts/pack-store-bundle.sh
PYTHONPATH="$PRG32_REPO" python3 -m prg32 store publish-bundle \
dist/moana-lemon-apocalypse-store-bundle.zip \
--store-url http://192.168.1.42:5080 \
--token "$PRG32_STORE_TOKEN"See docs/build-and-publish.md for the focused
build, deploy, QEMU, and Store workflow.
The current assets are generated. Rebuild them with:
python3 assets/generate_assets.pyUseful student exercises:
- change the splash screen title or classroom signature;
- recolor Moana, chickens, rooster, or lemons;
- adjust the lemon grove background;
- change short generated WAV motifs;
- keep artwork and sound original, and document provenance before publishing.
The running cartridge currently draws gameplay objects procedurally in
c/game.c, so visual changes that should appear during play may need matching
updates in the drawing functions.
This project is intentionally small. It is not a generic game engine. That is a feature for a classroom: students can trace the same ideas from state variables to update rules to pixels on the screen.
Suggested lab path:
- play the cartridge;
- change a quota, speed, color, or sound;
- inspect the related state variable in
c/game.c; - rebuild and deploy to QEMU;
- personalize one generated asset;
- pack and publish a final cartridge bundle.
The reward is immediate: a low-level state change becomes a visible lemon, timer, chicken, door, or final score.