Sprite- og teksteffekter

Skygge, omriss, glød og uskarphet på 2D-sprites og på tekst, med hva hver av dem koster, hva den gjør med en sprite i bevegelse, og oppskriften den erstatter.

Hva dette er til for#

Frem til nå kunne en 2D-sprite bære en tone og et bilde, og ingenting annet. For å løfte en karakter fra bakgrunnen måtte du bygge effekten for hånd: opprette en ny sprite, tone den svart, forskyve den, legge den bak, og holde den i takt med den første på hver eneste ramme. Det fungerer. Det er også fire ekstra linjer med bokføring per karakter, og den dagen du glemmer én av dem, henger skyggen etter eieren sin.

Fire kommandoer gjør det for deg, 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

Ingenting annet å vedlikeholde. Flytt spriten, skaler den, snu den, spill animasjonen: effektene følger med.

De fire effektene#

Shadow#

SpriteShadow(spriteID, offsetX, offsetY, softness, opacity)
SpriteShadowColor(spriteID, red, green, blue)

offsetX og offsetY er i dine egne skjermenheter, telt på samme måte som SpritePosition: positiv Y er ned. softness sprer skyggen; opacity går fra 0 til 255. Fargen er svart med mindre du sier noe annet.

SpriteShadow(hero, 3, 5, 4, 110)
SpriteShadowColor(hero, 20, 0, 40)      ' en kald skygge, ikke en grå

En skygge med opasitet 0 er ingen skygge. Det er slik du slår den av.

Outline#

SpriteOutline(spriteID, thickness, red, green, blue)

Omrisset følger silhuetten til spriten, ikke rektangelet den bor i: en gjennomsiktig PNG får et omriss rundt tegningen, ikke rundt filen. Tykkelse er i skjermenheter, og 1 til 3 er det brukbare området. Over det begynner de åtte retningene omrisset er bygget av, å vise seg som åtte lober.

SpriteOutline(hero, 2, 255, 255, 255)   ' omrisset som er lesbart på hva som helst
SpriteOutline(hero, 0, 0, 0, 0)         ' av

Glow#

SpriteGlow(spriteID, red, green, blue, size)

En farget glorie, som sprer seg size enheter forbi silhuetten. Den ligger bak spriten og foran skyggen, som er det som lar deg bruke begge.

SpriteGlow(pickup, 255, 210, 0, 10)     ' denne er verdt å gå bort til

Blur#

SpriteBlur(spriteID, radius)

Blur er avviket. De tre andre tegnes rundt spriten; blur erstatter spritens eget bilde med en uskarp kopi av det. Det betyr to ting verdt å vite:

  • det koster ingenting per ramme (det uskarpe bildet beregnes én gang), og
  • uskarpheten klippes ved kanten av bildet. En tegning som berører kanten av sin PNG, mister den delen av gloen sin som ville falt utenfor. La det stå igjen noen gjennomsiktige piksler med margin i filen hvis du planlegger å gjøre den uskarp.

SpriteColor fortsetter å fungere på en uskarp sprite.

Å slå alt av, og på igjen#

SpriteEffects(spriteID, 0)   ' alle fire av
SpriteEffects(spriteID, 1)   ' alle fire tilbake, akkurat som de var

SpriteEffects sletter ikke innstillingene dine. Det er en bryter, ikke en tilbakestilling, så en karakter kan blinke uten at du må erklære skyggen sin på nytt etterpå.

De samme fire på tekst#

score = CreateText("SCORE 0")
TextPositionSet(score, 10, 10)
TextSizeSet(score, 6)

TextOutline(score, 3, 0, 0, 0)          ' lesbart på hvilken som helst bakgrunn
TextShadow(score, 2, 2, 4, 160)
TextGlow(score, 255, 80, 0, 6)
TextBlur(score, 0)
TextEffects(score, 1)

