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.6)) |
| Zabití nepřítele / velký náraz | výbuch Particles + silnější Shake (add(0.8)–add(1.0)) + 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. Použij 0.6 pro malý kopanec, 0.8 pro zásah nebo výbuch, 1.0 pro velký náraz. Před výpočtem posunu se hodnota umocní na druhou, takže slabé události mají výrazně menší účinek - a pod zhruba 0.5 je posun přimax_offset=6menší než jeden pixel (0.4 dává 0.96 px), takže takové třesení není vidět a jen stojí překreslení celé obrazovky..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, top=0, bottom=0, left=0, right=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;top/bottom/left/rightje vyhrazený pruh pro HUD (stejná čísla, jaká jsi dalsetup()neboScene), aby kamera centrovala a omezovala pohled ve viditelné části obrazovky, ne pod HUDem..follow(tx, ty, snap=False)- posune střed kamery k(tx, ty)o podíllerp; ssnap=Trueho nastaví okamžitě. Vracíself..apply(shake=None)- vypočítá offset a přímo zavoláscene.set_view. Bez alokace; vracíNone. PředejShake(cam.apply(shaker)) a otřes se přičte ke kameře v témže volání - jedenset_view, žádná n-tice..offset()- vypočítá a vrátí offset jako n-tici(ox, oy)(alokuje n-tici při každém volání - dobré pro setup nebo test, ne pro herní smyčku). Poapply()/offset()jsou hodnoty k dispozici i jako.ox/.oy.
import picogame_fx as fx
cam = fx.Camera(scene, W, H, world_w=bounds_w, world_h=bounds_h, top=BAR) # stejný pruh jako setup(top=BAR)# ...každý snímek:cam.follow(player.x, player.y).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 displej desky, např.picogame_game.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(picogame_game.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.