Hoppa till innehåll

Kodavsnitt

Det här avsnittet innehåller tre användbara kodavsnitt för dina LightScripts: mätare, tillståndshanterare och effekthanterare.

Som en fortsättning från föregående avsnitt är Meter-klassen utformad för att hjälpa till att spåra meningsfulla förändringar i instabila mätardata. Tänk på den som ett bromspedalens bromssystem för din kod – den ger stabilitet även i komplexa zoner. Varje mätare håller en anpassningsbar matris med värden som samlats in under varje körning av din update-funktion. När alla värden i den matrisen är desamma (dvs. data är “stabila”) uppdaterar mätaren sitt värde och utlöser en kopplad återanropsfunktion för att aktivera en effekt.

MetodBeskrivning
Meter(size, callback)Konstruktorn accepterar både en size och ett callback.\n\n\n\nsize – antalet gånger ett identiskt värde ska vara tillgängligt för att mätarvärdet ska anses vara tillräckligt “stabilt” för att bearbetas. Högre värden resulterar i mer noggrannhet, lägre värden resulterar i mindre latens.\n\n\ncallback – en funktion som anropas när mätarvärdet är stabilt och har förändrats.
Meter.setValue(value)Du bör anropa setValue(value) varje bildruta, eller när som helst ny rådata för den här mätaren är tillgänglig.

Processen för att samla in skärmdata bör generellt följa den här strukturen:

  1. Värdet engine.vision.meter uppdateras baserat på nya data från skärmen.
  2. Inuti update-funktionen anropas Meter.setValue(engine.vision.meter) för att registrera det nya värdet.
  3. Meter kontrollerar sin interna matris för att se om alla värden är identiska. Om så är fallet uppdaterar den sitt eget tillstånd och kör sin tilldelade återanropsfunktion.
  4. Återanropsfunktionen utvärderar sedan specifika villkor med hjälp av Meter:ns variabler och kör sin kod om dessa villkor uppfylls.

VIKTIGT:

Hoppa inte över att använda callbacks. Eftersom update-funktionen körs kontinuerligt måste den förbli så effektiv som möjligt. Dess primära roll bör vara att uppdatera Meter-värden. Undvik att kedja villkor i update för att kontrollera mätare och utlösa effekter, eftersom detta leder till onödiga kontroller vid varje cykel. Definiera istället dina effekter i separata funktioner och skicka in dem i din Meter som callbacks.

När den är stabil ger Meter ett par värden till sin återanropsfunktion:

VariablerBeskrivning
Meter.valueMätarens aktuella värde.
Meter.increasedEtt booleskt värde som indikerar om vårt värde har ökat vid den här uppdateringen
Meter.decreasedEtt booleskt värde som indikerar om vårt värde har minskat vid den här uppdateringen
Meter.diffDet absoluta värdet av förändringen som mätaren har genomgått vid den här uppdateringen.

Här är en grundläggande enkelmätarkonfiguration, inklusive Meter-klasskoden:

<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");
// Initiera mätare
var healthMeter = new Meter(5, healthEffect);
function update(){
// Uppdatera Meter-värden
healthMeter.setValue(engine.vision.health);
window.requestAnimationFrame(update);
}
function healthEffect(){
if(healthMeter.increased){
// Utlös effekt
} else if (healthMeter.value == 0){
// Utlös effekt
} else if (healthMeter.diff > .3){
// Utlös effekt
}
}
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) {
// Lägg till och skifta.
values.push(updatedValue);
if (values.length > this.size) {
values.shift();
}
// Avsluta tidigt om vi inte har en långsiktig matchning.
for (var i = 0; i < values.length - 1; i++) {
if (values[i] !== values[i + 1]) return;
}
// Vi kom hit, så vi har en matchande värdesamling. Ange variabler och kör 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");
// Initiera mätare
var healthMeter = new Meter(5, healthEffect);
function update(){
// Uppdatera Meter-värden
healthMeter.setValue(engine.vision.health);
window.requestAnimationFrame(update);
}
function healthEffect(){
if(healthMeter.increased){
// Utlös effekt
} else if (healthMeter.value == 0){
// Utlös effekt
} else if (healthMeter.diff > .3){
// Utlös effekt
}
}
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) {
// Lägg till och skifta.
values.push(updatedValue);
if (values.length > this.size) {
values.shift();
}
// Avsluta tidigt om vi inte har en långsiktig matchning.
for (var i = 0; i < values.length - 1; i++) {
if (values[i] !== values[i + 1]) return;
}
// Vi kom hit, så vi har en matchande värdesamling. Ange variabler och kör 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) {
// Lägg till och skifta.
values.push(updatedValue);
if (values.length > this.size) {
values.shift();
}
// Avsluta tidigt om vi inte har en långsiktig matchning.
for (var i = 0; i < values.length - 1; i++) {
if (values[i] !== values[i + 1]) return;
}
// Vi kom hit, så vi har en matchande värdesamling. Ange variabler och kör 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();
}
};
}

