สนิปเพ็ต
ส่วนนี้รวบรวมสนิปเพ็ตโค้ดที่มีประโยชน์สามแบบสำหรับ LightScripts ของคุณ ได้แก่ มิเตอร์ (meter), ตัวจัดการสถานะ (state handler) และ ตัวจัดการเอฟเฟกต์ (effects handler)
มิเตอร์ (The Meter)
หัวข้อที่มีชื่อว่า “มิเตอร์ (The Meter)”ต่อเนื่องจากส่วนก่อนหน้า คลาส Meter ถูกออกแบบมาเพื่อช่วยติดตามการเปลี่ยนแปลงที่มีความหมายในข้อมูลมิเตอร์ที่ไม่เสถียร ให้คิดว่ามันเป็นเหมือนแป้นเบรกสำหรับโค้ดของคุณ ซึ่งช่วยให้เกิดความเสถียรแม้ในโซนที่ซับซ้อน แต่ละมิเตอร์จะเก็บอาร์เรย์ของค่าที่ปรับแต่งได้ ซึ่งรวบรวมระหว่างการทำงานแต่ละรอบของฟังก์ชัน update ของคุณ เมื่อค่าทั้งหมดในอาร์เรย์นั้นเหมือนกัน (กล่าวคือข้อมูล “เสถียร”) มิเตอร์จะอัปเดตค่าของตัวเองและเรียกฟังก์ชัน callback ที่เชื่อมโยงไว้เพื่อเปิดใช้งานเอฟเฟกต์
| เมธอด | คำอธิบาย |
|---|---|
| Meter(size, callback) | คอนสตรักเตอร์รับทั้ง size และ callback\n\n\n\nsize - จำนวนครั้งที่ค่าเดียวกันต้องปรากฏ เพื่อให้ค่ามิเตอร์ถือว่า ‘เสถียร’ พอที่จะนำไปประมวลผล ค่าที่สูงขึ้นให้ความแม่นยำมากขึ้น ค่าที่ต่ำลงให้ความหน่วงน้อยลง\n\n\ncallback - ฟังก์ชันที่จะถูกเรียกเมื่อค่ามิเตอร์เสถียรและมีการเปลี่ยนแปลง |
| Meter.setValue(value) | คุณควรเรียก setValue(value) ทุกเฟรม หรือทุกครั้งที่มีข้อมูลดิบใหม่สำหรับมิเตอร์นี้ |
โดยทั่วไป กระบวนการรวบรวมข้อมูลจากหน้าจอควรเป็นไปตามโครงสร้างนี้:
- ค่า engine.vision.meter อัปเดตตามข้อมูลใหม่จากหน้าจอ
- ภายในฟังก์ชัน update จะมีการเรียก Meter.setValue(engine.vision.meter) เพื่อบันทึกค่าใหม่
- Meter ตรวจสอบอาร์เรย์ภายในว่าค่าทั้งหมดเหมือนกันหรือไม่ หากเหมือนกัน จะอัปเดตสถานะของตัวเองและเรียกใช้ฟังก์ชัน callback ที่กำหนดไว้
- จากนั้นฟังก์ชัน callback จะประเมินเงื่อนไขเฉพาะโดยใช้ตัวแปรของ Meter และรันโค้ดหากเงื่อนไขเหล่านั้นเป็นจริง
หมายเหตุสำคัญ:
อย่าข้ามการใช้ callback เนื่องจากฟังก์ชัน update ทำงานอย่างต่อเนื่อง จึงต้องมีประสิทธิภาพมากที่สุดเท่าที่จะทำได้ หน้าที่หลักของมันควรเป็นการอัปเดตค่าของ Meter หลีกเลี่ยงการต่อเงื่อนไขหลายชั้นภายใน update เพื่อตรวจสอบมิเตอร์และเรียกเอฟเฟกต์ เพราะจะทำให้เกิดการตรวจสอบที่ไม่จำเป็นในทุกรอบ ให้กำหนดเอฟเฟกต์ของคุณในฟังก์ชันแยกต่างหาก แล้วส่งเข้าไปใน Meter เป็น callback แทน
ตัวแปรของ Meter
หัวข้อที่มีชื่อว่า “ตัวแปรของ Meter”เมื่อเสถียรแล้ว Meter จะให้ค่าบางอย่างแก่ฟังก์ชัน callback ของมัน:
| ตัวแปร | คำอธิบาย |
|---|---|
| Meter.value | ค่าปัจจุบันของมิเตอร์ |
| Meter.increased | ค่า boolean ที่บอกว่าค่าของเราเพิ่มขึ้นในการอัปเดตครั้งนี้หรือไม่ |
| Meter.decreased | ค่า boolean ที่บอกว่าค่าของเราลดลงในการอัปเดตครั้งนี้หรือไม่ |
| Meter.diff | ค่าสัมบูรณ์ ของการเปลี่ยนแปลงที่มิเตอร์เกิดขึ้นในการอัปเดตครั้งนี้ |
ตัวอย่าง Meter
หัวข้อที่มีชื่อว่า “ตัวอย่าง Meter”ต่อไปนี้คือการตั้งค่ามิเตอร์เดี่ยวแบบพื้นฐาน พร้อมโค้ดคลาส Meter:
<head> <title>Meter Example</title> <meta description="Step-by-step metering" /> <meta meter="health" tags="vlc,fortnite" x= ".05" y=".9" width=".189" h="70-140" s="40-100" l="40-100" type="linear" /></head>
<body style="margin: 0; padding: 0; background: #000;"> <canvas id="exCanvas" width="320" height="200"></canvas></body>
<script> var c = document.getElementById("exCanvas"); var ctx = c.getContext("2d");
// Initialize meter var healthMeter = new Meter(5, healthEffect);
function update(){ // Update Meter values healthMeter.setValue(engine.vision.health);
window.requestAnimationFrame(update); }
function healthEffect(){ if(healthMeter.increased){ // Trigger effect } else if (healthMeter.value == 0){ // Trigger effect } else if (healthMeter.diff > .3){ // Trigger effect } }
function Meter(size, callback) { this.size = size; this.value = 0; this.diff = 0; this.increased = false; this.decreased = false; var values = [];
this.setValue = function (updatedValue) { // Add and shift. values.push(updatedValue); if (values.length > this.size) { values.shift(); }
// Exit early if we don't have a long-term match. for (var i = 0; i < values.length - 1; i++) { if (values[i] !== values[i + 1]) return; }
// We got here, so we've got a matching value collection. Set variables and execute callback. if (this.value !== values[0]) { this.diff = Math.abs(this.value - values[0]); this.increased = this.value < values[0]; this.decreased = this.value > values[0]; this.value = values[0]; callback(); } }; }
window.requestAnimationFrame(update);
</script><head> <title>Meter Example</title> <meta description="Step-by-step metering" /> <meta meter="health" tags="vlc,fortnite" x= ".05" y=".9" width=".189" h="70-140" s="40-100" l="40-100" type="linear" /></head><body style="margin: 0; padding: 0; background: #000;"> <canvas id="exCanvas" width="320" height="200"></canvas></body><script> var c = document.getElementById("exCanvas"); var ctx = c.getContext("2d");
// Initialize meter var healthMeter = new Meter(5, healthEffect);
function update(){ // Update Meter values healthMeter.setValue(engine.vision.health);
window.requestAnimationFrame(update); }
function healthEffect(){ if(healthMeter.increased){ // Trigger effect } else if (healthMeter.value == 0){ // Trigger effect } else if (healthMeter.diff > .3){ // Trigger effect } }
function Meter(size, callback) { this.size = size; this.value = 0; this.diff = 0; this.increased = false; this.decreased = false; var values = [];
this.setValue = function (updatedValue) { // Add and shift. values.push(updatedValue); if (values.length > this.size) { values.shift(); }
// Exit early if we don't have a long-term match. for (var i = 0; i < values.length - 1; i++) { if (values[i] !== values[i + 1]) return; }
// We got here, so we've got a matching value collection. Set variables and execute callback. if (this.value !== values[0]) { this.diff = Math.abs(this.value - values[0]); this.increased = this.value < values[0]; this.decreased = this.value > values[0]; this.value = values[0]; callback(); } }; }
window.requestAnimationFrame(update);
</script>function Meter(size, callback) { this.size = size; this.value = 0; this.diff = 0; this.increased = false; this.decreased = false; var values = [];
this.setValue = function (updatedValue) { // Add and shift. values.push(updatedValue); if (values.length > this.size) { values.shift(); }
// Exit early if we don't have a long-term match. for (var i = 0; i < values.length - 1; i++) { if (values[i] !== values[i + 1]) return; }
// We got here, so we've got a matching value collection. Set variables and execute callback. if (this.value !== values[0]) { this.diff = Math.abs(this.value - values[0]); this.increased = this.value < values[0]; this.decreased = this.value > values[0]; this.value = values[0]; callback(); } }; }ตัวจัดการสถานะ (The State Handler)
หัวข้อที่มีชื่อว่า “ตัวจัดการสถานะ (The State Handler)”ตัวจัดการสถานะคือสแต็กเอฟเฟกต์ที่ใช้จัดการเอฟเฟกต์ซึ่งมีลำดับความสำคัญเหนือเอฟเฟกต์อื่นทั้งหมดโดยเฉพาะ หากคุณต้องการให้แอนิเมชันหลักขนาดใหญ่หนึ่งชุดทำงานจนจบโดยไม่ถูกขัดจังหวะ ให้ใส่มันไว้ในตัวจัดการสถานะ
| เมธอด | คำอธิบาย |
|---|---|
| StateHandler() | คอนสตรักเตอร์ไม่ต้องการอาร์กิวเมนต์ใด ๆ |
| StateHandler.push(new State()) | คุณสามารถเพิ่มสถานะใหม่ลงในสแต็กสถานะได้ด้วย push และการประมวลผลจะเริ่มทันที |
| StateHandler.pop() | นำสถานะปัจจุบันออกจากสแต็กสถานะ และเริ่มประมวลผลสถานะก่อนหน้าในสแต็ก |
ออบเจ็กต์ใด ๆ ที่ถูก push เข้าไปในตัวจัดการสถานะ ต้อง implement Process() ฟังก์ชัน Process เป็นตัวกำหนดอายุการทำงานของเอฟเฟกต์ในตัวจัดการ
ตัวอย่างตัวจัดการสถานะ
หัวข้อที่มีชื่อว่า “ตัวอย่างตัวจัดการสถานะ”ต่อไปนี้แสดงตัวจัดการสถานะแบบพื้นฐาน พร้อมฟังก์ชัน Process ที่ควรทำงานภายในฟังก์ชันเอฟเฟกต์ของคุณ:
var stateHdlr = new StateHandler();
function StateHandler() { var stack = []; var state = null;
// Set current state to the top item in the stack var updateState = function () { if (stack.length > 0) { state = stack[stack.length - 1]; } else { state = null; } };
// Allows dev to add effect to state handler this.Push = function (newState) { stack.push(newState); updateState(); }; // Allows dev to remove effect from handler this.Pop = function () { stack.pop(); updateState(); }; // Call the Process function of the current state (effect) this.Process = function () { if (state != null) { state.Process(); } }; }
function update(){ stateHdlr.Process();}this.start = new Date.now()this.elapsed = 0;this.duration = 1000;
this.Process = function () { // Evaluate time since effect start this.elapsed = new Date.now() - this.start; // If the effect has reached its lifespan, remove it from the state handler if (this.elapsed > this.duration) { stateMgr.Pop(); } // If the effect is still running, call the effect draw function this.Draw();};ตัวจัดการเอฟเฟกต์ (The Effect Handler)
หัวข้อที่มีชื่อว่า “ตัวจัดการเอฟเฟกต์ (The Effect Handler)”ตัวจัดการเอฟเฟกต์ เหมาะอย่างยิ่งสำหรับการจัดเก็บและเรนเดอร์เอฟเฟกต์ขนาดเล็กและเบากว่ารวมกันทั้งหมด เอฟเฟกต์แต่ละตัวในตัวจัดการจะถูกประเมินในทุกการเรียก update และจะถูกนำออกเมื่อหมดอายุการทำงาน
ตัวจัดการเอฟเฟกต์เป็นเพียงอาร์เรย์สำหรับเก็บเอฟเฟกต์ แค่นั้นเอง
// Declare effects arraylet effects = [];
// (Not shown) Evaluate Meter, callback function pushes effect into effects arrayeffects.push(new SpecialEffect());
// Iterate through the array, animating a frame for each effectfor (let i = 0; i < effects.length; i++) { effects[i].draw(); // Remove effect if the lifetime has ended if (effects[i].lifetime <= 0) { effects.splice(i, 1); }}คำเตือนเรื่องเอฟเฟกต์ VS. สถานะ
หัวข้อที่มีชื่อว่า “คำเตือนเรื่องเอฟเฟกต์ VS. สถานะ”ตัวจัดการสถานะมีไว้สำหรับเอฟเฟกต์ที่มีลำดับความสำคัญโดยเฉพาะ ซึ่งหมายความว่าเราต้องให้ความสำคัญกับมันระหว่างการทำงาน ในฟังก์ชัน update ของคุณ ให้ประมวลผลตัวจัดการเอฟเฟกต์ ก่อน แล้วจึง ประมวลผลตัวจัดการสถานะ วิธีนี้จะทำให้เอฟเฟกต์ของสถานะถูกวาดทับอยู่บนรายการของตัวจัดการเอฟเฟกต์
แบบนี้:
function update(){ // Evaluate effects handler for (let i = 0; i < effects.length; i++) { effects[i].draw(); if (effects[i].lifetime <= 0) { effects.splice(i, 1); } }
// THEN evaluate state handler stateMgr.Process();}คู่มือการดักจับข้อมูล USB
หัวข้อที่มีชื่อว่า “คู่มือการดักจับข้อมูล USB”การบันทึกข้อมูล USB เป็นกระบวนการที่ไม่ซับซ้อน แต่ไดรเวอร์ที่โปรแกรมเหล่านี้ใช้เป็นที่รู้กันว่าอาจขัดแย้งกับบางระบบ บางครั้งถึงขั้นปิดการทำงานของพอร์ต USB จนกว่าจะถอนการติดตั้งซอฟต์แวร์ วิธีแก้ไขทั่วไปคือปิด ‘Secure Boot’ ในการตั้งค่า BIOS/UEFI ของคุณ ก่อนดำเนินการต่อ ขอแนะนำอย่างยิ่งให้เตรียมระบบกู้คืน (system restore) ไว้ในแฟลชไดรฟ์ หรือมีวิธีเข้าถึงคอมพิวเตอร์ของคุณจากระยะไกลที่ไม่ต้องอาศัยการป้อนข้อมูลจากผู้ใช้ตอนบูต สิ่งนี้สำคัญในกรณีที่การปิด Secure Boot ไม่ช่วยแก้ปัญหา และคุณไม่สามารถเข้าถึงระบบเพื่อถอนการติดตั้งโปรแกรมได้ ในกรณีเช่นนั้น อาจจำเป็นต้องทำ Windows refresh เพื่อลบโปรแกรมที่ติดตั้งไว้ทั้งหมดโดยยังคงเก็บไฟล์ส่วนตัวของคุณไว้ คุณดำเนินการนี้โดยยอมรับความเสี่ยงเอง หากคุณไม่สะดวกใจที่จะลอง ให้ส่งคำขออุปกรณ์ของคุณที่นี่ ห้ามใช้แล็ปท็อปสำหรับกระบวนการนี้
เมื่อติดตั้งแล้ว กระบวนการนั้นง่ายและจะดักจับข้อมูลทั้งหมดที่ผ่านอุปกรณ์ USB ของคุณ อย่าพิมพ์ข้อมูลที่ละเอียดอ่อนใด ๆ ระหว่างการดักจับหากคุณวางแผนจะแชร์ข้อมูล เนื่องจากการกดแป้นพิมพ์จะถูกบันทึกไว้ด้วย โปรแกรมของบุคคลที่สามสองตัวที่ใช้ได้คือ Usblyzer(ทดลองใช้ฟรี) และ Wireshark (ฟรี) ทั้งสองใช้งานได้ แต่หากคุณเลือก Wireshark ให้แน่ใจว่าได้เลือก USBPcap ไว้แล้ว
ดูหน้าถัดไปของเรา Callbacks สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับการสร้าง callback ของมิเตอร์และฟังก์ชันเอฟเฟกต์