Efekty sprite a textu
Stín, obrys, záře a rozostření na 2D sprite a na textu, s tím, co každý stojí, co dělá s pohybujícím se sprite, a s ručně stavěným receptem, který nahrazují.
Na co to je#
Až dosud mohl 2D sprite nést tint a obrázek, a nic víc. Aby postava vystoupila ze svého pozadí, museli jste efekt postavit ručně: vytvořit druhý sprite, obarvit ho na černo, posunout ho, dát ho dozadu, a udržovat ho v kroku s prvním na úplně každém snímku. Funguje to. Je to taky čtyři řádky účetnictví navíc na postavu, a v den, kdy jeden z nich zapomenete, se stín táhne za svým majitelem.
Čtyři příkazy to za vás udělají, na sprite i na textu:
hero = LoadSprite("hero.png")
SpritePosition(hero, 160, 120)
SpriteShadow(hero, 4, 4, 6, 128) ' offset x, offset y, softness, opacity
SpriteOutline(hero, 2, 255, 255, 255) ' thickness, colour
SpriteGlow(hero, 0, 240, 255, 8) ' colour, size
DO
Sync()
LOOP
Nic dalšího se neudržuje. Posuňte sprite, změňte měřítko, otočte ho, přehrajte jeho animaci: efekty ho sledují.
Čtyři efekty#
Stín#
SpriteShadow(spriteID, offsetX, offsetY, softness, opacity)
SpriteShadowColor(spriteID, red, green, blue)
offsetX a offsetY jsou ve vašich vlastních jednotkách obrazovky, počítané
stejně jako SpritePosition: kladné Y je dolů. softness stín rozprostírá;
opacity běží od 0 do 255. Barva je černá, pokud neřeknete jinak.
SpriteShadow(hero, 3, 5, 4, 110)
SpriteShadowColor(hero, 20, 0, 40) ' a cold shadow, not a grey one
Stín s opacitou 0 není stín. Takhle ho vypnete.
Obrys#
SpriteOutline(spriteID, thickness, red, green, blue)
Obrys sleduje siluetu sprite, ne obdélník, ve kterém žije: průhledné PNG dostane obrys kolem kresby, ne kolem souboru. Tloušťka je v jednotkách obrazovky, a užitečný rozsah je 1 až 3. Nad tím se osm směrů, ze kterých je obrys postavený, začne ukazovat jako osm laloků.
SpriteOutline(hero, 2, 255, 255, 255) ' the readable-on-anything outline
SpriteOutline(hero, 0, 0, 0, 0) ' off
Záře#
SpriteGlow(spriteID, red, green, blue, size)
Barevná svatozář, rozprostřená o size jednotek za siluetu. Sedí za sprite a
před stínem, což je to, co umožňuje použít obojí zároveň.
SpriteGlow(pickup, 255, 210, 0, 10) ' this one is worth walking to
Rozostření#
SpriteBlur(spriteID, radius)
Rozostření je ten lichý efekt. Ostatní tři se kreslí kolem sprite; rozostření nahradí vlastní obrázek sprite jeho rozostřenou kopií. To znamená dvě věci, které stojí za vědění:
- nestojí nic za snímek (rozostřený obrázek se spočítá jednou), a
- rozostření je oříznuté na hraně obrázku. Kresba, která se dotýká okraje svého PNG, ztratí tu část své svatozáře, která by spadla mimo. Nechte v souboru pár průhledných pixelů okraje, pokud ho plánujete rozostřit.
SpriteColor na rozostřeném sprite dál funguje.
Vypnutí všeho, a zase zpátky#
SpriteEffects(spriteID, 0) ' all four off
SpriteEffects(spriteID, 1) ' all four back, exactly as they were
SpriteEffects nesmaže vaše nastavení. Je to přepínač, ne reset, takže postava
může bliknout, aniž byste jí museli znovu deklarovat stín potom.
Stejné čtyři na textu#
score = CreateText("SCORE 0")
TextPositionSet(score, 10, 10)
TextSizeSet(score, 6)
TextOutline(score, 3, 0, 0, 0) ' readable on any background
TextShadow(score, 2, 2, 4, 160)
TextGlow(score, 255, 80, 0, 6)
TextBlur(score, 0)
TextEffects(score, 1)
Signatury přesně odpovídají těm u sprite, takže se není potřeba učit nic nového. Dva rozdíly v chování:
- Záře vyhrává nad softness stínu. Obojí kreslí stejný mechanismus, a záře bez softness je neviditelná, zatímco stín bez softness je pořád stín. Když chcete oboje, softness dostane záře.
- Tohle platí na vektorový text, ne na text z bitmapového fontu. Text
nakreslený pomocí
TextFontImageje složenina sprite; příkazy se na něm tiše ignorují. V tom případě použijte efekty sprite na sprite uvnitř.
Vypracovaný příklad: čitelné na čemkoli#
Problém, který tyto příkazy skutečně řeší, je kontrast, který neovládáte. Bílé skóre je neviditelné na sněhu; černé je neviditelné v noci. Obrys to vyřeší jednou, pro každé pozadí, na které kdy budete kreslit.
CreateText(1, "SCORE 0")
TextPositionSet(1, 10, 10)
TextSizeSet(1, 8)
TextColorSet(1, 255, 255, 255, 255)
TextOutline(1, 3, 0, 0, 0)
hero = LoadSprite("hero.png")
SpriteName(hero, "hero")
SpriteShadow(hero, 4, 6, 5, 120)
SpriteOutline(hero, 2, 255, 255, 255)
points = 0
DO
points = points + 1
TextString(1, "SCORE " + Str(points))
Sync()
LOOP
Čtení efektu zpět#
Každý parametr, který zapíšete, má čtečku, stejně jako SpriteColor má
SpriteColorRed. Je to pravidlo dialektu, a tyto příkazy ho dodržují.
IF SpriteEffectsEnabled(hero) = 1
SpriteEffects(hero, 0)
ENDIF
alpha = SpriteShadowAlpha(hero) ' 0 to 255
size = SpriteGlowSize(hero) ' 0 means no glow
Celá sada, po rodinách: SpriteShadowOffsetX, SpriteShadowOffsetY,
SpriteShadowBlur, SpriteShadowAlpha, SpriteShadowColorRed,
SpriteShadowColorGreen, SpriteShadowColorBlue, SpriteGlowRed,
SpriteGlowGreen, SpriteGlowBlue, SpriteGlowSize,
SpriteOutlineThickness, SpriteOutlineRed, SpriteOutlineGreen,
SpriteOutlineBlue, SpriteBlurRadius, SpriteEffectsEnabled, plus stejných
sedmnáct s prefixem Text.
Dvě pravidla stojí za vědění:
- Sprite, který nikdy nedostal žádný efekt, hlásí sám sebe jako ZAPNUTÝ. To je výchozí stav; odpovědět 0 by programu řeklo, že jeho efekty jsou vypnuté dřív, než jakékoli nastavil.
- Dotaz na sprite, který neexistuje, odpoví 0, program tím nezastaví. Tak
se dialekt chová k dotazům všude:
SpriteHitodpoví 0, když se nic nedotýká, a programy tuto 0 čtou, aniž by ji testovaly.
Co to stojí#
Stín, obrys a záře se kreslí, takže stojí draw calls: jeden na stín (tři, když je měkký), čtyři na záři, osm na obrys. Obrazovka s dvěma sty obrysovanými sprite kreslí osmnáct set čtyřúhelníků, a bude to vidět. Jsou určené na hrstku věcí, na které se hráč má dívat: postavu, sběratelný předmět, vybranou jednotku.
Rozostření nestojí nic za snímek.
Praktické pravidlo: efekty na to, co se hýbe a záleží na tom, žádné na pozadí.
Co se přenese do exportované hry#
| Cíl | Stín, obrys, záře | Rozostření | Efekty textu |
|---|---|---|---|
| Editor | ano | ano | ano |
| Export HTML5 | ano | ano | ano |
| Native a wasm (Bevy) | ano | ne | ne |
Stín, obrys a záře jsou postavené z obyčejných sprite, takže cestují všude, kam cestují sprite. Rozostření a efekty textu potřebují most, který cíle Bevy ještě nemají: zpráva o konverzi exportu je pojmenuje, místo aby je tiše zahodila, takže build vám řekne, co nedokázal přenést.
Kde efekty nejsou#
Neexistuje SpriteEffect(id, "glow", ...), který by bral jméno efektu jako
řetězec. Každý efekt je vlastní příkaz, aby jeho parametry mohly být
pojmenované, zdokumentované a doplňované při psaní. Pro cokoli za těmito
čtyřmi přebírají dva další příkazy: SpriteBlendModes(id, src, dst) pro
aditivní nebo multiplikativní míchání (oheň, laser), a SpriteShader(id, shaderID) pro nasazení shaderu zkompilovaného pomocí LoadSpriteShader na
sprite. Oba byly dlouho deklarované v katalogu bez implementace, a jejich
volání vyhazovalo chybu; teď fungují.