Signaturene stemmer nøyaktig overens med sprite-versjonene, så det er ingenting nytt å lære. To forskjeller i oppførsel:

  • En glow vinner over en shadows softness. Begge tegnes av samme mekanisme, og en glow uten softness er usynlig mens en shadow uten softness fortsatt er en shadow. Når du ber om begge, får glowen softnessen.
  • Disse gjelder for vektortekst, ikke for bitmap-font-tekst. En tekst tegnet med TextFontImage er en sammensetning av sprites; kommandoene ignoreres stille på den. Bruk sprite-effektene på spritene i det tilfellet.

Et gjennomarbeidet eksempel: lesbart på hva som helst#

Problemet disse kommandoene faktisk løser, er kontrast du ikke kontrollerer. En hvit poengsum er usynlig på snø; en svart er usynlig om natten. Et omriss løser det én gang, for hver bakgrunn du noensinne kommer til å 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

Å lese en effekt tilbake#

Hver parameter du skriver, har en leser, på samme måte som SpriteColor har SpriteColorRed. Det er dialektens regel, og disse kommandoene følger den.

IF SpriteEffectsEnabled(hero) = 1
  SpriteEffects(hero, 0)
ENDIF

alpha = SpriteShadowAlpha(hero)      ' 0 til 255
size  = SpriteGlowSize(hero)         ' 0 betyr ingen glow

Hele settet, per familie: SpriteShadowOffsetX, SpriteShadowOffsetY, SpriteShadowBlur, SpriteShadowAlpha, SpriteShadowColorRed, SpriteShadowColorGreen, SpriteShadowColorBlue, SpriteGlowRed, SpriteGlowGreen, SpriteGlowBlue, SpriteGlowSize, SpriteOutlineThickness, SpriteOutlineRed, SpriteOutlineGreen, SpriteOutlineBlue, SpriteBlurRadius, SpriteEffectsEnabled, pluss de samme sytten med et Text-prefiks.

To regler verdt å vite:

  • En sprite som aldri har fått en effekt, rapporterer seg selv som PÅ. Det er standardtilstanden; å svare 0 ville fortalt et program at effektene dets er kuttet før det har satt noen.
  • Å spørre om en sprite som ikke finnes, svarer 0, det stopper ikke programmet. Det er slik dialekten behandler spørsmål overalt: SpriteHit svarer 0 når ingenting berøres, og programmer leser den 0-en uten å teste den.

Hva det koster#

Shadow, outline og glow tegnes, så de koster draw calls: én for skyggen (tre når den er myk), fire for en glow, åtte for et omriss. En skjerm med to hundre spriter med omriss er en skjerm som tegner atten hundre quads, og det vil vise seg. De er ment for den håndfullen ting spilleren er ment å se på: karakteren, gjenstanden, den valgte enheten.

Blur koster ingenting per ramme.

En praktisk regel: effekter på det som beveger seg og betyr noe, ingen på bakgrunnen.

Hva som overlever en eksport til et spill#

MålShadow, outline, glowBlurTeksteffekter
Editorenjajaja
HTML5-eksportjajaja
Native og wasm (Bevy)janeinei

Shadow, outline og glow er bygget av vanlige sprites, så de følger med overalt sprites gjør det. Blur og teksteffektene trenger en bro Bevy-målene ikke har ennå: eksport-konverteringsrapporten navngir dem i stedet for å droppe dem stille, så et bygg forteller deg hva det ikke kunne ta med.

Hvor effektene ikke er#

Det finnes ingen SpriteEffect(id, "glow", ...) som tar effektnavnet som en streng. Hver effekt er sin egen kommando, slik at parameterne kan navngis, dokumenteres og fullføres mens du skriver. For alt utover disse fire tar to andre kommandoer over: SpriteBlendModes(id, src, dst) for additiv eller multiplisert blending (en ild, en laser), og SpriteShader(id, shaderID) for å legge en shader kompilert av LoadSpriteShader på en sprite. Begge var deklarert i katalogen lenge uten en implementasjon, og å kalle dem gav en feil; nå fungerer de.