Sprite- og teksteffekter
Skygge, kontur, glød og sløring på 2D-sprites og på tekst, med hvad hver enkelt koster, hvad den gør ved et sprite i bevægelse, og opskriften i hånden, den erstatter.
Hvad dette er til#
Indtil nu kunne et 2D-sprite bære en tone og et billede, og intet andet. For at løfte en karakter fri af sin baggrund måtte du bygge effekten i hånden: oprette et andet sprite, tone det sort, forskyde det, lægge det bagved, og holde det i takt med det første på hvert eneste billede. Det virker. Det er også fire ekstra linjer bogholderi pr. karakter, og den dag du glemmer én af dem, slæber skyggen efter sin ejer.
Fire kommandoer gør det for dig, på sprites og på tekst:
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
Intet andet at vedligeholde. Flyt spritet, skalér det, vend det, afspil dets animation: effekterne følger med.
De fire effekter#
Skygge#
SpriteShadow(spriteID, offsetX, offsetY, softness, opacity)
SpriteShadowColor(spriteID, red, green, blue)
offsetX og offsetY er i dine egne skærmenheder, talt på samme måde som
SpritePosition: positiv Y er ned. softness spreder skyggen; opacity
løber fra 0 til 255. Farven er sort, medmindre du siger andet.
SpriteShadow(hero, 3, 5, 4, 110)
SpriteShadowColor(hero, 20, 0, 40) ' a cold shadow, not a grey one
En skygge med opacitet 0 er ingen skygge. Det er sådan, du slår den fra.
Kontur#
SpriteOutline(spriteID, thickness, red, green, blue)
Konturen følger spritets silhuet, ikke det rektangel, det bor i: en gennemsigtig PNG får en kontur rundt om tegningen, ikke rundt om filen. Tykkelse er i skærmenheder, og 1 til 3 er det brugbare område. Over det begynder de otte retninger, konturen bygges af, at vise sig som otte lapper.
SpriteOutline(hero, 2, 255, 255, 255) ' the readable-on-anything outline
SpriteOutline(hero, 0, 0, 0, 0) ' off
Glød#
SpriteGlow(spriteID, red, green, blue, size)
En farvet glorie, der spreder sig size enheder ud over silhuetten. Den
sidder bag spritet og foran skyggen, hvilket er det, der lader dig bruge
begge.
SpriteGlow(pickup, 255, 210, 0, 10) ' this one is worth walking to
Sløring#
SpriteBlur(spriteID, radius)
Sløring er den mærkelige af de fire. De andre tre tegnes rundt om spritet; sløring erstatter spritets eget billede med en sløret kopi af det. Det betyder to ting, der er værd at vide:
- det koster ingenting pr. billede (det slørede billede beregnes én gang), og
- sløringen beskæres ved billedets kant. En tegning, der rører kanten af sin PNG, mister den del af sin glorie, der ellers ville falde uden for. Efterlad et par gennemsigtige pixels margin i filen, hvis du planlægger at sløre den.
SpriteColor bliver ved med at virke på et sløret sprite.
At slå alt fra, og til igen#
SpriteEffects(spriteID, 0) ' all four off
SpriteEffects(spriteID, 1) ' all four back, exactly as they were
SpriteEffects sletter ikke dine indstillinger. Det er en kontakt, ikke en
nulstilling, så en karakter kan blinke uden at du skal generklære dens skygge
bagefter.
De samme fire på tekst#
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)
Signaturerne stemmer nøjagtigt overens med sprite-versionerne, så der er intet nyt at lære. To forskelle i opførsel:
- En glød vinder over en skygges softness. Begge tegnes af den samme mekanisme, og en glød uden softness er usynlig, mens en skygge uden softness stadig er en skygge. Når du beder om begge, får gløden softnessen.
- Disse gælder for vektortekst, ikke for bitmap-font-tekst. En tekst
tegnet med
TextFontImageer en komposition af sprites; kommandoerne ignoreres stiltiende på den. Brug sprite-effekterne på spritesne i det tilfælde.
Et gennemarbejdet eksempel: læsbar på hvad som helst#
Det, disse kommandoer faktisk løser, er kontrast, du ikke kontrollerer. En hvid score er usynlig på sne; en sort er usynlig om natten. En kontur løser det én gang, for enhver baggrund, du nogensinde vil tegne.
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
At læse en effekt tilbage#
Hver parameter, du skriver, har en læser, ligesom SpriteColor har
SpriteColorRed. Det er dialektens regel, og disse kommandoer følger den.
IF SpriteEffectsEnabled(hero) = 1
SpriteEffects(hero, 0)
ENDIF
alpha = SpriteShadowAlpha(hero) ' 0 to 255
size = SpriteGlowSize(hero) ' 0 means no glow
Det fulde sæt, pr. familie: SpriteShadowOffsetX, SpriteShadowOffsetY,
SpriteShadowBlur, SpriteShadowAlpha, SpriteShadowColorRed,
SpriteShadowColorGreen, SpriteShadowColorBlue, SpriteGlowRed,
SpriteGlowGreen, SpriteGlowBlue, SpriteGlowSize,
SpriteOutlineThickness, SpriteOutlineRed, SpriteOutlineGreen,
SpriteOutlineBlue, SpriteBlurRadius, SpriteEffectsEnabled, plus de
samme sytten med et Text-præfiks.
To regler, det er værd at kende:
- Et sprite, der aldrig har fået en effekt, melder sig selv som TIL. Det er standardtilstanden; at svare 0 ville fortælle et program, at dets effekter er slået fra, før det har sat nogen.
- At spørge om et sprite, der ikke findes, svarer 0, det stopper ikke
programmet. Det er, hvordan dialekten behandler spørgsmål alle steder:
SpriteHitsvarer 0, når intet berøres, og programmer læser den 0 uden at teste den.
Hvad det koster#
Skygge, kontur og glød tegnes, så de koster draw calls: én til skyggen (tre når den er blød), fire til en glød, otte til en kontur. En skærm med to hundrede sprites med kontur er en skærm, der tegner atten hundrede quads, og det vil vise sig. De er ment til den håndfuld ting, spilleren skal lægge mærke til: karakteren, genstanden, den valgte enhed.
Sløring koster ingenting pr. billede.
En praktisk regel: effekter på det, der bevæger sig og betyder noget, ingen på baggrunden.
Hvad der overlever til et eksporteret spil#
| Mål | Skygge, kontur, glød | Sløring | Teksteffekter |
|---|---|---|---|
| Editoren | ja | ja | ja |
| HTML5-eksport | ja | ja | ja |
| Native og wasm (Bevy) | ja | nej | nej |
Skygge, kontur og glød er bygget af almindelige sprites, så de rejser overalt, sprites gør. Sløring og teksteffekterne har brug for en bro, Bevy-målene endnu ikke har: eksportens konverteringsrapport navngiver dem i stedet for at droppe dem stiltiende, så en build fortæller dig, hvad den ikke kunne bære med.
Hvor effekterne ikke er#
Der findes intet SpriteEffect(id, "glow", ...), der tager effektnavnet som
en streng. Hver effekt er sin egen kommando, så dens parametre kan navngives,
dokumenteres og autofuldføres, mens du skriver. For alt ud over disse fire
overtager to andre kommandoer: SpriteBlendModes(id, src, dst) til additiv
eller multiplikativ blanding (en ild, en laser), og SpriteShader(id, shaderID) til at sætte en shader kompileret af LoadSpriteShader på et
sprite. Begge var erklæret i kataloget i lang tid uden en implementering, og
at kalde dem gav en fejl; nu virker de.