Kesan sprite dan teks
Shadow, outline, glow dan blur pada sprite 2D dan pada teks, dengan kos setiap satu, kesannya pada satu sprite yang bergerak, dan resipi buatan tangan yang digantikannya.
Untuk apa ini#
Sehingga kini satu sprite 2D boleh membawa satu tint dan satu imej, dan tiada apa-apa lagi. Untuk mengangkat satu watak daripada latar belakangnya anda terpaksa membina kesan itu secara manual: cipta satu sprite kedua, tint hitam, offset, letak di belakang, dan pastikan ia sentiasa selari dengan sprite pertama pada setiap bingkai. Ia berfungsi. Ia juga empat baris tambahan kerja perakaunan bagi setiap watak, dan pada hari anda terlupa satu daripadanya, bayang itu tertinggal di belakang pemiliknya.
Empat arahan melakukan itu untuk anda, pada sprite dan pada teks:
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
Tiada apa-apa lagi untuk diselenggara. Alih sprite itu, skalakan, flip, mainkan animasinya: kesan-kesan itu mengikutinya.
Empat kesan itu#
Shadow#
SpriteShadow(spriteID, offsetX, offsetY, softness, opacity)
SpriteShadowColor(spriteID, red, green, blue)
offsetX dan offsetY dalam unit skrin anda sendiri, dikira dengan cara
yang sama seperti SpritePosition: Y positif ialah ke bawah. softness
merebakkan bayang itu; opacity berjalan dari 0 hingga 255. Warnanya hitam
melainkan anda nyatakan sebaliknya.
SpriteShadow(hero, 3, 5, 4, 110)
SpriteShadowColor(hero, 20, 0, 40) ' satu bayang sejuk, bukan satu yang kelabu
Satu bayang dengan opacity 0 bukan satu bayang. Begitulah caranya anda mematikannya.
Outline#
SpriteOutline(spriteID, thickness, red, green, blue)
Outline mengikut siluet sprite itu, bukan segi empat tempat ia hidup: satu PNG lutsinar mendapat satu outline di sekeliling lukisan itu, bukan di sekeliling fail itu. Thickness dalam unit skrin, dan 1 hingga 3 adalah julat yang berguna. Melebihi itu lapan arah yang membina outline itu mula kelihatan sebagai lapan lob.
SpriteOutline(hero, 2, 255, 255, 255) ' outline yang boleh dibaca pada apa sahaja
SpriteOutline(hero, 0, 0, 0, 0) ' mati
Glow#
SpriteGlow(spriteID, red, green, blue, size)
Satu halo berwarna, merebak size unit melepasi siluet itu. Ia berada di
belakang sprite dan di hadapan bayang, dan itulah yang membolehkan anda
menggunakan kedua-duanya.
SpriteGlow(pickup, 255, 210, 0, 10) ' yang ini berbaloi untuk dijalani
Blur#
SpriteBlur(spriteID, radius)
Blur adalah yang berbeza. Tiga yang lain dilukis di sekeliling sprite itu; blur menggantikan imej sprite itu sendiri dengan satu salinan kabur daripadanya. Itu bermaksud dua perkara yang berbaloi diketahui:
- ia tidak memakan apa-apa kos setiap bingkai (imej kabur itu dikira sekali sahaja), dan
- kabur itu dipotong pada tepi imej itu. Satu lukisan yang menyentuh tepi PNG-nya kehilangan bahagian halonya yang sepatutnya jatuh di luar. Tinggal beberapa piksel lutsinar sebagai jidar dalam fail itu jika anda merancang untuk mengaburkannya.
SpriteColor terus berfungsi pada satu sprite yang kabur.
Mematikan segalanya, dan menghidupkannya semula#
SpriteEffects(spriteID, 0) ' kesemua empat mati
SpriteEffects(spriteID, 1) ' kesemua empat kembali, tepat seperti sediakala
SpriteEffects tidak memadamkan tetapan anda. Ia satu suis, bukan satu
reset, jadi satu watak boleh berkelip tanpa anda perlu mengisytiharkan
semula bayangnya selepas itu.
Empat kesan yang sama pada teks#
score = CreateText("SCORE 0")
TextPositionSet(score, 10, 10)
TextSizeSet(score, 6)
TextOutline(score, 3, 0, 0, 0) ' boleh dibaca pada mana-mana latar
TextShadow(score, 2, 2, 4, 160)
TextGlow(score, 255, 80, 0, 6)
TextBlur(score, 0)
TextEffects(score, 1)
Tandatangannya sepadan tepat dengan yang sprite, jadi tiada apa-apa baharu untuk dipelajari. Dua perbezaan dalam kelakuan:
- Satu glow mengatasi softness satu shadow. Kedua-duanya dilukis oleh mekanisme yang sama, dan satu glow tanpa softness tidak kelihatan manakala satu shadow tanpa softness masih satu shadow. Apabila anda meminta kedua-duanya, glow itu mendapat softness itu.
- Ini terpakai pada teks vektor, bukan pada teks bitmap-font. Satu teks
yang dilukis dengan
TextFontImageadalah satu komposisi sprite; arahan itu diabaikan secara senyap padanya. Gunakan kesan sprite pada sprite-sprite dalam kes itu.
Satu contoh terperinci: boleh dibaca pada apa sahaja#
Masalah yang sebenarnya diselesaikan oleh arahan ini ialah kontras yang tidak anda kawal. Satu skor putih tidak kelihatan pada salji; satu yang hitam tidak kelihatan pada waktu malam. Satu outline menyelesaikannya sekali sahaja, untuk setiap latar belakang yang akan anda lukis.
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
Membaca semula satu kesan#
Setiap parameter yang anda tulis mempunyai satu pembaca, cara yang sama
seperti SpriteColor mempunyai SpriteColorRed. Itulah peraturan dialek
ini, dan arahan-arahan ini mengikutinya.
IF SpriteEffectsEnabled(hero) = 1
SpriteEffects(hero, 0)
ENDIF
alpha = SpriteShadowAlpha(hero) ' 0 hingga 255
size = SpriteGlowSize(hero) ' 0 bermakna tiada glow
Set lengkap, bagi setiap keluarga: SpriteShadowOffsetX,
SpriteShadowOffsetY, SpriteShadowBlur, SpriteShadowAlpha,
SpriteShadowColorRed, SpriteShadowColorGreen, SpriteShadowColorBlue,
SpriteGlowRed, SpriteGlowGreen, SpriteGlowBlue, SpriteGlowSize,
SpriteOutlineThickness, SpriteOutlineRed, SpriteOutlineGreen,
SpriteOutlineBlue, SpriteBlurRadius, SpriteEffectsEnabled, ditambah
tujuh belas yang sama dengan prefix Text.
Dua peraturan yang berbaloi diketahui:
- Satu sprite yang tidak pernah diberikan satu kesan melaporkan dirinya sebagai HIDUP. Itulah keadaan lalai; menjawab 0 akan memberitahu satu program kesannya telah dimatikan sebelum ia menetapkan mana-mana pun.
- Bertanya tentang satu sprite yang tidak wujud menjawab 0, ia tidak
menghentikan program. Begitulah cara dialek ini melayan soalan di
merata-rata:
SpriteHitmenjawab 0 apabila tiada apa yang tersentuh, dan program membaca 0 itu tanpa mengujinya.
Apa kosnya#
Shadow, outline dan glow dilukis, jadi ia memakan kos draw call: satu untuk shadow (tiga apabila ia lembut), empat untuk satu glow, lapan untuk satu outline. Satu skrin dengan dua ratus sprite beroutline adalah satu skrin yang melukis seribu lapan ratus quad, dan ia akan kelihatan. Ia ditujukan untuk sebilangan kecil perkara yang sepatutnya dilihat oleh pemain: watak itu, pickup itu, unit yang dipilih.
Blur tidak memakan apa-apa kos setiap bingkai.
Satu peraturan praktikal: kesan pada apa yang bergerak dan penting, tiada pada latar belakang.
Apa yang terus wujud dalam satu permainan yang dieksport#
| Sasaran | Shadow, outline, glow | Blur | Kesan teks |
|---|---|---|---|
| Editor | ya | ya | ya |
| Eksport HTML5 | ya | ya | ya |
| Native dan wasm (Bevy) | ya | tidak | tidak |
Shadow, outline dan glow dibina daripada sprite biasa, jadi ia berjalan ke mana sahaja sprite berjalan. Blur dan kesan teks memerlukan satu jambatan yang belum dimiliki oleh sasaran Bevy: laporan penukaran menamakannya berbanding membuangnya secara senyap, jadi satu binaan memberitahu anda apa yang tidak dapat dibawanya.
Di mana kesan-kesan ini tidak wujud#
Tiada SpriteEffect(id, "glow", ...) yang mengambil nama kesan sebagai satu
string. Setiap kesan adalah arahannya sendiri supaya parameternya boleh
dinamakan, didokumenkan dan dilengkapkan semasa anda menaip. Untuk apa-apa
yang melebihi empat ini, dua arahan lain mengambil alih:
SpriteBlendModes(id, src, dst) untuk blending additif atau berdarab (satu
api, satu laser), dan SpriteShader(id, shaderID) untuk meletakkan satu
shader yang dikompil oleh LoadSpriteShader pada satu sprite. Kedua-duanya
telah diisytiharkan dalam katalog untuk masa yang lama tanpa satu
implementasi, dan memanggilnya membangkitkan satu ralat; ia berfungsi
sekarang.