Gå til indhold

Snippets

Dette afsnit indeholder tre nyttige kodesnippets til LightScripts: Meter, State-handler og Effect-handler.

Som fortsættelse af det foregående afsnit er Meter-klassen designet til at spore meningsfulde ændringer i ustabile målerdata. Den fungerer som et bremsepedal for koden — selv i komplekse scenarier sikrer den stabilitet. Hver måler gemmer et konfigurerbart array af værdier der indsamles ved hvert gennemløb af update-funktionen. Når alle værdier i arrayet er ens (dvs. dataene er “stabile”), opdaterer måleren sin værdi og udløser en tilknyttet callback-funktion for at aktivere en effekt.

MetodeBeskrivelse
Meter(size, callback)Konstruktøren accepterer både en size og en callback.\n\n\n\nsize – antallet af gange en identisk værdi skal forekomme for at målerens værdi anses som “stabil” nok til at blive behandlet. Højere værdier giver mere nøjagtighed, lavere værdier giver mindre forsinkelse.\n\n\ncallback – en funktion der kaldes, når målerens værdi er stabil og har ændret sig.
Meter.setValue(value)setValue(value) bør kaldes hvert frame eller hver gang nye rådata er tilgængelige for denne måler.

Processen med indsamling af skærmdata bør generelt følge denne struktur:

  1. engine.vision.meter-værdien opdateres baseret på nye data fra skærmen.
  2. Inden for update-funktionen kaldes Meter.setValue(engine.vision.meter) for at registrere den nye værdi.
  3. Meter’en kontrollerer sit interne array om alle værdier er identiske. Hvis ja, opdaterer den sin egen tilstand og kører den tildelte callback-funktion.
  4. Callback-funktionen evaluerer derefter specifikke betingelser baseret på Meter-variablerne og udfører koden, hvis disse betingelser er opfyldt.

VIGTIGT:

Spring ikke callbacks over. Da update-funktionen kører kontinuerligt, skal den forblive så effektiv som muligt. Dens primære rolle bør være at opdatere Meter-værdier. At kæde betingelser inden for update for at kontrollere målere og udløse effekter bør undgås, da det fører til unødvendige kontroller ved hvert cyklus. Definer i stedet effekter i separate funktioner og send dem som callbacks til Meter’en.

Når stabil, giver måleren sin callback-funktion nogle værdier:

VariabelBeskrivelse
Meter.valueMålerens aktuelle værdi.
Meter.increasedEn boolean der angiver om værdien er steget i denne opdatering
Meter.decreasedEn boolean der angiver om værdien er faldet i denne opdatering
Meter.diffDen absolutte værdi af ændringen måleren har oplevet i denne opdatering.

Her er et simpelt enkeltmåler-setup inklusive Meter-klassekoden:

<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");
// Initialiser måler
var healthMeter = new Meter(5, healthEffect);
function update(){
// Opdatér målerværdier
healthMeter.setValue(engine.vision.health);
window.requestAnimationFrame(update);
}
function healthEffect(){
if(healthMeter.increased){
// Udløs effekt
} else if (healthMeter.value == 0){
// Udløs effekt
} else if (healthMeter.diff > .3){
// Udlø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) {
// Tilføj og forskyd.
values.push(updatedValue);
if (values.length > this.size) {
values.shift();
}
// Afslut tidligt, hvis der ikke er langsigtet match.
for (var i = 0; i < values.length - 1; i++) {
if (values[i] !== values[i + 1]) return;
}
// Nået hertil er der en matchende værdissamling. Sæt variabler og 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) {
// Tilføj og forskyd.
values.push(updatedValue);
if (values.length > this.size) {
values.shift();
}
// Afslut tidligt, hvis der ikke er langsigtet match.
for (var i = 0; i < values.length - 1; i++) {
if (values[i] !== values[i + 1]) return;
}
// Nået hertil er der en matchende værdissamling. Sæt variabler og 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();
}
};
}

State-handleren er en effektstak der specifikt håndterer effekter der har prioritet over alle andre. Skal en stor, dominerende animation køre uafbrudt til ende, indsættes den i state-handleren.

