ข้ามไปยังเนื้อหา

สนิปเพ็ต

ส่วนนี้รวบรวมสนิปเพ็ตโค้ดที่มีประโยชน์สามแบบสำหรับ LightScripts ของคุณ ได้แก่ มิเตอร์ (meter), ตัวจัดการสถานะ (state handler) และ ตัวจัดการเอฟเฟกต์ (effects handler)

ต่อเนื่องจากส่วนก่อนหน้า คลาส Meter ถูกออกแบบมาเพื่อช่วยติดตามการเปลี่ยนแปลงที่มีความหมายในข้อมูลมิเตอร์ที่ไม่เสถียร ให้คิดว่ามันเป็นเหมือนแป้นเบรกสำหรับโค้ดของคุณ ซึ่งช่วยให้เกิดความเสถียรแม้ในโซนที่ซับซ้อน แต่ละมิเตอร์จะเก็บอาร์เรย์ของค่าที่ปรับแต่งได้ ซึ่งรวบรวมระหว่างการทำงานแต่ละรอบของฟังก์ชัน update ของคุณ เมื่อค่าทั้งหมดในอาร์เรย์นั้นเหมือนกัน (กล่าวคือข้อมูล “เสถียร”) มิเตอร์จะอัปเดตค่าของตัวเองและเรียกฟังก์ชัน callback ที่เชื่อมโยงไว้เพื่อเปิดใช้งานเอฟเฟกต์

เมธอดคำอธิบาย
Meter(size, callback)คอนสตรักเตอร์รับทั้ง size และ callback\n\n\n\nsize - จำนวนครั้งที่ค่าเดียวกันต้องปรากฏ เพื่อให้ค่ามิเตอร์ถือว่า ‘เสถียร’ พอที่จะนำไปประมวลผล ค่าที่สูงขึ้นให้ความแม่นยำมากขึ้น ค่าที่ต่ำลงให้ความหน่วงน้อยลง\n\n\ncallback - ฟังก์ชันที่จะถูกเรียกเมื่อค่ามิเตอร์เสถียรและมีการเปลี่ยนแปลง
Meter.setValue(value)คุณควรเรียก setValue(value) ทุกเฟรม หรือทุกครั้งที่มีข้อมูลดิบใหม่สำหรับมิเตอร์นี้

โดยทั่วไป กระบวนการรวบรวมข้อมูลจากหน้าจอควรเป็นไปตามโครงสร้างนี้:

  1. ค่า engine.vision.meter อัปเดตตามข้อมูลใหม่จากหน้าจอ
  2. ภายในฟังก์ชัน update จะมีการเรียก Meter.setValue(engine.vision.meter) เพื่อบันทึกค่าใหม่
  3. Meter ตรวจสอบอาร์เรย์ภายในว่าค่าทั้งหมดเหมือนกันหรือไม่ หากเหมือนกัน จะอัปเดตสถานะของตัวเองและเรียกใช้ฟังก์ชัน callback ที่กำหนดไว้
  4. จากนั้นฟังก์ชัน callback จะประเมินเงื่อนไขเฉพาะโดยใช้ตัวแปรของ Meter และรันโค้ดหากเงื่อนไขเหล่านั้นเป็นจริง

หมายเหตุสำคัญ:

อย่าข้ามการใช้ callback เนื่องจากฟังก์ชัน update ทำงานอย่างต่อเนื่อง จึงต้องมีประสิทธิภาพมากที่สุดเท่าที่จะทำได้ หน้าที่หลักของมันควรเป็นการอัปเดตค่าของ Meter หลีกเลี่ยงการต่อเงื่อนไขหลายชั้นภายใน update เพื่อตรวจสอบมิเตอร์และเรียกเอฟเฟกต์ เพราะจะทำให้เกิดการตรวจสอบที่ไม่จำเป็นในทุกรอบ ให้กำหนดเอฟเฟกต์ของคุณในฟังก์ชันแยกต่างหาก แล้วส่งเข้าไปใน Meter เป็น callback แทน

เมื่อเสถียรแล้ว Meter จะให้ค่าบางอย่างแก่ฟังก์ชัน callback ของมัน:

