INHOUDSOPGAWE:

Scratch 3.0 -uitbreidings: 8 stappe
Scratch 3.0 -uitbreidings: 8 stappe

Video: Scratch 3.0 -uitbreidings: 8 stappe

Video: Scratch 3.0 -uitbreidings: 8 stappe
Video: Замена подшипника в стиральной машине самсунг 2024, Julie
Anonim
Kras 3.0 -uitbreidings
Kras 3.0 -uitbreidings

Krasuitbreidings is stukke Javascript -kode wat nuwe blokke by Scratch voeg. Alhoewel Scratch saamgevoeg is met 'n klomp amptelike uitbreidings, is daar nie 'n amptelike meganisme om gebruikersgemaakte uitbreidings by te voeg nie.

Toe ek my Minecraft -beheeruitbreiding vir Scratch 3.0 maak, het ek dit moeilik gevind om aan die gang te kom. Hierdie instruksie versamel inligting uit verskillende bronne (veral hierdie), plus 'n paar dinge wat ek self ontdek het.

U moet weet hoe u in Javascript moet programmeer en hoe u u Javascript op 'n webwerf kan huisves. Vir laasgenoemde beveel ek GitHub Pages aan.

Die belangrikste truuk is om SheepTester se mod van Scratch te gebruik waarmee u uitbreidings en inproppe kan laai.

Hierdie instruksie sal u lei deur twee uitbreidings te maak:

  • Haal: laai data van 'n URL en onttrek JSON -etikette, byvoorbeeld om weerdata te laai
  • SimpleGamepad: gebruik 'n spelbeheerder in Scratch ('n meer gesofistikeerde weergawe is hier).

Stap 1: Twee tipes uitbreidings

