Bỏ qua để đến nội dung

Snippets

Phần này chứa ba đoạn code hữu ích cho LightScripts: Meter, State HandlerEffect Handler.

Là phần tiếp nối từ phần trước, lớp Meter được thiết kế để theo dõi những thay đổi quan trọng trong dữ liệu meter không ổn định. Nó hoạt động như một bộ hãm phanh cho code — ngay cả trong các vùng phức tạp, nó đảm bảo tính ổn định. Mỗi meter lưu trữ một mảng giá trị có thể điều chỉnh được thu thập ở mỗi lượt của hàm update. Khi tất cả các giá trị trong mảng bằng nhau (tức là dữ liệu “ổn định”), meter cập nhật giá trị của nó và kích hoạt hàm callback đính kèm để chạy hiệu ứng.

Phương thứcMô tả
Meter(size, callback)Constructor nhận sizecallback.\n\n\n\nsize – số lần một giá trị giống hệt nhau phải xuất hiện để giá trị meter được coi là “đủ ổn định” để xử lý. Giá trị lớn hơn dẫn đến độ chính xác cao hơn, giá trị nhỏ hơn dẫn đến độ trễ thấp hơn.\n\n\ncallback – hàm được gọi khi giá trị meter ổn định và đã thay đổi.
Meter.setValue(value)setValue(value) nên được gọi mỗi khung hoặc mỗi khi có dữ liệu thô mới cho meter này.

Quá trình lấy dữ liệu từ màn hình thường phải tuân theo cấu trúc này:

  1. Giá trị engine.vision.meter được cập nhật dựa trên dữ liệu màn hình mới.
  2. Bên trong hàm update, Meter.setValue(engine.vision.meter) được gọi để ghi nhận giá trị mới.
  3. Meter kiểm tra mảng nội bộ của nó xem tất cả các giá trị có giống hệt nhau không. Nếu có, nó cập nhật trạng thái của chính nó và thực thi hàm callback được gán.
  4. Hàm callback sau đó đánh giá các điều kiện cụ thể dựa trên các biến Meter và thực thi code khi các điều kiện đó được đáp ứng.

LƯU Ý QUAN TRỌNG:

Đừng bỏ qua callbacks. Vì hàm update chạy liên tục, nó phải duy trì hiệu quả nhất có thể. Vai trò chính của nó nên là cập nhật các giá trị Meter. Nên tránh việc xâu chuỗi các điều kiện bên trong update để kiểm tra meter và kích hoạt hiệu ứng, vì điều đó dẫn đến các kiểm tra không cần thiết trong mỗi chu kỳ. Thay vào đó, hãy định nghĩa các hiệu ứng trong các hàm riêng biệt và truyền chúng dưới dạng callbacks vào Meter.

Khi ổn định, meter cung cấp cho hàm callback một số giá trị:

BiếnMô tả
Meter.valueGiá trị hiện tại của meter.
Meter.increasedBoolean cho biết giá trị có tăng lên trong lần cập nhật này không
Meter.decreasedBoolean cho biết giá trị có giảm xuống trong lần cập nhật này không
Meter.diffGiá trị tuyệt đối của sự thay đổi mà meter đã trải qua trong lần cập nhật này.

Đây là cài đặt đơn giản với một meter bao gồm code lớp 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");
// Meter initialisieren
var healthMeter = new Meter(5, healthEffect);
function update(){
// Meter-Werte aktualisieren
healthMeter.setValue(engine.vision.health);
window.requestAnimationFrame(update);
}
function healthEffect(){
if(healthMeter.increased){
// Effekt auslösen
} else if (healthMeter.value == 0){
// Effekt auslösen
} else if (healthMeter.diff > .3){
// Effekt auslösen
}
}
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) {
// Hinzufügen und verschieben.
values.push(updatedValue);
if (values.length > this.size) {
values.shift();
}
// Frühzeitig beenden, wenn keine langfristige Übereinstimmung vorliegt.
for (var i = 0; i < values.length - 1; i++) {
if (values[i] !== values[i + 1]) return;
}
// Hier angekommen, liegt eine übereinstimmende Wertsammlung vor. Variablen setzen und Callback ausführen.
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");
// Meter initialisieren
var healthMeter = new Meter(5, healthEffect);
function update(){
// Meter-Werte aktualisieren
healthMeter.setValue(engine.vision.health);
window.requestAnimationFrame(update);
}
function healthEffect(){
if(healthMeter.increased){
// Effekt auslösen
} else if (healthMeter.value == 0){
// Effekt auslösen
} else if (healthMeter.diff > .3){
// Effekt auslösen
}
}
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) {
// Hinzufügen und verschieben.
values.push(updatedValue);
if (values.length > this.size) {
values.shift();
}
// Frühzeitig beenden, wenn keine langfristige Übereinstimmung vorliegt.
for (var i = 0; i < values.length - 1; i++) {
if (values[i] !== values[i + 1]) return;
}
// Hier angekommen, liegt eine übereinstimmende Wertsammlung vor. Variablen setzen und Callback ausführen.
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) {
// Hinzufügen und verschieben.
values.push(updatedValue);
if (values.length > this.size) {
values.shift();
}
// Frühzeitig beenden, wenn keine langfristige Übereinstimmung vorliegt.
for (var i = 0; i < values.length - 1; i++) {
if (values[i] !== values[i + 1]) return;
}
// Hier angekommen, liegt eine übereinstimmende Wertsammlung vor. Variablen setzen und Callback ausführen.
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();
}
};
}

Trình xử lý trạng thái là một stack các hiệu ứng đặc biệt quản lý các hiệu ứng có độ ưu tiên cao hơn tất cả các hiệu ứng khác. Khi cần chạy một animation lớn chiếm ưu thế mà không bị gián đoạn đến cuối, nó được đẩy vào trình xử lý trạng thái.

Phương thứcMô tả
StateHandler()Constructor không yêu cầu đối số.
StateHandler.push(new State())Push cho phép đẩy trạng thái mới vào stack trạng thái, và quá trình xử lý bắt đầu ngay lập tức.
StateHandler.pop()Xóa trạng thái hiện tại khỏi stack trạng thái và bắt đầu xử lý trạng thái trước đó trên stack.

Mỗi đối tượng được đẩy vào trình xử lý trạng thái phải triển khai Process(). Hàm Process xác định vòng đời của hiệu ứng trong handler.

Đây là trình xử lý trạng thái cơ bản cùng với hàm Process nên thực thi bên trong các hàm hiệu ứng:

var stateHdlr = new StateHandler();
function StateHandler() {
var stack = [];
var state = null;
// Aktuellen Zustand auf das oberste Element im Stapel setzen
var updateState = function () {
if (stack.length > 0) {
state = stack[stack.length - 1];
} else {
state = null;
}
};
// Ermöglicht dem Entwickler, einen Effekt zum State-Handler hinzuzufügen
this.Push = function (newState) {
stack.push(newState);
updateState();
};
// Ermöglicht dem Entwickler, einen Effekt aus dem Handler zu entfernen
this.Pop = function () {
stack.pop();
updateState();
};
// Process-Funktion des aktuellen Zustands (Effekts) aufrufen
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 () {
// Zeit seit Effektstart auswerten
this.elapsed = new Date.now() - this.start;
// Wenn der Effekt seine Lebensdauer erreicht hat, aus dem State-Handler entfernen
if (this.elapsed > this.duration) {
stateMgr.Pop();
}
// Wenn der Effekt noch läuft, die Effekt-Zeichenfunktion aufrufen
this.Draw();
};

Trình xử lý hiệu ứng rất tuyệt vời để lưu trữ và render các hiệu ứng nhỏ hơn, nhẹ hơn cùng nhau. Mỗi hiệu ứng trong handler được đánh giá ở mỗi lần gọi update và bị xóa khi đạt đến cuối vòng đời của nó.

Trình xử lý hiệu ứng chỉ đơn giản là một mảng để lưu trữ các hiệu ứng. Chỉ vậy thôi.

// Effekte-Array deklarieren
let effects = [];
// (Nicht gezeigt) Meter auswerten, Callback-Funktion schiebt Effekt in das Effekte-Array
effects.push(new SpecialEffect());
// Durch das Array iterieren und für jeden Effekt einen Frame animieren
for (let i = 0; i < effects.length; i++) {
effects[i].draw();
// Effekt entfernen, wenn die Lebensdauer abgelaufen ist
if (effects[i].lifetime <= 0) {
effects.splice(i, 1);
}
}

State Manager được dành riêng cho các hiệu ứng có độ ưu tiên, có nghĩa là nó phải được ưu tiên khi thực thi. Trong hàm update, hãy xử lý trình xử lý hiệu ứng trước, sau đó xử lý trình xử lý trạng thái. Theo cách này, hiệu ứng trạng thái được vẽ trên các phần tử của trình xử lý hiệu ứng.

Như thế này:

function update(){
// Effect-Handler auswerten
for (let i = 0; i < effects.length; i++) {
effects[i].draw();
if (effects[i].lifetime <= 0) {
effects.splice(i, 1);
}
}
// DANN State-Handler auswerten
stateMgr.Process();
}

Chụp dữ liệu USB là một quá trình đơn giản, nhưng các driver mà các chương trình này sử dụng được biết là gây ra xung đột trên một số hệ thống và đôi khi vô hiệu hóa các cổng USB cho đến khi phần mềm được gỡ bỏ. Giải pháp thông thường là tắt “Secure Boot” trong cài đặt BIOS/UEFI. Trước khi tiếp tục, rất nên có USB với tùy chọn khôi phục hệ thống hoặc khả năng truy cập và quản lý máy tính từ xa không yêu cầu đầu vào người dùng khi khởi động. Điều này quan trọng trong trường hợp tắt Secure Boot không giải quyết được vấn đề và không có cách nào truy cập hệ thống để gỡ cài đặt phần mềm. Trong những trường hợp như vậy, có thể cần làm mới Windows để xóa tất cả các chương trình đã cài đặt trong khi giữ lại các tệp cá nhân. Thực hiện điều này với rủi ro của riêng bạn. Nếu bạn không chắc muốn thử, bạn có thể yêu cầu thêm thiết bị của mình tại đây. Không sử dụng hệ thống laptop cho quá trình này.

Sau khi cài đặt, quá trình rất đơn giản và ghi lại tất cả dữ liệu đi qua các thiết bị USB. Trong khi chụp, đừng nhập thông tin nhạy cảm nếu bạn định chia sẻ dữ liệu, vì các phím bấm được bao gồm trong bản ghi. Hai chương trình bên thứ ba có thể sử dụng là Usblyzer (bản dùng thử miễn phí) và Wireshark (miễn phí). Cả hai đều hoạt động, nhưng với Wireshark hãy chắc chắn chọn USBPcap.

Để biết thêm chi tiết về việc xây dựng Meter callbacks và các hàm hiệu ứng, hãy xem các trang tiếp theo của chúng tôi về Callbacks.