Ukládání & paměť
Tyto tři helpery řeší části PicoPad hry, které bojují s omezenou RAM a flashem zařízení: udržení malého stavu mezi restarty (picogame_save), vyhnutí se MemoryError z fragmentované haldy (picogame_arena) a zobrazování sprite sheetů příliš velkých na to, aby se načetly celé (picogame_stream). Pro samotné signatury viz /cs/reference/; pro rozpočet RAM, který motivuje ty poslední dva, viz /cs/memory/.
picogame_save
Sekce “picogame_save”Malé strukturované úložiště klíč-hodnota postavené na microcontroller.nvm - vyhrazené 4 KB oblasti ve flashi RP2040, do které můžeš přímo zapisovat z code.py. Sáhni po něm, když chceš, aby high score, odemčená úroveň nebo nastavení přežily vypnutí. Na rozdíl od souborového systému CIRCUITPY (jen pro čtení z kódu, pokud ho nepřipojíš znovu v boot.py), NVM nevyžaduje žádný boot.py, žádný reflash a přežije i smazání souborového systému.
NVM je jedna sdílená oblast pro všechny programy na zařízení, takže každá hra předává vlastní key. Klíč se zahashuje do hlavičky a při načítání se zkontroluje - pokud jiná hra nebo stará data zapsala ten slot, load() vrátí tvoje výchozí hodnoty místo špatně přečtených cizích bajtů.
Data popisuješ pomocí schématu: seřazeného slovníku name -> (struct format char, default). Běžné znaky: "B" 0-255, "H" 0-65535, "I" 0 až 2^32-1; malá b/h/i jsou se znaménkem.
Save(key, schema, *, offset=0)- vytvoří úložiště.keyje název tvé hry (str nebo bytes).offsetje jen klíčové slovo; zvedni ho pouze pokud dvě souběžně běžící hry musí používat různé oblasti NVM. VyhodíRuntimeError, pokud NVM není dostupná, neboValueError, pokud se schéma do NVM nevejde.load()- vrátí slovník uložených hodnot, nebo čerstvou kopii výchozích hodnot, pokud je slot prázdný, poškozený nebo zapsaný jinou hrou (neshoda klíče). Na špatná data nikdy nevyhodí výjimku.save(values)- uloží slovník. Chybějící klíče se doplní výchozí hodnotou ze schématu. Zapíše kontrolní součet, aby ho pozdějšíload()mohl detekovat jako poškozený.reset()- zapíše výchozí hodnoty zpět pod klíčem této hry.defaults()- čerstvý slovník pouze s výchozími hodnotami, bez čtení NVM.
import picogame_save
# persist the best lap time (seconds) across rebootsstore = picogame_save.Save("ghostrace", {"best_t": ("H", 0)})best_t = store.load()["best_t"] # 0 = no record yet
# ...later, on a new best run:if best_t == 0 or secs < best_t: best_t = secs store.save({"best_t": best_t}) # survives power-offPozor: každé save() smaže a přepíše sektor flashe, takže flash se opotřebuje, pokud ho voláš každý snímek - ukládej jen při smysluplných událostech (game over, nové high score, změna nastavení). Schéma udržuj malé; celý blob (hlavička + pole + kontrolní součet) se musí vejít do NVM.
picogame_arena
Sekce “picogame_arena”Předalokovaná bufferová aréna, která rozdává plátky jednoho velkého bufferu, takže velké povrchy za běhu nic nealokují ani neuvolňují. Sáhni po ní, když dlouhobě běžící hra opakovaně vytváří velké Canvas povrchy a nakonec narazí na MemoryError, přestože gc.mem_free() vypadá v pořádku. MicroPython GC haldu nikdy nekompaktuje, takže točení velkých bufferů ji fragmentuje: spousta celkové volné RAM, ale žádný dost velký souvislý blok. Aréna si jeden blok vezme najednou, brzy, dokud je halda čerstvá.
Arena(pixels)- alokuje arénu. Velikost je v pixelech; rezervujepixels * 2bajtů (RGB565). Udělej to brzy, než se halda fragmentuje.canvas(w, h, transparent=None)-pg.Canvaspodložený dalším plátkem (bez alokace haldy na canvas); automaticky 16-bitově zarovnaný. VrátíCanvas.alloc(nbytes, align=1)- generickýmemoryviewplátek onbytes: znovupoužij ho jako buffer pro čtení souboru/sítě, pomocný prostor pro parsování, audio blok atd.alignzaokrouhlí začátek plátku nahoru (použijalign=2pro 16-bitová data,align=4pro přístup po slovech). VyhodíMemoryError, pokud je aréna plná. Platný do dalšíhoreset().reset()- uvolní všechny dosud vydané plátky. Volej na začátku každé scény, která arénu znovu používá. JakýkoliCanvaspřed resetem se nesmí dále kreslit.free()- bajty stále dostupné v aréně.
import picogame_arena
# one arena for the big canvases, grabbed once while the heap is contiguous;# scenes that never run at the same time share the bytes (reset each).ARENA = picogame_arena.Arena(320 * 80) # 320x80 px = 51 200 bytes
def big_canvas(w, h, transparent=None, first=False): if first: ARENA.reset() # reuse the arena for this scene return ARENA.canvas(w, h, transparent=transparent)Pozor: tohle vyžaduje firmware Canvas s argumentem buffer= - na simulátoru je tento argument ignorován a simulátor alokuje vlastní buffer, takže přínos proti fragmentaci se projeví jen na skutečném hardwaru. Po reset() jsou všechny povrchy z předchozí dávky mrtvé; kreslení do jednoho poškodí nový obsah.
picogame_stream
Sekce “picogame_stream”Přehrává velký sprite sheet přímo ze souboru ve flashi a drží v RAM jen jeden snímek. Sáhni po něm, když je sheet příliš velký na to, aby se importoval celý - .mpy import zkopíruje celý sheet na haldu, ale StreamSheet soubor otevře jednou a při každém požadavku na snímek provede readinto() do bufferu pro jeden snímek (bez alokace na snímek). Pro sheet 64x100, 11 snímků to znamená ~6,4 KB rezidentní paměti místo ~70 KB. Sheet musí být frame-major (bajty každého snímku w*h jsou za sebou) - zabal ho pomocí tools/pack_sheet.py.
StreamSheet(pg, path, w, h, frames, palette, transparent=None)- otevřepath, alokuje buffer pro jeden snímek, sestavípg.Bitmap(PAL8) nad ním a načte snímek 0.paletteje tabulka barev pro PAL8 data..bitmap- jedinýpg.Bitmap, jehož pixely se přepisují na místě. Z tohoto sestav svůjpg.Sprite.use(i)- načte snímeki(zabalený moduloframes) do sdíleného bufferu a vrátí bitmap. Cachovaný: znovu čte z flashe jen když seiskutečně změní.close()- zavře podkladový soubor.
import picogame_stream
sheet = picogame_stream.StreamSheet(pg, "jill.bin", 64, 100, 11, PAL, transparent=0)player = pg.Sprite(sheet.bitmap, x, y)# ...each frame the animation advances:sheet.use(frame_index) # stream that frame into the shared bufferplayer.touch() # tell the scene to repaint it (pixels changed in place)Pozor: vždy volej sprite.touch() po use(). use() přepíše jeden bitmap buffer na místě, ale dirty-rect engine scény překreslí sprite jen tehdy, když se změní sledovaná vlastnost (pozice, index snímku, měřítko, úhel, objekt bitmapy). Změna pixelů na místě je pro něj neviditelná, takže bez touch() změna snímku bez pohybu (vrchol výskoku, chůze do zdi) zanechá zastaralý nebo roztrhaný sprite. Sprite.touch() vyžaduje firmware z picogame engine 2026-06 nebo novějšího; na simulátoru je to no-op (simulátor překresluje celý obraz). Viz /cs/scene-format/, jak dirty-rect překreslování funguje.