Daar is twee tipes uitbreidings wat ek 'onbeseerde' en 'sandkas' sal noem. Uitbreidings met sandkaste werk as webwerkers en het gevolglik aansienlike beperkings:

  • Webwerkers het nie toegang tot die wêreldwye in die venstervoorwerp nie (in plaas daarvan het hulle 'n wêreldwye selfvoorwerp, wat baie meer beperk is), sodat u dit nie kan gebruik vir dinge soos toegang tot gamepad nie.
  • Uitbreidings met sandkaste het nie toegang tot die Scratch -runtime -voorwerp nie.
  • Uitbreidings met sandkaste is baie stadiger.
  • Javascript -konsole -foutboodskappe vir uitbreidings met sandkaste is meer kripties in Chrome.

Aan die ander kant:

  • Dit is veiliger om ander uitbreidings met sandkaste te gebruik.
  • Uitbreidings met sandkaste werk meer waarskynlik saam met die uiteindelike laai -ondersteuning van amptelike uitbreidings.
  • Uitbreidings met sandkaste kan getoets word sonder om dit na 'n webbediener op te laai deur te kodeer in 'n data: // URL.

Die amptelike uitbreidings (soos die musiek, pen, ens.) Is almal onbeperk. Die konstruktor vir die uitbreiding kry die runtime -voorwerp van Scratch, en die venster is volledig toeganklik.

Die Fetch -uitbreiding is in sandkas, maar die Gamepad -een benodig die navigator -voorwerp uit die venster.

Stap 2: Skryf 'n uitbreiding met sandkaste: Deel I

Om 'n uitbreiding te maak, skep u 'n klas wat inligting daaroor kodeer en voeg dan 'n bietjie kode by om die uitbreiding te registreer.

Die belangrikste ding in die uitbreidingsklas is 'n getInfo () -metode wat 'n voorwerp met die vereiste velde teruggee:

  • id: die interne naam van die uitbreiding moet uniek wees vir elke uitbreiding
  • naam: die vriendelike naam van die uitbreiding, wat verskyn in die lys blokke van Scratch
  • blokke: 'n lys van voorwerpe wat die nuwe pasgemaakte blok beskryf.

En daar is 'n opsionele spyskaarteveld wat nie in Fetch gebruik word nie, maar in Gamepad gebruik sal word.

Hier is die basiese sjabloon vir haal:

klas ScratchFetch {

constructor () {} getInfo () {return {"id": "Haal", "naam": "Haal", "blokke": [/* voeg later by * /]}} / * voeg metodes by vir blokke * /} Scratch.extensions.register (nuwe ScratchFetch ())

Stap 3: Skryf 'n uitbreiding met sandkaste: Deel II

Nou moet ons die lys blokke in die voorwerp van getInfo () skep. Elke blok benodig ten minste hierdie vier velde:

  • opcode: dit is die naam van die metode om die blok se werk te doen
  • blockType: dit is die bloktipe; die algemeenste vir uitbreidings is:

    • "command": doen iets, maar gee nie 'n waarde terug nie
    • "verslaggewer": gee 'n string of getal terug
    • "Boolean": gee 'n Boolean terug (let op die hoofletter)
    • "hoed": gebeurtenis vang blok; as u Scratch -kode hierdie blok gebruik, word die geassosieerde metode gereeld deur die Scratch -tydsduur ondersoek, wat 'n booleaner gee om te sê of die gebeurtenis plaasgevind het
  • teks: dit is 'n vriendelike beskrywing van die blok, met die argumente tussen hakies, bv. "haal data van "
  • argumente: dit is 'n voorwerp met 'n veld vir elke argument (bv. 'url' in die voorbeeld hierbo); hierdie voorwerp het weer die volgende velde:

    • tipe: óf "string" óf "nommer"
    • defaultValue: die standaardwaarde wat vooraf ingevul moet word.

Hier is byvoorbeeld die blokke -veld in my Fetch -uitbreiding:

"blokke": [{"opcode": "fetchURL", "blockType": "reporter", "text": "haal data van ", "argumente": {"url": {"type": "string", "defaultValue ":" https://api.weather.gov/stations/KNYC/observations "},}}, {" opcode ":" jsonExtract "," blockType ":" reporter "," text ":" extract [name] van [data] "," argumente ": {" naam ": {" tipe ":" string "," defaultValue ":" temperatuur "}," data ": {" type ":" string "," defaultValue ": '{' temperatuur ': 12.3}'},}},]

Hier het ons twee blokke gedefinieer: fetchURL en jsonExtract. Albei is verslaggewers. Die eerste haal data uit 'n URL en gee dit terug, en die tweede onttrek 'n veld uit JSON -data.

Uiteindelik moet u die metodes vir twee blokke insluit. Elke metode neem 'n voorwerp as 'n argument, en die voorwerp bevat velde vir al die argumente. U kan dit met behulp van krulletjies in die argumente dekodeer. Hier is byvoorbeeld 'n sinchroniese voorbeeld:

jsonExtract ({naam, data}) {

var parsed = JSON.parse (data) if (name in parsed) {var out = parsed [name] var t = typeof (out) if (t == "string" || t == "number") return out if (t == "boolean") terugkeer t? 1: 0 gee JSON.stringify (uit)} anders terug {return ""}}

Die kode trek die naamveld uit die JSON -data. As die veld 'n string, getal of boolean bevat, gee ons dit terug. Anders her-JSONify ons die veld. En ons gee 'n leë string terug as die naam ontbreek in die JSON.

Soms wil u egter 'n blok maak wat 'n asynchrone API gebruik. Die metode fetchURL () gebruik die haal -API wat asynchroon is. In so 'n geval moet u 'n belofte van u metode teruggee wat die werk doen. Byvoorbeeld:

fetchURL ({url}) {

stuur terug (url). dan (response => response.text ())}

Dis dit. Die volledige uitbreiding is hier.

Stap 4: Gebruik 'n sandbox -uitbreiding

Gebruik 'n sandbox -uitbreiding
Gebruik 'n sandbox -uitbreiding
Gebruik 'n sandbox -uitbreiding
Gebruik 'n sandbox -uitbreiding
Gebruik 'n sandbox -uitbreiding
Gebruik 'n sandbox -uitbreiding

Daar is twee maniere om sandbox -uitbreidings te gebruik. Eerstens kan u dit na 'n webbediener oplaai en dit dan in SheepTester se Scratch -mod laai. Tweedens kan u dit in 'n data -URL kodeer en dit in die Scratch -mod laai. Ek gebruik die tweede metode eintlik 'n bietjie om te toets, want dit vermy kommer oor die ouer weergawes van die uitbreiding deur die bediener. Let daarop dat, hoewel u javascript van Github Pages kan aanbied, u dit nie direk vanaf 'n gewone github -bewaarplek kan doen nie.

My fetch.js word aangebied op https://arpruss.github.io/fetch.js. Of u kan u uitbreiding omskakel na 'n data -URL deur dit hier op te laai en dit dan na die knipbord te kopieer. 'N Data -URL is 'n reuse -URL wat 'n hele lêer daarin bevat.

Gaan na SheepTester's Scratch -mod. Klik op die knoppie Voeg uitbreiding in die onderste linkerhoek. Klik dan op "Kies 'n uitbreiding" en voer u URL in (u kan die hele reuse -gegewens -URL plak as u wil).

As alles goed verloop, het u 'n inskrywing vir u uitbreiding aan die linkerkant van u Scratch-skerm. As dit nie goed gaan nie, moet u u Javascript-konsole (shift-ctrl-J in Chrome) oopmaak en die probleem probeer ontfout.

Hierbo vind u 'n voorbeeldkode wat JSON -data van die KNYC (in New York) stasie van die Amerikaanse nasionale weerdiens af haal en ontleed, en dit vertoon terwyl u die sprite na dieselfde kant toe draai as wat die wind waai. Die manier waarop ek dit gemaak het, was deur die data in 'n webblaaier te gaan haal en dan die etikette uit te vind. As u 'n ander weerstasie wil probeer, voer die poskode in die buurt in die soekkassie by weather.gov, en die weerbladsy vir u ligging moet 'n vierletter -stasiekode gee wat u kan gebruik in plaas van KNYC in die kode.

U kan ook u uitbreiding met sandbox direk in die URL vir SheepTester se mod insluit deur 'n "? Url =" argument by te voeg. Byvoorbeeld:

sheeptester.github.io/scratch-gui/?url=https://arpruss.github.io/fetch.js

Stap 5: Skryf van 'n uitbreiding wat nie in die sand gestuur is nie: inleiding

Die konstrukteur van 'n uitbreiding wat nie in die boks is nie, word deur 'n Runtime -voorwerp geslaag. U kan dit ignoreer of gebruik. Een gebruik van die Runtime -voorwerp is om sy huidige MSecs -eienskap te gebruik om gebeurtenisse ("hoedblokke") te sinchroniseer. Sover ek kan weet, word alle opcodes van die gebeurtenisblokke gereeld ondervra, en elke rondte van die stembus het 'n enkele huidige MSMS -waarde. As u die Runtime -voorwerp benodig, sal u u uitbreiding waarskynlik begin met:

klas UITBREIDINGKLAS {

constructor (runtime) {this.runtime = runtime…}…}

Al die standaardvoorwerpe van die venster kan in die uitbreiding sonder sandbox gebruik word. Uiteindelik moet u uitbreiding sonder sandbox eindig met hierdie bietjie magiese kode:

(funksie () {

var extensionInstance = nuwe EXTENSIONCLASS (window.vm.extensionManager.runtime) var serviceName = window.vm.extensionManager._registerInternalExtension (extensionInstance) window.vm.extensionManager._loadedExtensions.set (extensionInstance.getInfo (). id, serviceName})))

waar u EXTENSIONCLASS moet vervang met die klas van u uitbreiding.

Stap 6: Skryf 'n uitbreiding wat nie in die sand gestuur is nie: Eenvoudige gamepad

Kom ons maak nou 'n eenvoudige gamepad -uitbreiding wat 'n enkele gebeurtenis ("hoed") blok bied vir wanneer 'n knoppie ingedruk of losgemaak word.

Tydens elke peilingsiklus van 'n gebeurtenisblok sal ons 'n tydstempel van die runtime -voorwerp en die vorige en huidige gamepad -toestande stoor. Die tydstempel word gebruik om te herken of ons 'n nuwe stembusiklus het. Dus, ons begin met:

klas ScratchSimpleGamepad {

constructor (runtime) {this.runtime = runtime this.currentMSecs = -1 this.previousButtons = this.currentButtons = }…} Ons sal een gebeurtenisblok hê met twee insette-'n knoppie nommer en 'n spyskaart om te kies of ons wil hê dat die gebeurtenis tydens pers of vrystelling moet begin. So, hier is ons metode

kry inligting() {

return {"id": "SimpleGamepad", "name": "SimpleGamepad", "blocks": [{"opcode": "buttonPressedReleased", "blockType": "hat", "text": "knoppie [eventType] "," argumente ": {" b ": {" type ":" nommer "," defaultValue ":" 0 "}," eventType ": {" type ":" nommer "," defaultValue ":" 1 "," menu ":" pressReleaseMenu "},},},]," menu's ": {" pressReleaseMenu ": [{text:" press ", waarde: 1}, {text:" release ", waarde: 0}],}}; } Ek dink dat die waardes in die keuselys steeds as snare na die opcode-funksie oorgedra word, al word dit as getalle verklaar. Vergelyk dit dus uitdruklik met die waardes wat in die spyskaart gespesifiseer word. Ons skryf nou 'n metode om die knoppies by te werk wanneer 'n nuwe siklus vir gebeurtenisse plaasvind

Opdateer() {

if (this.runtime.currentMSecs == this.currentMSecs) return // not a new polling cycle 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) { // verskillende aantal knoppies, dus nuwe gamepad this.previousButtons = vir (var i = 0; i <gamepad.buttons.length; i ++) this.previousButtons.push (false)} anders {this.previousButtons = dit. currentButtons} this.currentButtons = vir (var i = 0; i <gamepad.buttons.length; i ++) this.currentButtons.push (gamepad.buttons .gedruk)} Uiteindelik kan ons ons gebeurtenisblok implementeer deur die update () -metode aan te roep en dan te kyk of die nodige knoppie pas ingedruk of vrygestel is, deur huidige en vorige knoppies te vergelyk

buttonPressedReleased ({b, eventType}) {

this.update () if (b <this.currentButtons.length) {if (eventType == 1) {// let wel: dit sal 'n string wees, daarom is dit beter om dit met 1 te vergelyk as om dit as 'n Boole te behandel as (this.currentButtons &&! this.previousButtons ) {return true}} else {if (! this.currentButtons && this.previousButtons ) {return true}}} return false} En uiteindelik voeg ons ons magiese uitbreidingsregistrasiekode by nadat ons die klas gedefinieer het

(funksie () {

var extensionInstance = nuwe ScratchSimpleGamepad (window.vm.extensionManager.runtime) var serviceName = window.vm.extensionManager._registerInternalExtension (extensionInstance) window.vm.extensionManager._loadedExtensions.set (extensionInstance.getInfo ().), id))

U kan die volledige kode hier kry.

Stap 7: Gebruik 'n uitbreiding wat nie in die sand gestuur is nie

Gebruik 'n uitbreiding wat nie in die sand gebêre is nie
Gebruik 'n uitbreiding wat nie in die sand gebêre is nie

Weereens, host u uitbreiding iewers en laai dit hierdie keer met die load_plugin = eerder as url = argument na SheepTester's Scratch mod. Byvoorbeeld, vir my eenvoudige Gamepad -mod, gaan na:

sheeptester.github.io/scratch-gui/?load_plugin=https://arpruss.github.io/simplegamepad.js

(Terloops, as u 'n meer gesofistikeerde gamepad wil hê, verwyder dan 'eenvoudig' van die bogenoemde URL, en u sal gedreun en analoge asondersteuning hê.)

Die uitbreiding moet weer aan die linkerkant van u Scratch -redakteur verskyn. Hierbo is 'n baie eenvoudige Scratch -program wat 'hallo' sê as u op knoppie 0 druk en 'totsiens' as u dit loslaat.

Stap 8: Dubbele verenigbaarheid en snelheid

Ek het opgemerk dat uitbreidingsblokke vinniger 'n grootteorde volg met die laaimetode wat ek gebruik het vir uitbreidings sonder sandbox. Dus, tensy u omgee vir die veiligheidsvoordele van die gebruik in 'n Web Worker -sandkas, sal u kode baat daarby om die? Load_plugin = URL -argument na SheepTester se mod te laai.

U kan 'n sandbox -uitbreiding verenigbaar maak met albei laai metodes deur die volgende kode te gebruik nadat u die uitbreidingsklas gedefinieer het (verander CLASSNAME na die naam van u uitbreidingsklas):

(funksie () {

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

Aanbeveel: