Snippets
Ta sekcja zawiera trzy przydatne fragmenty kodu dla twoich LightScripts: mierniki, procedury obsługi stanu i procedury obsługi efektów.
Klasa Meter
Dział zatytułowany „Klasa Meter”Kontynuując poprzednią sekcję, klasa Meter jest zaprojektowana do śledzenia znaczących zmian w niestabilnych danych miernika. Traktuj ją jak pedał hamulca dla twojego kodu — zapewnia stabilność nawet w złożonych strefach. Każdy miernik zawiera konfigurowalną tablicę wartości zbieranych podczas każdego wykonania funkcji aktualizacji. Gdy wszystkie wartości w tej tablicy są takie same (tj. dane są “stabilne”), miernik aktualizuje swoją wartość i aktywuje dołączoną funkcję callback, aby uruchomić efekt.
| Metoda | Opis |
|---|---|
| Meter(size, callback) | Konstruktor akceptuje zarówno size jak i callback.\n\n\n\nsize — liczba razy, kiedy identyczna wartość musi być obecna, aby wartość miernika była uznana za wystarczająco “stabilną” do przetworzenia. Wyższe wartości dają większą dokładność, niższe wartości dają mniejsze opóźnienie.\n\n\ncallback — funkcja wywoływana, gdy wartość miernika jest stabilna i zmieniła się. |
| Meter.setValue(value) | Musisz wywoływać setValue(value) w każdej klatce, lub za każdym razem, gdy są dostępne nowe surowe dane dla tego miernika. |
Proces zbierania danych ekranu powinien generalnie mieć tę strukturę:
- Wartość engine.vision.meter jest aktualizowana na podstawie nowych danych z ekranu.
- Wewnątrz funkcji aktualizacji wywoływane jest Meter.setValue(engine.vision.meter), aby przechwycić nową wartość.
- Meter sprawdza swoją wewnętrzną tablicę, aby zobaczyć, czy wszystkie wartości są identyczne. Jeśli tak, aktualizuje swój własny stan i wykonuje przypisaną funkcję callback.
- Funkcja callback następnie ocenia konkretne warunki przy użyciu zmiennych Meter i wykonuje swój kod, jeśli te warunki są spełnione.
WAŻNA UWAGA:
Nie pomijaj używania callbacków. Ponieważ funkcja aktualizacji działa ciągle, musi pozostawać jak najbardziej wydajna. Jej główną rolą powinno być aktualizowanie wartości Meter. Unikaj łączenia warunków wewnątrz aktualizacji, aby sprawdzać mierniki i aktywować efekty, ponieważ prowadzi to do niepotrzebnych sprawdzeń przy każdym cyklu. Zamiast tego definiuj swoje efekty w oddzielnych funkcjach i przekazuj je do swojego Meter jako callbacki.
Zmienne Meter
Dział zatytułowany „Zmienne Meter”Gdy jest stabilna, Meter udostępnia kilka wartości swojej funkcji callback:
| Zmienne | Opis |
|---|---|
| Meter.value | Bieżąca wartość miernika. |
| Meter.increased | Wartość boolean wskazująca, czy nasza wartość wzrosła w tej aktualizacji |
| Meter.decreased | Wartość boolean wskazująca, czy nasza wartość spadła w tej aktualizacji |
| Meter.diff | Wartość bezwzględna zmiany, którą miernik przeszedł w tej aktualizacji. |
Przykład Meter
Dział zatytułowany „Przykład Meter”Oto prosta konfiguracja z jednym miernikiem, zawierająca kod klasy 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(); } }; }Procedura obsługi stanu
Dział zatytułowany „Procedura obsługi stanu”Procedura obsługi stanu to stos efektów przeznaczony specjalnie do obsługi efektów, które mają priorytet nad wszystkimi innymi. Jeśli chcesz, aby jedna duża dominująca animacja działała do końca bez przerwania, umieść ją w procedurze obsługi stanu.
| Metoda | Opis |
|---|---|
| StateHandler() | Konstruktor nie wymaga argumentów. |
| StateHandler.push(new State()) | Możesz umieścić nowy stan na stosie stanu za pomocą push, a przetwarzanie rozpocznie się natychmiast. |
| StateHandler.pop() | Usuwa bieżący stan ze stosu stanu i zaczyna przetwarzać poprzedni stan na stosie. |
Każdy obiekt umieszczony w procedurze obsługi stanu musi implementować Process(). Funkcja Process określa czas życia efektu w procedurze obsługi.
Przykład procedury obsługi stanu
Dział zatytułowany „Przykład procedury obsługi stanu”Poniżej przedstawiono prostą procedurę obsługi stanu oraz funkcję Process, która musi być wykonywana wewnątrz twoich funkcji efektów:
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();};Procedura obsługi efektów
Dział zatytułowany „Procedura obsługi efektów”Procedury obsługi efektów są doskonałe do przechowywania i renderowania mniejszych, lżejszych efektów razem. Każdy efekt w procedurze obsługi jest oceniany przy każdym wywołaniu aktualizacji i jest usuwany po osiągnięciu końca swojego czasu życia.
Procedura obsługi efektów to po prostu tablica do przechowywania efektów. To wszystko.
// 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); }}OSTRZEŻENIE: EFEKT VS. STAN
Dział zatytułowany „OSTRZEŻENIE: EFEKT VS. STAN”Menedżer stanu jest przeznaczony dla efektów priorytetowych, co oznacza, że musimy mu nadać priorytet podczas wykonywania. W funkcji aktualizacji przetwarzaj procedurę obsługi efektów A NASTĘPNIE procedurę obsługi stanu. Rysuje to efekt stanu na wierzchu elementów procedury obsługi efektów.
Tak:
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();}Przewodnik przechwytywania danych USB
Dział zatytułowany „Przewodnik przechwytywania danych USB”Przechowywanie danych USB to prosty proces, ale sterowniki używane przez te programy są znane z powodowania konfliktów z niektórymi systemami, czasami wyłączając porty USB do momentu odinstalowania oprogramowania. Typowym rozwiązaniem jest wyłączenie “Bezpiecznego rozruchu” w ustawieniach BIOS/UEFI. Przed kontynuowaniem zdecydowanie zaleca się posiadanie przywracania systemu dostępnego na pendrive lub sposobu zdalnego dostępu do komputera, który nie polega na danych wejściowych użytkownika podczas uruchamiania. Jest to ważne w przypadku, gdy wyłączenie bezpiecznego rozruchu nie rozwiąże problemu i nie możesz uzyskać dostępu do systemu w celu odinstalowania programu. W takich przypadkach może być konieczne odświeżenie systemu Windows, aby usunąć wszystkie zainstalowane programy przy zachowaniu plików osobistych. Robisz to na własne ryzyko. Jeśli nie czujesz się z tym komfortowo, poproś o swoje urządzenie tutaj. Nie używaj laptopa do tego procesu.
Po zainstalowaniu proces jest prosty i przechwytuje wszystkie dane przechodzące przez twoje urządzenia USB. Nie wpisuj poufnych informacji podczas przechwytywania, jeśli planujesz udostępniać dane, ponieważ naciśnięcia klawiszy są rejestrowane w nagraniu. Dwa programy firm trzecich, które można użyć, to Usblyzer (bezpłatna wersja próbna) i Wireshark (bezpłatny). Oba działają, ale jeśli wybierzesz Wireshark, upewnij się, że USBPcap jest zaznaczony.
Sprawdź naszą następną stronę, Callbacki, aby uzyskać więcej szczegółów na temat składania callbacków mierników i funkcji efektów.