Indholdsfortegnelse:
- Trin 1: To typer udvidelser
- Trin 2: Skrivning af en sandkasseudvidelse: Del I
- Trin 3: Skrivning af en sandkasseudvidelse: Del II
- Trin 4: Brug af en sandkasseudvidelse
- Trin 5: Skrivning af en ikke -sandboxet udvidelse: Introduktion
- Trin 6: Skrivning af en udvidet udvidelse: Enkel gamepad
- Trin 7: Brug af en ikke -sandboxet udvidelse
- Trin 8: Dual-kompatibilitet og hastighed
Video: Scratch 3.0 -udvidelser: 8 trin
2024 Forfatter: John Day | [email protected]. Sidst ændret: 2024-01-30 08:25
Scratch -udvidelser er stykker af Javascript -kode, der tilføjer nye blokke til Scratch. Mens Scratch er bundtet med en masse officielle udvidelser, er der ikke en officiel mekanisme til tilføjelse af brugerfremstillede udvidelser.
Da jeg lavede min Minecraft -kontroludvidelse til Scratch 3.0, fandt jeg det svært at komme i gang. Denne instruktør indsamler oplysninger fra forskellige kilder (især dette) plus et par ting, jeg selv fandt ud af.
Du skal vide, hvordan du programmerer i Javascript, og hvordan du hoster dit Javascript på et websted. Til sidstnævnte anbefaler jeg GitHub Pages.
Hovedtricket er at bruge SheepTesters mod af Scratch, som lader dig indlæse udvidelser og plugins.
Denne instruks vil guide dig gennem to udvidelser:
- Hent: indlæsning af data fra en URL og udtrækning af JSON -tags, f.eks. Til indlæsning af vejrdata
- SimpleGamepad: ved hjælp af en spilcontroller i Scratch (en mere sofistikeret version er her).
Trin 1: To typer udvidelser
Der er to typer udvidelser, som jeg vil kalde "usandboxed" og "sandboxed". Udvidelser med sandkasse kører som webarbejdere, og har som følge heraf betydelige begrænsninger:
- Webarbejdere kan ikke få adgang til globaler i vindueobjektet (i stedet har de et globalt selvobjekt, som er meget mere begrænset), så du kan ikke bruge dem til ting som adgang til gamepad.
- Udvidelser med sandkasse har ikke adgang til objektet Scratch runtime.
- Udvidelser med sandkasse er meget langsommere.
- Javascript -konsolfejlmeddelelser for udvidelser med sandkasse er mere kryptiske i Chrome.
På den anden side:
- Det er sikrere at bruge andres sandkasseudvidelser.
- Sandboxed -udvidelser fungerer mere sandsynligt med enhver eventuel officiel understøttelse af indlæsning af udvidelser.
- Udvidelser med sandkasse kan testes uden at uploades til en webserver ved at kode til en data: // URL.
De officielle udvidelser (f.eks. Musik, pen osv.) Er alle ikke i sandboks. Konstruktøren til udvidelsen får runtime -objektet fra Scratch, og vinduet er fuldt tilgængeligt.
Fetch -udvidelsen er sandkasse, men Gamepad -en har brug for navigatorobjektet fra vinduet.
Trin 2: Skrivning af en sandkasseudvidelse: Del I
For at lave en udvidelse opretter du en klasse, der koder for oplysninger om den, og tilføjer derefter en smule kode for at registrere udvidelsen.
Det vigtigste i udvidelsesklassen er en getInfo () -metode, der returnerer et objekt med de nødvendige felter:
- id: det interne navn på udvidelsen skal være unikt for hver udvidelse
- navn: udvidelsens venlige navn, der vises på Scratchs liste over blokke
- blokke: en liste over objekter, der beskriver den nye brugerdefinerede blok.
Og der er et valgfrit menufelt, der ikke bliver brugt i Fetch, men vil blive brugt i Gamepad.
Så her er den grundlæggende skabelon til Hent:
klasse ScratchFetch {
constructor () {} getInfo () {return {"id": "Hent", "navn": "Hent", "blokke": [/* tilføj senere * /]}} / * tilføj metoder til blokke * /} Scratch.extensions.register (ny ScratchFetch ())
Trin 3: Skrivning af en sandkasseudvidelse: Del II
Nu skal vi oprette listen over blokke i getInfo () objekt. Hver blok har brug for mindst disse fire felter:
- opcode: dette er navnet på den metode, der kaldes til at udføre blokens arbejde
-
blockType: dette er bloktypen; de mest almindelige for udvidelser er:
- "kommando": gør noget, men returnerer ikke en værdi
- "reporter": returnerer en streng eller et tal
- "Boolean": returnerer en boolean (bemærk store bogstaver)
- "hat": begivenhedsfangende blok; hvis din Scratch -kode bruger denne blok, undersøger Scratch -runtime regelmæssigt den tilknyttede metode, der returnerer en boolean for at sige, om hændelsen er sket
- tekst: dette er en venlig beskrivelse af blokken med argumenterne i parentes, f.eks. "hent data fra "
-
argumenter: dette er et objekt med et felt for hvert argument (f.eks. "url" i ovenstående eksempel); dette objekt har til gengæld disse felter:
- type: enten "streng" eller "nummer"
- defaultValue: standardværdien, der skal udfyldes på forhånd.
Her er for eksempel blokkefeltet i min Hent -udvidelse:
"blokke": [{"opcode": "fetchURL", "blockType": "reporter", "text": "hent data fra ", "argumenter": {"url": {"type": "string", "defaultValue ":" https://api.weather.gov/stations/KNYC/observations "},}}, {" opcode ":" jsonExtract "," blockType ":" reporter "," text ":" extract [name] fra [data] "," argumenter ": {" navn ": {" type ":" streng "," defaultValue ":" temperatur "}," data ": {" type ":" streng "," defaultValue ": '{"temperatur": 12.3}'},}},]
Her definerede vi to blokke: fetchURL og jsonExtract. Begge er journalister. Den første trækker data fra en URL og returnerer den, og den anden udtrækker et felt fra JSON -data.
Endelig skal du inkludere metoderne for to blokke. Hver metode tager et objekt som et argument, hvor objektet indeholder felter for alle argumenterne. Du kan afkode disse ved hjælp af krøllede seler i argumenterne. For eksempel er her et synkront eksempel:
jsonExtract ({navn, data}) {
var parsed = JSON.parse (data) if (name in parsed) {var out = parsed [name] var t = typeof (out) if (t == "string" || t == "number") returnerer hvis (t == "boolsk") return t? 1: 0 return JSON.stringify (out)} else {return ""}}
Koden trækker navnefeltet fra JSON -dataene. Hvis feltet indeholder en streng, et tal eller en boolean, returnerer vi det. Ellers re-JSONify vi feltet. Og vi returnerer en tom streng, hvis navnet mangler i JSON.
Nogle gange kan du dog lave en blok, der bruger en asynkron API. Metoden fetchURL () bruger fetch API, som er asynkron. I et sådant tilfælde skal du returnere et løfte fra din metode, der gør arbejdet. For eksempel:
fetchURL ({url}) {
returner hentning (url). derefter (respons => svar.tekst ())}
Det er det. Den fulde udvidelse er her.
Trin 4: Brug af en sandkasseudvidelse
Der er to måder at bruge sandboxed extension. Først kan du uploade det til en webserver og derefter indlæse det i SheepTesters Scratch -mod. For det andet kan du kode det ind i en data -URL og indlæse det i Scratch -moden. Jeg bruger faktisk den anden metode ganske lidt til test, da den undgår bekymringer om ældre versioner af udvidelsen, der bliver cachelagret af serveren. Bemærk, at mens du kan være vært for javascript fra Github Pages, kan du ikke gøre det direkte fra et almindeligt github -lager.
Min fetch.js er hostet på https://arpruss.github.io/fetch.js. Eller du kan konvertere din udvidelse til en data -URL ved at uploade den her og derefter kopiere den til udklipsholderen. En data -URL er en kæmpe URL, der indeholder en hel fil i den.
Gå til SheepTester's Scratch mod. Klik på knappen Tilføj udvidelse i nederste venstre hjørne. Klik derefter på "Vælg en udvidelse", og indtast din webadresse (du kan indsætte hele den gigantiske data -URL, hvis du vil).
Hvis alt gik godt, har du en post til din udvidelse i venstre side af din Scratch-skærm. Hvis det ikke gik godt, skal du åbne din Javascript-konsol (shift-ctrl-J i Chrome) og prøve at fejlsøge problemet.
Ovenfor finder du nogle eksempler på kode, der henter og analyserer JSON -data fra KNYC (i New York) -stationen i US National Weather Service, og viser den, mens du vender spriten til ansigtet på samme måde, som vinden blæser. Den måde, jeg lavede det på, var ved at hente dataene i en webbrowser og derefter finde ud af koderne. Hvis du vil prøve en anden vejrstation, skal du indtaste et nærliggende postnummer i søgefeltet på weather.gov, og vejrsiden for din placering skal give dig en firebogstavsstationskode, som du kan bruge i stedet for KNYC i kode.
Du kan også inkludere din sandkasseudvidelse direkte i URL'en til SheepTester's mod ved at tilføje et "? Url =" argument. For eksempel:
sheeptester.github.io/scratch-gui/?url=https://arpruss.github.io/fetch.js
Trin 5: Skrivning af en ikke -sandboxet udvidelse: Introduktion
Konstruktøren af en ikke -sandboxet udvidelse får bestået et Runtime -objekt. Du kan ignorere det eller bruge det. En brug af Runtime -objektet er at bruge dets nuværende MSMS -egenskab til at synkronisere hændelser ("hat -blokke"). Så vidt jeg kan se, bliver alle hændelsesblok -opcodes undersøgt regelmæssigt, og hver runde i afstemningen har en enkelt currentMSecs -værdi. Hvis du har brug for Runtime -objektet, starter du sandsynligvis din udvidelse med:
klasse EXTENSIONCLASS {
constructor (runtime) {this.runtime = runtime…}…}
Alle standardvindueobjekter kan bruges i udvidelsen uden sandkasse. Endelig skal din usandbox -udvidelse ende med denne magiske kode:
(funktion () {
var extensionInstance = ny EXTENSIONCLASS (window.vm.extensionManager.runtime) var serviceName = window.vm.extensionManager._registerInternalExtension (extensionInstance) window.vm.extensionManager._loadedExtensions.set (extensionInstance.getInfo (). (id, serviceName)}))
hvor du skal udskifte EXTENSIONCLASS med din udvidelses klasse.
Trin 6: Skrivning af en udvidet udvidelse: Enkel gamepad
Lad os nu lave en simpel gamepad -udvidelse, der giver en enkelt hændelsesblok ("hat"), når der trykkes på en knap eller slippes.
Under hver afstemningscyklus for hændelsesblokke gemmer vi et tidsstempel fra runtime -objektet, og den tidligere og aktuelle gamepad -tilstand. Tidsstemplet bruges til at genkende, om vi har en ny afstemningscyklus. Så starter vi med:
klasse ScratchSimpleGamepad {
constructor (runtime) {this.runtime = runtime this.currentMSecs = -1 this.previousButtons = this.currentButtons = }…} Vi vil have en hændelsesblok med to indgange-et knapnummer og en menu til at vælge, om vi vil have hændelsen til at udløses ved tryk eller slip. Så her er vores metode
få information() {
return {"id": "SimpleGamepad", "name": "SimpleGamepad", "blocks": [{"opcode": "buttonPressedReleased", "blockType": "hat", "text": "knap [eventType] "," argumenter ": {" b ": {" type ":" nummer "," defaultValue ":" 0 "}," eventType ": {" type ":" nummer "," defaultValue ":" 1 "," menu ":" pressReleaseMenu "},},},]," menuer ": {" pressReleaseMenu ": [{tekst:" press ", værdi: 1}, {text:" release ", værdi: 0}],}}; } Jeg tror, at værdierne i rullemenuen stadig overføres til opcode-funktionen som strenge, på trods af at de er erklæret som tal. Så sammenlign dem eksplicit med de værdier, der er angivet i menuen efter behov. Vi skriver nu en metode, der opdaterer knaptilstandene, når der sker en ny afstemningscyklus for hændelser
opdater () {
hvis (this.runtime.currentMSecs == this.currentMSecs) returnerer // ikke en ny pollingcyklus this.currentMSecs = this.runtime.currentMSecs var gamepads = navigator.getGamepads () if (gamepads == null || gamepads.length = = 0 || gamepads [0] == null) {this.previousButtons = this.currentButtons = return} var gamepad = gamepads [0] if (gamepad.buttons.length! = This.previousButtons.length) { // forskelligt antal knapper, så ny gamepad this.previousButtons = for (var i = 0; i <gamepad.buttons.length; i ++) this.previousButtons.push (false)} else {this.previousButtons = this. currentButtons} this.currentButtons = for (var i = 0; i <gamepad.buttons.length; i ++) this.currentButtons.push (gamepad.buttons .pressed)} Endelig kan vi implementere vores hændelsesblok ved at kalde metoden update () og derefter kontrollere, om den nødvendige knap lige er blevet trykket eller frigivet ved at sammenligne nuværende og tidligere knaptilstande
buttonPressedReleased ({b, eventType}) {
this.update () if (b <this.currentButtons.length) {if (eventType == 1) {// note: dette vil være en streng, så det er bedre at sammenligne det med 1 end at behandle det som en booleske hvis (this.currentButtons &&! this.previousButtons ) {return true}} else {if (! this.currentButtons && this.previousButtons ) {return true}}} return false { Og endelig tilføjer vi vores magiske udvidelsesregistreringskode efter at have defineret klassen
(funktion () {
var extensionInstance = ny ScratchSimpleGamepad (window.vm.extensionManager.runtime) var serviceName = window.vm.extensionManager._registerInternalExtension (extensionInstance) window.vm.extensionManager._loadedExtensions.set (extensionInstance.getInfo ()). id, serviceName))
Du kan få den fulde kode her.
Trin 7: Brug af en ikke -sandboxet udvidelse
Igen, vært din udvidelse et sted, og denne gang indlæse den med load_plugin = frem for url = argument til SheepTester's Scratch mod. For eksempel, for min enkle Gamepad -mod, skal du gå til:
sheeptester.github.io/scratch-gui/?load_plugin=https://arpruss.github.io/simplegamepad.js
(Forresten, hvis du vil have en mere sofistikeret gamepad, skal du bare fjerne "simple" fra ovenstående URL, så får du rumlen og analog akseunderstøttelse.)
Igen skal udvidelsen vises i venstre side af din Scratch -editor. Ovenfor er et meget simpelt Scratch -program, der siger "hej", når du trykker på knap 0 og "farvel", når du slipper det.
Trin 8: Dual-kompatibilitet og hastighed
Jeg har lagt mærke til, at udvidelsesblokke kører en størrelsesorden hurtigere ved hjælp af den indlæsningsmetode, jeg brugte til udvidelser uden sandkasse. Så medmindre du bekymrer dig om sikkerhedsfordelene ved at køre i en Web Worker -sandkasse, vil din kode have fordel af at blive indlæst med argumentet? Load_plugin = URL til SheepTesters mod.
Du kan gøre en sandkasseudvidelse kompatibel med begge indlæsningsmetoder ved at bruge følgende kode efter at have defineret udvidelsesklassen (skift CLASSNAME til navnet på din udvidelsesklasse):
(funktion () {
var extensionClass = CLASSNAME if (typeof window === "undefined" ||! window.vm) {Scratch.extensions.register (new extensionClass ())} else {var extensionInstance = new extensionClass (window.vm.extensionManager.runtime) var serviceName = window.vm.extensionManager._registerInternalExtension (extensionInstance) window.vm.extensionManager._loadedExtensions.set (extensionInstance.getInfo (). id, serviceName)}}) ()
Anbefalede:
BBC Micro: bit og Scratch - interaktivt rat og drivspil: 5 trin (med billeder)
BBC Micro: bit and Scratch - Interactive Rat & Driving Game: En af mine klasseopgaver i denne uge er at bruge BBC Micro: bit til at komme i kontakt med et Scratch -program, vi har skrevet. Jeg troede, at dette var den perfekte mulighed for at bruge mit ThreadBoard til at oprette et integreret system! Min inspiration til bunden p
ARDUINO + SCRATCH Skydespil: 6 trin
ARDUINO + SCRATCH Skydespil: Gem din kage !!! Den er i fare. Der er fire fluer, der nærmer sig det. Du har kun 30 sekunder til at skyde fluerne og gemme din kage
(Meget enkel) Sygdomsmodellering (ved hjælp af Scratch): 5 trin
(Meget enkel) Sygdomsmodellering (ved hjælp af Scratch): I dag simulerer vi et sygdomsudbrud, idet det er en hvilken som helst sygdom, ikke nødvendigvis COVID-19. Denne simulering blev inspireret af en video af 3blue1brown, som jeg vil linke til. Da dette er træk og slip, kan vi ikke gøre så meget som vi kan med JS eller Pyt
Story Interactive (Scratch Game): 8 trin
Story Interactive (Scratch Game): Dette vil være en vejledning i, hvordan man laver et spil i bunden med dialog og sprites. Det vil også lære dig at tilføje klip i dit spil og timing, herunder broadcast og mere
Akustisk levitation med Arduino Uno trin for trin (8 trin): 8 trin
Akustisk levitation med Arduino Uno Step-by Step (8-trin): ultralyds lydtransducere L298N Dc kvindelig adapter strømforsyning med en han-DC-pin Arduino UNOBreadboard Sådan fungerer det: Først uploader du kode til Arduino Uno (det er en mikrokontroller udstyret med digital og analoge porte til konvertering af kode (C ++)