MetodeBeskrivelse
StateHandler()Konstruktøren kræver ingen argumenter.
StateHandler.push(new State())Med push kan en ny tilstand skubbes på tilstandsstakken, og behandlingen starter straks.
StateHandler.pop()Fjerner den aktuelle tilstand fra tilstandsstakken og begynder at behandle den forrige tilstand på stakken.

Ethvert objekt der skubbes ind i state-handleren skal implementere Process(). Process-funktionen bestemmer levetiden for en effekt i handleren.

Det følgende viser en grundlæggende state-handler samt Process-funktionen der bør køre inden for effektfunktionerne:

var stateHdlr = new StateHandler();
function StateHandler() {
var stack = [];
var state = null;
// Sæt aktuel tilstand til øverste element på stakken
var updateState = function () {
if (stack.length > 0) {
state = stack[stack.length - 1];
} else {
state = null;
}
};
// Giver udvikleren mulighed for at tilføje en effekt til state-handleren
this.Push = function (newState) {
stack.push(newState);
updateState();
};
// Giver udvikleren mulighed for at fjerne en effekt fra handleren
this.Pop = function () {
stack.pop();
updateState();
};
// Kald Process-funktionen for den aktuelle tilstand (effekt)
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 () {
// Evaluer tid siden effektstart
this.elapsed = new Date.now() - this.start;
// Fjern fra state-handleren, hvis effekten har nået sin levetid
if (this.elapsed > this.duration) {
stateMgr.Pop();
}
// Kald effektens tegnefunktion, hvis den stadig kører
this.Draw();
};

Effect-handlere er fremragende til at gemme og rendere mindre, lettere effekter samlet. Hver effekt i handleren evalueres ved hvert update-kald og fjernes, når den når slutningen af sin levetid.

Effect-handleren er blot et array til at gemme effekter. Det er alt.

// Deklarér effects-array
let effects = [];
// (Ikke vist) Evaluer måler, callback-funktion skubber effekt ind i effects-arrayet
effects.push(new SpecialEffect());
// Iterer gennem arrayet og animer én frame for hver effekt
for (let i = 0; i < effects.length; i++) {
effects[i].draw();
// Fjern effekt, hvis levetiden er udløbet
if (effects[i].lifetime <= 0) {
effects.splice(i, 1);
}
}

State-manageren er specifikt til prioritetseffekter, hvilket betyder at den skal have prioritet i udførelsen. I update-funktionen skal effect-handleren behandles først og derefter state-handleren. Dette sikrer at state-effekten tegnes over elementerne i effect-handleren.

Sådan her:

function update(){
// Evaluer effect-handler
for (let i = 0; i < effects.length; i++) {
effects[i].draw();
if (effects[i].lifetime <= 0) {
effects.splice(i, 1);
}
}
// DEREFTER evaluer state-handler
stateMgr.Process();
}

Lagring af USB-data er en ligetil proces, men de drivere disse programmer bruger er kendt for at forårsage konflikter på visse systemer og til tider deaktivere USB-porte, indtil softwaren fjernes. Den sædvanlige løsning er at deaktivere “Secure Boot” i BIOS/UEFI-indstillingerne. Inden du fortsætter, anbefales det kraftigt at have en systemgendannelse på en USB-stick eller en måde at fjernadgangsstyre computeren der ikke kræver brugerinput ved opstart. Dette er vigtigt, hvis deaktivering af Secure Boot ikke løser problemet og der ikke er adgang til systemet for at afinstallere programmet. I sådanne tilfælde kan en Windows-opdatering være nødvendig for at fjerne alle installerede programmer mens personlige filer bevares. Dette sker på eget ansvar. Er du ikke tryg ved at prøve det, kan du anmode om din enhed her. Brug ikke et laptop-system til denne proces.

Efter installation er processen enkel og opfanger alle data der flyder gennem USB-enhederne. Undlad at indtaste følsomme oplysninger under optagelse, hvis dataene skal deles, da tastetryk er inkluderet i optagelsen. To tredjepartsprogrammer der kan bruges er Usblyzer (gratis prøveperiode) og Wireshark (gratis). Begge fungerer, men med Wireshark skal du sikre at USBPcap er valgt.

Yderligere detaljer om opbygning af måler-callbacks og effektfunktioner findes på vores næste side Callbacks.