Callbacks
Bahagian ini merangkumi pengumpulan data, pembinaan fungsi kesan, dan penggunaan kelas Meter untuk mencetuskan fungsi tersebut. Tidak akan ada penekanan pada penjelasan animasi atau spesifik pengendali kesan kami, jadi jika Anda perlu mengulang semula, saya akan menyemak bahagian Tutorial atau Rujukan API kami.
Proses untuk mencetuskan animasi dari awal hingga akhir dengan berkesan adalah:
- Gunakan kaedah Meter.setValue(value) di dalam fungsi kemaskini untuk memasukkan data meter mentah ke dalam contoh kelas Meter Anda.
- Jika Meter menganggap dirinya stabil, ia akan mengaktifkan fungsi panggilan balik yang dihantar sebagai parameter keduanya.
- Fungsi panggilan balik ini mengandungi logik bersyarat untuk menilai keadaan Meter. Jika keadaan adalah benar, kesan Anda harus ditambah ke susunan kesan (effects.push(new yourEffect())) atau pengendali keadaan (steMgr.Push(new yourEffect())).
- Setiap jalan fungsi kemaskini menilai susunan kesan penuh dan elemen terkini dalam pengendali keadaan. Pada peringkat ini, kesan dilukis berdasarkan pemboleh ubah keadaan.
- Selepas dilukis, setiap kesan menyumbang kepada memeriksa jangka hayatnya. Kesan dalam susunan kesan hanya mengulang pemboleh ubah jangka hayat yang ditetapkan kepada contoh kelas mereka. Apabila jangka hayat adalah 0 atau kurang, kesan mudah dialih keluar dengan splice semasa penilaian susunan kesan. Kesan dalam pengendali keadaan boleh mengalih keluar diri mereka sendiri apabila diperlukan kerana pengendali keadaan berfungsi sebagai tindanan, dan logik bersyarat untuk kesan ini cenderung lebih rumit.
Meter ini mencari bar kesihatan biasa dan akan mengembalikan peratusan warna yang sepadan sebagai nombor antara 0 dan 1. Julat HSL agak luas dalam kes ini untuk mengambil kira kecerunan dalam pewarnaan bar. Ini memperkenalkan isu — apabila bar kesihatan mengecil, ia sebenarnya mendedahkan latar belakang telus, yang mungkin termasuk elemen hijau dari persekitaran permainan yang lulus pemeriksaan warna dan mengganggu meter kita.
<head> <meta meter="health" tags="example" x= ".05" y=".9" width=".189" h="70-140" s="40-100" l="40-100" type="linear"/></head>Kelas Meter
Section titled “Kelas Meter”Di sini, saya telah mencipta contoh kelas Meter yang dipanggil healthM untuk mengaktifkan kesan “mengambil kerosakan”.
<script> // Meter instance var healthM = new Meter(25, healthHelper);
function update () => { healthM.setValue(health); window.requestAnimationFrame(update); }
function healthHelper () => { // "Took Damage" effect up next }
// . . .
</script>Saya telah memberikan keperluan kestabilan yang agak tinggi (25) untuk mengambil kira isu ketidakstabilan di atas. Fungsi panggilan balik yang dilampirkan hanya akan diaktifkan jika nilai meter stabil selama 25 kemaskini, yang akan mengecualikan kebanyakan data yang bukan bar kesihatan sebenar, walaupun pemain masih pegun. Satu-satunya kelemahan ini adalah kelewatan kesan yang semakin meningkat, yang akan sentiasa menjadi faktor pembatas dalam senario ini. Untuk bar kesihatan tertentu ini, kita boleh mengatasinya sekurang-kurangnya dalam beberapa cara:
- Apabila terkena, sebahagian bar hijau serta-merta ditukar kepada merah sebelum mengecil ke tahap kesihatan hijau yang baru. Jika kita menambah meter healthRed yang mencari merah di tempat yang sama dengan meter kesihatan, kita boleh menggabungkan nilai mereka untuk pencetus yang lebih cepat. Syarat bersyarat if ( healthM.decreased && healthRed.increased ) sepatutnya memberikan ketepatan yang baik dalam kes ini.
- Kita juga boleh menggabungkan bacaan beberapa meter linear dengan tetapan warna yang sama. Saya kini mempunyai satu meter linear yang ditetapkan di tengah bar kesihatan. Jika saya menyediakan dua lagi, satu sedikit di atas dan di bawah yang asal tetapi masih di dalam bar kesihatan, kedekatan tiga nilai meter boleh digunakan sebagai pemeriksaan kestabilan tambahan. Ketiga-tiga meter perlu membaca Meter.decreased dan berada dalam julat kecil nilai antara satu sama lain untuk mencetuskan kesan.
Panggilan Balik
Section titled “Panggilan Balik”Fungsi panggilan balik ini hanya berjalan selepas meter mengesahkan bahawa semua elemen dalam susunan nilainya adalah sama. Ini memastikan bahawa nilai meter adalah berdasarkan data yang stabil. Di dalam panggilan balik, saya akan menggunakan pernyataan bersyarat untuk menentukan sama ada kesan harus dimainkan.
let healthPrev = 0;
function healthHelper () => { if (healthM.decreased && healthM.value != healthPrev){ effects.push(new healthEffect()); healthPrev = healthM.value; }}Pernyataan bersyarat memerlukan dua syarat benar: penurunan stabil dalam meter dan ketidakpadanan antara nilai meter semasa dan nilai yang direkod sebelumnya. Saya menambah syarat kedua ini untuk mengelakkan pepijat. Jika kita hanya memeriksa penurunan, kesan akan dimainkan berulang kali. Memandangkan Meter.decreased ditetapkan sebaik sahaja meter menstabilkan, nilainya kekal sama selagi meter tidak berubah. Dengan cara ini, kesan hanya akan dimainkan jika terdapat penurunan yang berbeza daripada nilai stabil terakhir.
Saya akan mencipta dua kesan untuk Anda: satu untuk dimasukkan ke dalam susunan kesan, dan satu lagi untuk pengendali keadaan.
Susunan Kesan
Section titled “Susunan Kesan”Blok kod pertama ini mentakrifkan fungsi kesan yang dimaksudkan untuk susunan kesan. Ia direka untuk menjadi pantas dan ringan untuk membolehkan berbilang kesan kecil berjalan serentak. Untuk mengurangkan beban sistem, saya juga menjadikan kesan mudah untuk disesuaikan melalui parameter untuk penggunaan semula.
function healthEffect(color, direction, speed){ // The lifetime of the effect should be iterated in the draw function. this.lifetime = 200; this.speed = speed; this.direction = direction; this.color = color;
this.draw = () => { // Set fill from parameter ctx.fillStyle = `hsl(${this.color}, 100%, 50%)`; // Check direction if (this.direction == "up"){ ctx.fillRect(0, this.lifetime, width, 30); } else { ctx.fillRect(0, height - this.lifetime, width, 30); } // As the lifetime decreases by 5 each update, the rectangle moves accordingly. this.lifetime -= speed; } }function update() { // Background color ctx.fillStyle = "black"; ctx.fillRect(0, 0, 320, 200);
// Draw all effects in array and remove them if they are done. effects.forEach((ele, i) => { ele.draw(); if (ele.lifetime == 0){ effects.splice(i, 1); } })
window.requestAnimationFrame(update);}function healthHelper () => { if (healthM.decreased && healthM.value != healthPrev){ // Make sure to correctly set the color and direction paremeters. effects.push(new healthEffect(1, "down", 5)); healthPrev = healthM.value; }}Inilah bagaimana ia sepatutnya kelihatan dalam tindakan:

Terima kasih kepada reka bentuk fungsi yang boleh diedit, kita boleh dengan mudah mencipta kesan penyembuhan juga! Hanya tambah syarat bersyarat tambahan kepada fungsi panggilan balik.
function healthHelper () => { if (healthM.decreased && healthM.value != healthPrev){ // Damage effect effects.push(new healthEffect(1, "down", 5)); healthPrev = healthM.value; } if (healthM.increased && healthM.value != healthPrev){ // Healing effect effects.push(new healthEffect(120, "up", 5)); healthPrev = healthM.value; }}
Kesederhanaan kesan ini adalah kelebihan terbesarnya untuk pembangun LightScript. Daripada mencipta kesan reka bentuk tersuai, masing-masing memerlukan ratusan baris kod, bina kesan kecil yang boleh digunakan semula yang berfungsi sebagai blok binaan untuk pencetus tertentu. Tiga kesan seterusnya adalah variasi berdasarkan kesan kecil yang baru kita cipta. Jangan ragu untuk bereksperimen dan lihat apa yang boleh Anda capai!



Pengendali Keadaan
Section titled “Pengendali Keadaan”Saya secara peribadi menyimpan pengendali keadaan untuk kesan besar dan kompleks dengan logik keadaan yang sangat spesifik, terutamanya apabila Anda ingin kesan mengambil keutamaan ke atas semua yang lain. Ingat bahawa pengendali keadaan berfungsi seperti tindanan dan hanya menjalankan kesan teratas; setiap kesan keadaan bertanggungjawab untuk mengalih keluar dirinya sendiri apabila selesai. Contoh ini menunjukkan animasi lobi cari padanan yang menyesuaikan diri berdasarkan sama ada Anda sedang mencari atau tidak. Ia juga termasuk susunan kesan kecilnya sendiri dengan kesan pembantu. Meter yang digunakan di sini adalah inLobby dan yellowPlayButton, yang hanya mengaktifkan dalam lobi cari padanan. yellowPlayButton bertukar warna bergantung pada sama ada Anda sedang mencari.
function lobbyAnimation(){ // Instance variables this.start = new Date().getTime(); this.elapsed = 0; this.radius = 0; this.searching = 1000; // Instance effects array this.effects = [];
// Process is the method that allows a state effect to remove itself this.Process = function () { // If the lobby menu and play button disappear, remove the effect if (inLobby.decreased && yellowPlayButton.decreased) { stateMgr.Pop(); // Global boolean to prevent duplicate lobby effects in the state handler lobbyAnim = false; } // If the play button is present, edit this.searching based on its color yellowPlayButton.value == 1 ? this.searching = 1000 : this.searching = 100; // Call the Draw function attached to the effect this.Draw(); };
this.Draw = function(){ // Iterate important variables this.elapsed = new Date().getTime() - this.start; this.radius = 50 + (Math.sin(this.elapsed/this.searching)*10);
// Fill the background to overwrite other effects ctx.fillStyle = 'black'; ctx.fillRect(0, 0, 320, 200);
// Draw the main arc ctx.beginPath(); ctx.strokeStyle = `hsl(120, 100%, 50%)`; ctx.lineWidth = 20; ctx.arc(160, 100, this.radius, 0, 2 * Math.PI); ctx.stroke(); // If the main arc is the right size, push helper effects into the helper array if(this.radius > 59 && this.elapsed % 2 == 0){ this.effects.push(new lobbyHelper(160, 100, 69)); } // Play and remove helper effects if necessary this.effects.forEach((e, i) => { ctx.lineWidth = 1; e.draw(); if (e.radius > 360) { this.effects.splice(i, 1); } }); } }
function lobbyHelper(x, y, radius){ this.x = x; this.y = y; this.radius = radius; this.draw = function(){ // Set the global transparency value. 1 is opaque, 0 is invisible. ctx.globalAlpha = 1 - this.radius/360; ctx.beginPath(); ctx.strokeStyle = `hsl(120, 100%, ${50 + (this.radius/7)}%)`; ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI); ctx.stroke(); // Set the global transparency back to 1 so your other effects are opaque ctx.globalAlpha = 1; this.radius++; }}// Declare state handler (found in Snippets)var stateMgr = new StateHandler();// Global boolean to prevent duplicate lobby animationsvar lobbyAnim = false;
function update(){ // Run the Process function to draw the animation stateMgr.Process();}function lobbyAnimationPlay(){ if(inLobby.value == 1 && yellowPlayButton.value == 1 && !lobbyAnim){ stateMgr.Push(new lobbyAnimation()); lobbyAnim = true; }};Tidak Mencari:

Mencari:

Dan itulah yang membungkus tutorial callbacks kami, serta panduan rasmi dev SignalRGB. Nantikan penambahan seterusnya dan terakhir kepada panduan kami, Penyelenggaraan Lightscript!