Skip to content

Snippets

Ovaj odeljak sadrži tri korisna isečka koda za LightScripts: Meter, State Handler i Effect Handler.

Kao nastavak prethodnog odeljka, klasa Meter je dizajnirana za praćenje značajnih promena u nestabilnim podacima merača. Funkcioniše kao kočnica za kod — čak i u složenim oblastima osigurava stabilnost. Svaki merač čuva prilagodljivi niz vrednosti prikupljenih na svakom prolazu funkcije update. Kada su sve vrednosti u nizu jednake (tj. podaci su “stabilni”), merač ažurira svoju vrednost i aktivira priloženu callback funkciju za pokretanje efekta.

MetodaOpis
Meter(size, callback)Konstruktor prihvata size i callback.\n\n\n\nsize – broj puta koliko identična vrednost mora biti prisutna da bi se vrednost merača smatrala “dovoljno stabilnom” za obradu. Veće vrednosti rezultiraju većom preciznošću, manje vrednosti manjom latencijom.\n\n\ncallback – funkcija koja se poziva kada je vrednost merača stabilna i promenila se.
Meter.setValue(value)setValue(value) treba pozivati svaki frejm ili svaki put kada su dostupni novi sirovi podaci za ovaj merač.

Proces preuzimanja podataka sa ekrana generalno treba da prati ovu strukturu:

  1. Vrednost engine.vision.meter se ažurira na osnovu novih podataka sa ekrana.
  2. Unutar funkcije update, poziva se Meter.setValue(engine.vision.meter) za beleženje nove vrednosti.
  3. Meter proverava svoj interni niz da li su sve vrednosti identične. Ako jesu, ažurira sopstveno stanje i izvršava dodeljenu callback funkciju.
  4. Callback funkcija zatim evaluira specifične uslove na osnovu promenljivih Meter-a i izvršava kod kada su ti uslovi ispunjeni.

VAŽNA NAPOMENA:

Ne preskačite callbacks. Budući da funkcija update kontinuirano radi, mora ostati što efikasnija. Njena primarna uloga treba da bude ažuriranje vrednosti Meter-a. Treba izbegavati ulančavanje uslova unutar update za proveru merača i aktiviranje efekata, jer to dovodi do nepotrebnih provera u svakom ciklusu. Umesto toga, definirajte efekte u zasebnim funkcijama i prosleđujte ih kao callbacks u Meter.

Kada je stabilan, merač pruža callback funkciji neke vrednosti:

PromenljivaOpis
Meter.valueTrenutna vrednost merača.
Meter.increasedBoolean koji označava da li je vrednost porasla u ovom ažuriranju
Meter.decreasedBoolean koji označava da li je vrednost opala u ovom ažuriranju
Meter.diffApsolutna vrednost promene koju je merač doživeo u ovom ažuriranju.

Evo jednostavnog podešavanja sa jednim meračem uključujući kod klase 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();
}
};
}

Handler stanja je stack efekata koji posebno upravlja efektima koji imaju prioritet nad svima ostalima. Kada treba da se pokrene velika dominantna animacija bez prekida do kraja, ubacuje se u handler stanja.

MetodaOpis
StateHandler()Konstruktor ne zahteva argumente.
StateHandler.push(new State())Push omogućava guranje novog stanja na stack stanja, a obrada počinje odmah.
StateHandler.pop()Uklanja trenutno stanje sa stack-a stanja i počinje obradu prethodnog stanja na stack-u.

Svaki objekat gurnut u handler stanja mora implementirati Process(). Funkcija Process određuje životni vek efekta u handleru.

Sledeće prikazuje osnovni handler stanja kao i Process funkciju koja bi trebala da se izvršava unutar funkcija efekata:

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();
};

Handler efekata je odličan za zajedničko skladištenje i renderovanje manjih, lakših efekata. Svaki efekat u handleru se evaluira pri svakom pozivu update-a i uklanja kada dostigne kraj svog životnog veka.

Handler efekata je jednostavno niz za čuvanje efekata. To je sve.

// 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 je posebno namenjen efektima sa prioritetom, što znači da mu se mora dati prioritet pri izvršavanju. U funkciji update, najpre obradite handler efekata, a zatim handler stanja. Na taj način efekat stanja se crta preko elemenata handlera efekata.

Ovako:

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();
}

Snimanje USB podataka je jednostavan proces, ali drajveri koje ovi programi koriste poznati su po izazivanju konflikata na određenim sistemima i ponekad onemogućavaju USB portove sve dok se softver ne ukloni. Uobičajeno rešenje je onemogućavanje “Secure Boot” u BIOS/UEFI podešavanjima. Pre nastavka, snažno se preporučuje imati USB sa opcijom obnavljanja sistema ili mogućnost daljinskog pristupa i upravljanja računarom koja ne zahteva korisnički unos pri pokretanju. Ovo je važno u slučaju da onemogućavanje Secure Boot-a ne reši problem i nema mogućnosti pristupa sistemu za deinstalaciju programa. U takvim slučajevima može biti potrebno osvežavanje Windows-a za uklanjanje svih instaliranih programa uz zadržavanje ličnih datoteka. Ovo radite na sopstvenu odgovornost. Ako niste sigurni da želite da to isprobate, možete zatražiti dodavanje svog uređaja ovde. Ne koristite laptop sistem za ovaj proces.

Nakon instalacije, proces je jednostavan i snima sve podatke koji prolaze kroz USB uređaje. Tokom snimanja ne unosite osetljive informacije ako planirate da delite podatke, jer su pritisci tastera uključeni u snimanje. Dva programa trećih strana koja se mogu koristiti su Usblyzer (besplatna probna verzija) i Wireshark (besplatno). Oba rade, ali sa Wireshark-om obavezno izaberite USBPcap.

Za više detalja o izgradnji Meter callback-ova i funkcija efekata, pogledajte naše sledeće stranice o Callbacks-ima.