Efekty a herní odezva
Tyto efekty doplňují vizuální odezvu a pohyb bez ploch přes celou obrazovku. Jejich paměťové náklady se liší: Fade kreslí přes callback StripDraw, Sky drží tabulku barev, Scanlines drží jeden řádek bitmapy a funkce pro palety mění existující palety PAL8. Signatury najdeš v /cs/reference/.
Hledáš odezvu na herní událost? Tato tabulka tě nasměruje na správný efekt; podrobnosti jsou v sekcích níže.
| Událost | Sáhni po |
|---|---|
| Malý zásah / obdržené poškození | flash spritu (1–3 snímky) + slabý Shake (add(~0.15)) |
| Zabití nepřítele / velký náraz | výbuch Particles + silnější Shake (add(~0.6)) + hit-stop |
| Sebrání / naskočení skóre | „pop“ přes Tween (blip je na stránce o zvuku) |
| Změna obrazovky / scény | Fade |
| Pohyb v nabídce / rozhraní | Tween |
picogame_fx
Sekce “picogame_fx”Tyto objekty vytvoř pro danou scénu a časované efekty aktualizuj jednou za herní snímek. Shake a InvertFlash zvýrazní náraz, Fade obslouží přechod, Tween vyhladí změnu hodnoty, Camera sleduje svět a Sky nebo Scanlines kreslí rastrové pozadí a překryvy.
import picogame_fx as fx
fx.Shake - doznívající třesení obrazovky
Sekce “fx.Shake - doznívající třesení obrazovky”
Shake ukládá intenzitu nazvanou trauma. Volání add() ji zvýší a každý tick() přidá náhodný posun a uloženou hodnotu sníží. Běžný posun kamery předej do tick(), aby oba efekty použily jediné volání scene.set_view().
Shake(scene, max_offset=6, decay=0.03, seed=0x9E37)-max_offsetje maximální posun v pixelech adecayúbytek intenzity za snímek. Výchozí hodnoty jsou určené pro obrazovku 320×240 a 30 FPS..add(amount)- přidá intenzitu v rozsahu 0 až 1 a výsledek omezí na 1. Před výpočtem posunu se hodnota umocní na druhou, takže slabé události mají výrazně menší účinek..tick(cam_x=0, cam_y=0)- přidá náhodný posun k(cam_x, cam_y)a zavoláscene.set_view()s výsledkem. Dokud třesení trvá, vracíTrue.
import picogame_fx as fx
shaker = fx.Shake(scene, max_offset=6)# ...při zásahu:shaker.add(0.8)# ...každý snímek (bez kamery, takže zadej 0,0):shaker.tick(0, 0)Hit-stop (zmrazení snímku)
Sekce “Hit-stop (zmrazení snímku)”Zmrazení obrazu při velkém nárazu je běžná technika herní odezvy, engine pro ni ale nemá žádný primitiv — sám přeskočíš N herních tiků / volání scene.refresh(). Drž počítadlo freeze a dokud je kladné, sniž ho a proveď continue ve smyčce (stále volej clock.tick(), aby časování zůstalo plynulé).
freeze = 0# ...při velkém nárazu:freeze = 4# ...na začátku herní smyčky:if freeze > 0: freeze -= 1 clock.tick() continuefx.Fade - rastrový přechod, ztmavení a záblesk
Sekce “fx.Fade - rastrový přechod, ztmavení a záblesk”
Překryv StripDraw nanáší barvu do obdélníku pomocí uspořádaného Bayerova rastru. Nedrží žádnou obrazovou plochu. Při úrovni 0 zmenší vykreslovací obdélník na 0×0, takže nepřidává další dirty region.
Fade(scene, width, height, x=0, y=0, color=0, cell=8)- pokryje obdélník(x, y, width, height).color=0znamená černou acellurčuje velikost buněk rastru. Vrstva je přidaná jakofixed=True, proto se neposouvá s kamerou..set(level)- okamžitě nastavílevel, kde 0 znamená průhledný a 16 plný překryv..to(target, speed=2.0)- mění hodnotu ktargetrychlostíspeedúrovní za snímek. Vracíself..out(speed=2.0)/.into(speed=2.0)- zkratky proto(16)(k neprůhledné) ato(0)(k průhledné)..dim(level=8)- nastaví částečné ztmavení, například pod nabídkou..clear()nastaví 0..pulse(level=12, speed=2.0)- vystoupá nalevela pak automaticky zpět na 0; plynulý celoobrazovkový záblesk. Nechlevelpod 16, ať zůstane průhledný dither, nikdy plná zeď..tick()- posunelevelktargetospeed. VracíTrue, když je cíl dosažen..is_done(vlastnost) -True, kdyžlevel == target.
import picogame_fx as fx
fader = fx.Fade(scene, W, H)# ...spusť fade do černé:fader.out(speed=2)# ...každý snímek; po dosažení černé spusť přechod zpět:if fading and fader.tick(): fader.into(speed=2)fx.Tween - plynulé dojíždění skaláru k cíli
Sekce “fx.Tween - plynulé dojíždění skaláru k cíli”
Tween v každém snímku exponenciálně přibližuje jednu hodnotu k cíli. Hodí se pro posun prvku rozhraní, změnu měřítka nebo plynule aktualizované číslo.
Tween(value=0.0, speed=0.2)-speedje podíl zbývající vzdálenosti, který se uzavře v jednom snímku, v rozsahu 0 až 1..to(target, speed=None)- nastav nový cíl (a volitelně novou rychlost). Vracíself..set(value)- okamžitě nastaví hodnotu i cíl navalue..tick()- posune hodnotu o podílspeedk cíli a vrátí nový stav. Při rozdílu menším než 0,01 nastaví přesný cíl..is_done(vlastnost) -True, jakmile se hodnota rovná cíli.
import picogame_fx as fx
y = fx.Tween(0)y.to(100) # posuň panel dolů na y=100# ...každý snímek:panel.y = int(y.tick())fx.Camera - plynulá sledovací kamera
Sekce “fx.Camera - plynulá sledovací kamera”
Kamera sleduje bod ve světě a vypočítává posun pohledu. Volitelně ho omezí tak, aby za hranou úrovně nebyla vidět prázdná plocha.
Camera(scene, w, h, lerp=0.18, world_w=0, world_h=0)-wahjsou rozměry obrazovky,lerpurčuje vyhlazení v každém snímku a nenulovéworld_waworld_homezí pohled na rozměry světa..follow(tx, ty, snap=False)- posune střed kamery k(tx, ty)o podíllerp; ssnap=Trueho nastaví okamžitě. Vracíself..apply()- vypočítá offset a přímo zavoláscene.set_view. Bez alokace; vracíNone. Použij, když není žádný shake..offset()- vypočítá a vrátí offset jako n-tici(ox, oy)(alokuje). Předej to doShake.tick(ox, oy)pro složení obou efektů.
import picogame_fx as fx
cam = fx.Camera(scene, W, 240, world_w=bounds_w)# ...každý snímek:cam.follow(player.x, 120).apply()fx.Sky - vertikální gradientní pozadí
Sekce “fx.Sky - vertikální gradientní pozadí”Svislý gradient se kreslí po řádcích přes StripDraw. Drží tabulku h barev v pořadí pro přenos, tedy 2 * h bajtů, a při překreslení znovu vykreslí požadované řádky. Přidej ho před herní vrstvy.
Sky(scene, x, y, w, h, top, bottom)- vyplní obdélník a interpoluje každý řádek od barvytopkbottom. Obě jsou RGB565 v pořadí pro přenos. Vrstva jefixed=True. Změnou.topa.bottommůžeš animovat denní dobu.
import picogame as pgimport picogame_fx as fx
sky = fx.Sky(scene, 0, 0, W, HORIZON, pg.rgb565(60, 120, 240), pg.rgb565(200, 230, 255))fx.Scanlines - překryv s řádky CRT
Sekce “fx.Scanlines - překryv s řádky CRT”Efekt ztmaví každý N-tý řádek pro vzhled CRT nebo mřížky LCD. Drží jeden řádek PAL8 o velikosti w bajtů a dvoupoložkovou paletu a blituje ho přes StripDraw. Přidej ho až po herních vrstvách.
Scanlines(scene, x, y, w, h, step=2, dark=pg.rgb565(0, 0, 0))-step=2ztmaví každý druhý řádek adarkurčuje barvu překryvu. Předpočítaný rastrový řádek jednou blitne na každý ztmavený řádek.
import picogame_fx as fx
scanlines = fx.Scanlines(scene, 0, 0, W, H) # přidej JAKO POSLEDNÍ, navrch všehofx.InvertFlash - záblesk pomocí inverze řadiče
Sekce “fx.InvertFlash - záblesk pomocí inverze řadiče”
Kompatibilní SPI panel na několik snímků přepne do negativu pomocí inverze barev řadiče (pg.invert). Scénu nepřekresluje ani nealokuje obrazový buffer. Použij ho s řadiči třídy ST7789 nebo ST7735; framebufferové výstupy, například Fruit Jam DVI, tuto funkci nepodporují. Simulátor efekt emuluje.
InvertFlash(display, frames=3, normal=None)-displayje např.board.DISPLAY;framesje délka záblesku.normalje klidový stav inverze panelu. PicoPad posílá INVON při inicializaci, takže jeho klidový stav jenormal=None(výchozí); předejnormal=Falsejen pro panel, jehož init neprovádí inverzi..pulse(frames=None)- přepne z klidového stavu, volitelně na vlastní počet snímků..tick()- odpočítává a po skončení obnoví klidový stav. Dokud záblesk trvá, vracíTrue. Volej poscene.refresh(), aby INVON nebo INVOFF byla poslední operace na sběrnici v daném snímku.
import boardimport picogame_fx as fx
flash = fx.InvertFlash(board.DISPLAY, frames=6)# ...při zásahu:flash.pulse()# ...po scene.refresh():flash.tick()Bezpečnost proti záchvatům: u jakéhokoli celoobrazovkového záblesku (InvertFlash, Fade.pulse, rychlé blikání spritu) se vyhni trvalému blikání nad ~3 Hz (nejméně 10 snímků od sebe při 30 fps); celoobrazovkové inverze drž na 1–3 snímcích, jednorázově.
picogame.Particles
Sekce “picogame.Particles”
pg.Particles je základní vrstva enginu pro jiskry, exploze, efekt sebrání předmětu nebo prach. Předem vytvoří fond s pevnou kapacitou a během emit() ani tick() nevytváří nové objekty částic.
pg.Particles(capacity, *, size=1, gravity=0.0, fade=False)- fond ažcapacitybodů o velikostisizepixelů.gravityje při každém kroku posouvá dolů afade=Trueje s věkem ztmavuje.size/gravity/fadejsou keyword-only (předávej je jménem)..emit(x, y, count, speed=1, life=30, color=0xFFFF)- výbuchcountteček z(x, y)s náhodnou rychlostí dospeedpx/tick, každá žijelifeticků..tick()- posune a zestárne živé tečky; volej jednou za snímek.
import picogame as pg
ps = pg.Particles(180, size=2, gravity=0.0, fade=True)scene.add(ps) # přidej jednou, jako každou vrstvu# ...při zásahu / killu / sebrání:ps.emit(x, y, 16, 4, 24, pg.rgb565(255, 210, 120)) # 16 jisker, rychlost 4, život 24 ticků# ...každý snímek:ps.tick()picogame_palette
Sekce “picogame_palette”
Grafika PAL8 může měnit barvy bez kopie obrazových indexů. cycle otáčí vybranou část palety, swap kopíruje jinou paletu a fade interpoluje položky k cílové barvě. Položky palety jsou celá čísla RGB565 v pořadí pro přenos, která vrací pg.rgb565().
import picogame_palette as palette
snapshot(palette)- vrátí kopii palety jakoarray('H'). Ulož ji před změnami, abyfademohl interpolovat od původních barev arestoreje obnovit.restore(palette, base)- zkopírujebasezpět dopalettena místě.cycle(palette, lo, hi, step=1)- otočí položky[lo..hi]včetně osteppřímo v původní paletě. Vyhrazená skupina barev tak může animovat například vodu.swap(dst_palette, src_palette)- zkopíruje jednu paletu do druhé až po délku kratší z nich. Jedna bitmapa PAL8 tak může mít více barevných variant.fade(palette, base, t, target=0, skip=None)- interpoluje položkypaletteod uloženébasek barvětargetpodlet, kde 0.0 znamená původní barvu a 1.0 cíl.skipponechá vybraný index beze změny, například průhlednou položku.
import picogame_palette as palette
# ...každý snímek animuj vyhrazený rozsah barev vody:palette.cycle(water_bmp.palette, 1, 6)water.touch() # řekni rendereru, že se paleta změnilaPřebarvení spritu na jasnější / jiný odstín — co sprite.tint neumí (násobení jen ztmavuje).
Drž jednu PAL8 bitmapu a dej jí teplou paletu (např. zelený nepřítel → žhavě jantarová „elita“):
import array, picogame_palette as palette
WARM = array.array("H", [0, pg.rgb565(150, 40, 30), pg.rgb565(255, 130, 45), pg.rgb565(120, 45, 25), pg.rgb565(255, 215, 130), pg.rgb565(235, 90, 45), pg.rgb565(255, 245, 190)]) # jedna položka na indexpalette.swap(enemy.bitmap.palette, WARM) # zkopíruj WARM do palety bitmapy, in placeenemy.touch() # renderer si změny palety sám nevšimne# Variantu místo in-place? Postav druhou `pg.Bitmap(DATA, ..., palette=WARM)` a přiřaď ji do# sprite `.bitmap` — viz examples/picogame_picowing.py, který takhle přebarvuje Kenney nepřítele.