Tillståndshanteraren är en effektstack som specifikt hanterar effekter som har prioritet framför alla andra. Om du vill att en stor dominant animation ska köra tills den är klar utan avbrott, lägg in den i tillståndshanteraren.

MetodBeskrivning
StateHandler()Konstruktorn kräver inga argument.
StateHandler.push(new State())Du kan skjuta in ett nytt tillstånd på tillståndssteget med push, och bearbetning börjar omedelbart.
StateHandler.pop()Tar bort det aktuella tillståndet från tillståndssteget och börjar bearbeta det föregående tillståndet.

Alla objekt som skjuts in i tillståndshanteraren måste implementera Process(). Process-funktionen bestämmer livslängden för en effekt i hanteraren.

Följande visar en grundläggande tillståndshanterare, plus Process-funktionen som ska köras inuti dina effektfunktioner:

var stateHdlr = new StateHandler();
function StateHandler() {
var stack = [];
var state = null;
// Sätt aktuellt tillstånd till det översta elementet i steget
var updateState = function () {
if (stack.length > 0) {
state = stack[stack.length - 1];
} else {
state = null;
}
};
// Låter utvecklaren lägga till effekt i tillståndshanteraren
this.Push = function (newState) {
stack.push(newState);
updateState();
};
// Låter utvecklaren ta bort effekt från hanteraren
this.Pop = function () {
stack.pop();
updateState();
};
// Anropa Process-funktionen för det aktuella tillståndet (effekten)
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 () {
// Utvärdera tid sedan effekten startade
this.elapsed = new Date.now() - this.start;
// Om effekten har nått sin livslängd, ta bort den från tillståndshanteraren
if (this.elapsed > this.duration) {
stateMgr.Pop();
}
// Om effekten fortfarande körs, anropa effektens draw-funktion
this.Draw();
};

Effekthanterare är utmärkta för att lagra och rendera mindre, lättare effekter tillsammans. Varje effekt i hanteraren utvärderas vid varje update-anrop och de tas bort när de når slutet av sin livslängd.

Effekthanteraren är bara en matris för att lagra effekter. Det är allt.

// Deklarera effektmatris
let effects = [];
// (Visas inte) Utvärdera Meter, återanropsfunktion lägger in effekt i effektmatrisen
effects.push(new SpecialEffect());
// Iterera genom matrisen och animera en bildruta för varje effekt
for (let i = 0; i < effects.length; i++) {
effects[i].draw();
// Ta bort effekt om livslängden har avslutats
if (effects[i].lifetime <= 0) {
effects.splice(i, 1);
}
}

Tillståndshanteraren är specifikt för prioritetseffekter, vilket innebär att vi måste ge den prioritet under körning. I din update-funktion, bearbeta effekthanteraren SEDAN tillståndshanteraren. Det ritar tillståndseffekten ovanpå effekthanterarens element.

Såhär:

function update(){
// Utvärdera effekthanterare
for (let i = 0; i < effects.length; i++) {
effects[i].draw();
if (effects[i].lifetime <= 0) {
effects.splice(i, 1);
}
}
// SEDAN utvärdera tillståndshanterare
stateMgr.Process();
}

Att spara USB-data är en enkel process, men drivrutinerna som används av dessa program är kända för att konflikta med vissa system och ibland inaktivera USB-portar tills programvaran tas bort. Den vanliga lösningen är att inaktivera “Secure Boot” i dina BIOS/UEFI-inställningar. Innan du fortsätter rekommenderas starkt att ha en systemåterställning tillgänglig på ett USB-minne eller ett sätt att fjärransluta till datorn som inte förlitar sig på användarinmatning vid uppstart. Det är viktigt om inaktivering av Secure Boot inte löser problemet och du inte kan komma åt systemet för att avinstallera programmet. I sådana fall kan en Windows-uppdatering vara nödvändig för att ta bort alla installerade program men bevara dina personliga filer. Du gör det här på egen risk. Om du inte känner dig bekväm med att försöka, begär din enhet här. Använd inte ett bärbardatorsystem för den här processen.

När det är installerat är processen enkel och fångar alla data som passerar genom dina USB-enheter. Skriv inte in någon känslig information under inspelning om du planerar att dela data, eftersom tangenttryckningar ingår i inspelningen. Två tredjepartsprogram som kan användas är Usblyzer (gratis provperiod) och Wireshark (gratis). Båda fungerar, men om du väljer Wireshark, se till att USBPcap är valt.

Kolla in vår nästa sida, Callbacks, för mer detaljer om att konstruera mätarcallbacks och effektfunktioner.