ตัวแปรคำอธิบาย
Meter.valueค่าปัจจุบันของมิเตอร์
Meter.increasedค่า boolean ที่บอกว่าค่าของเราเพิ่มขึ้นในการอัปเดตครั้งนี้หรือไม่
Meter.decreasedค่า boolean ที่บอกว่าค่าของเราลดลงในการอัปเดตครั้งนี้หรือไม่
Meter.diffค่าสัมบูรณ์ ของการเปลี่ยนแปลงที่มิเตอร์เกิดขึ้นในการอัปเดตครั้งนี้

ต่อไปนี้คือการตั้งค่ามิเตอร์เดี่ยวแบบพื้นฐาน พร้อมโค้ดคลาส 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();
}
};
}

ตัวจัดการสถานะคือสแต็กเอฟเฟกต์ที่ใช้จัดการเอฟเฟกต์ซึ่งมีลำดับความสำคัญเหนือเอฟเฟกต์อื่นทั้งหมดโดยเฉพาะ หากคุณต้องการให้แอนิเมชันหลักขนาดใหญ่หนึ่งชุดทำงานจนจบโดยไม่ถูกขัดจังหวะ ให้ใส่มันไว้ในตัวจัดการสถานะ

เมธอดคำอธิบาย
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();
};

ตัวจัดการเอฟเฟกต์ เหมาะอย่างยิ่งสำหรับการจัดเก็บและเรนเดอร์เอฟเฟกต์ขนาดเล็กและเบากว่ารวมกันทั้งหมด เอฟเฟกต์แต่ละตัวในตัวจัดการจะถูกประเมินในทุกการเรียก update และจะถูกนำออกเมื่อหมดอายุการทำงาน

ตัวจัดการเอฟเฟกต์เป็นเพียงอาร์เรย์สำหรับเก็บเอฟเฟกต์ แค่นั้นเอง

// Declare effects array
let effects = [];
// (Not shown) Evaluate Meter, callback function pushes effect into effects array
effects.push(new SpecialEffect());
// Iterate through the array, animating a frame for each effect
for (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);
}
}

ตัวจัดการสถานะมีไว้สำหรับเอฟเฟกต์ที่มีลำดับความสำคัญโดยเฉพาะ ซึ่งหมายความว่าเราต้องให้ความสำคัญกับมันระหว่างการทำงาน ในฟังก์ชัน 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 จนกว่าจะถอนการติดตั้งซอฟต์แวร์ วิธีแก้ไขทั่วไปคือปิด ‘Secure Boot’ ในการตั้งค่า BIOS/UEFI ของคุณ ก่อนดำเนินการต่อ ขอแนะนำอย่างยิ่งให้เตรียมระบบกู้คืน (system restore) ไว้ในแฟลชไดรฟ์ หรือมีวิธีเข้าถึงคอมพิวเตอร์ของคุณจากระยะไกลที่ไม่ต้องอาศัยการป้อนข้อมูลจากผู้ใช้ตอนบูต สิ่งนี้สำคัญในกรณีที่การปิด Secure Boot ไม่ช่วยแก้ปัญหา และคุณไม่สามารถเข้าถึงระบบเพื่อถอนการติดตั้งโปรแกรมได้ ในกรณีเช่นนั้น อาจจำเป็นต้องทำ Windows refresh เพื่อลบโปรแกรมที่ติดตั้งไว้ทั้งหมดโดยยังคงเก็บไฟล์ส่วนตัวของคุณไว้ คุณดำเนินการนี้โดยยอมรับความเสี่ยงเอง หากคุณไม่สะดวกใจที่จะลอง ให้ส่งคำขออุปกรณ์ของคุณที่นี่ ห้ามใช้แล็ปท็อปสำหรับกระบวนการนี้

เมื่อติดตั้งแล้ว กระบวนการนั้นง่ายและจะดักจับข้อมูลทั้งหมดที่ผ่านอุปกรณ์ USB ของคุณ อย่าพิมพ์ข้อมูลที่ละเอียดอ่อนใด ๆ ระหว่างการดักจับหากคุณวางแผนจะแชร์ข้อมูล เนื่องจากการกดแป้นพิมพ์จะถูกบันทึกไว้ด้วย โปรแกรมของบุคคลที่สามสองตัวที่ใช้ได้คือ Usblyzer(ทดลองใช้ฟรี) และ Wireshark (ฟรี) ทั้งสองใช้งานได้ แต่หากคุณเลือก Wireshark ให้แน่ใจว่าได้เลือก USBPcap ไว้แล้ว

ดูหน้าถัดไปของเรา Callbacks สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับการสร้าง callback ของมิเตอร์และฟังก์ชันเอฟเฟกต์