Obsah:

Rozšírenia Scratch 3.0: 8 krokov
Rozšírenia Scratch 3.0: 8 krokov

Video: Rozšírenia Scratch 3.0: 8 krokov

Video: Rozšírenia Scratch 3.0: 8 krokov
Video: Делаем платформер на Scratch #3 2024, November
Anonim
Rozšírenia Scratch 3.0
Rozšírenia Scratch 3.0

Rozšírenia Scratch sú časti kódu Javascript, ktoré do Scratch pridávajú nové bloky. Aj keď je program Scratch dodávaný s množstvom oficiálnych rozšírení, neexistuje žiadny oficiálny mechanizmus na pridávanie rozšírení vytvorených používateľmi.

Keď som robil svoje rozšírenie pre ovládanie Minecraft pre Scratch 3.0, bolo pre mňa ťažké začať. Tento návod zhromažďuje informácie z rôznych zdrojov (obzvlášť z tohto) a niekoľko vecí, ktoré som sám objavil.

Musíte vedieť, ako programovať v jazyku Javascript a ako ho hostovať na webovej stránke. V prípade druhého z nich odporúčam stránky GitHub.

Hlavným trikom je použiť program Scratch spoločnosti SheepTester, ktorý vám umožní načítať rozšírenia a doplnky.

Tento návod vás prevedie dvoma rozšíreniami:

  • Načítanie: načítanie údajov z adresy URL a extrahovanie značiek JSON, napríklad na načítanie údajov o počasí
  • SimpleGamepad: používanie herného ovládača v programe Scratch (sofistikovanejšia verzia je tu).

Krok 1: Dva typy rozšírení

Existujú dva typy rozšírení, ktoré budem nazývať „bez sandboxov“a „sandboxed“. Rozšírenia v karanténe fungujú ako weboví pracovníci a v dôsledku toho majú značné obmedzenia:

  • Web Workers nemôže pristupovať ku globálom v objekte window (namiesto toho majú globálny vlastný objekt, ktorý je oveľa obmedzenejší), takže ich nemôžete používať na veci, ako je prístup k gamepadu.
  • Rozšírenia v karanténe nemajú prístup k runtime objektu Scratch.
  • Rozšírenia v karanténe sú oveľa pomalšie.
  • Chybové správy konzoly Javascript pre rozšírenia izolovaného priestoru sú v prehliadači Chrome záhadnejšie.

Na druhej strane:

  • Používanie rozšírení izolovaného priestoru iných ľudí je bezpečnejšie.
  • U rozšírení v karanténe je väčšia pravdepodobnosť, že budú fungovať s prípadnou oficiálnou podporou načítania rozšírení.
  • Rozšírenia v karanténe je možné testovať bez nahrávania na webový server kódovaním do adresy URL data: //.

Oficiálne rozšírenia (ako napríklad Hudba, Pero atď.) Sú všetky bez schránky. Konštruktor rozšírenia získa runtime objekt z programu Scratch a okno je plne prístupné.

Rozšírenie Fetch je v karanténe, ale gamepad potrebuje objekt navigátora z okna.

Krok 2: Napísanie rozšírenia v karanténe: časť I

Ak chcete vytvoriť rozšírenie, vytvorte triedu, ktorá kóduje informácie o ňom, a potom pridajte kúsok kódu na registráciu rozšírenia.

Hlavnou vecou v triede rozšírení je metóda getInfo (), ktorá vracia objekt s požadovanými poľami:

  • id: interný názov rozšírenia, musí byť jedinečný pre každé rozšírenie
  • názov: popisný názov rozšírenia, ktorý sa zobrazuje v zozname blokov programu Scratch
  • bloky: zoznam objektov popisujúcich nový vlastný blok.

A existuje voliteľné pole ponúk, ktoré sa vo Fetch nepoužije, ale použije sa v Gamepade.

Tu je teda základná šablóna pre Fetch:

trieda ScratchFetch {

constructor () {} getInfo () {return {"id": "Fetch", "name": "Fetch", "blocks": [/* add later * /]}} / * add methods for blocks * /} Scratch.extensions.register (nový ScratchFetch ())

Krok 3: Napísanie rozšírenia v karanténe: časť II

Teraz musíme vytvoriť zoznam blokov v objekte getInfo (). Každý blok potrebuje najmenej tieto štyri polia:

  • opcode: toto je názov metódy, ktorá sa volá na vykonanie práce bloku
  • blockType: toto je typ bloku; Najbežnejšie pre rozšírenia sú:

    • "príkaz": urobí niečo, ale nevráti hodnotu
    • "reportér": vráti reťazec alebo číslo
    • „Boolean“: vráti logickú hodnotu (všimnite si veľké písmená)
    • „klobúk“: blok zachytávajúci udalosť; ak váš kód Scratch používa tento blok, runtime programu Scratch pravidelne vyhľadáva priradenú metódu, ktorá vracia logickú hodnotu, a uvádza, či sa udalosť stala
  • text: toto je priateľský popis bloku s argumentmi v zátvorkách, napr. „načítať údaje z “
  • argumenty: toto je objekt s poľom pre každý argument (napr. „URL“vo vyššie uvedenom príklade); tento objekt má zase tieto polia:

    • zadajte: buď „reťazec“alebo „číslo“
    • defaultValue: predvolená hodnota, ktorá sa má vopred vyplniť.

Tu je napríklad pole blokov v mojom rozšírení Fetch:

"bloky": [{"opcode": "fetchURL", "blockType": "reporter", "text": "fetch data from ", "arguments": {"url": {"type": "string", "defaultValue ":" https://api.weather.gov/stations/KNYC/observations "},}}, {" opcode ":" jsonExtract "," blockType ":" reportér "," text ":" výpis [názov] from [data] "," arguments ": {" name ": {" type ":" string "," defaultValue ":" temperature "}," data ": {" type ":" string "," defaultValue ": '{"teplota": 12,3}'}}}}},]

Tu sme definovali dva bloky: fetchURL a jsonExtract. Obaja sú reportéri. Prvý vyberie údaje z adresy URL a vráti ich a druhý extrahuje pole z údajov JSON.

Nakoniec musíte zahrnúť metódy pre dva bloky. Každá metóda berie objekt ako argument, pričom objekt obsahuje polia pre všetky argumenty. Môžete ich dekódovať pomocou zložených zátvoriek v argumentoch. Tu je napríklad jeden synchrónny príklad:

jsonExtract ({meno, údaje}) {

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") vrátiť t? 1: 0 vrátiť JSON.stringify (out)} else {return ""}}

Kód stiahne pole s názvom z údajov JSON. Ak pole obsahuje reťazec, číslo alebo booleovskú hodnotu, vrátime ho. V opačnom prípade pole znova JSONify. A ak v názve JSON chýba názov, vrátime prázdny reťazec.

Niekedy však môžete chcieť vytvoriť blok, ktorý používa asynchrónne API. Metóda fetchURL () používa fetch API, ktoré je asynchrónne. V takom prípade by ste mali vrátiť sľub zo svojej metódy, ktorá funguje. Napríklad:

fetchURL ({url}) {

vrátiť načítanie (URL). potom (odpoveď => response.text ())}

To je všetko. Úplné rozšírenie je tu.

Krok 4: Použitie rozšírenia v karanténe

Použitie rozšírenia v karanténe
Použitie rozšírenia v karanténe
Použitie rozšírenia v karanténe
Použitie rozšírenia v karanténe
Použitie rozšírenia v karanténe
Použitie rozšírenia v karanténe

Existujú dva spôsoby použitia rozšírenia v karanténe. Najprv ho môžete nahrať na webový server a potom načítať do režimu Scratch spoločnosti SheepTester. Za druhé, môžete ho zakódovať na údajovú adresu URL a načítať do režimu Scratch. Druhú metódu v skutočnosti používam na testovanie dosť, pretože predchádza obavám, že by sa staršie verzie rozšírenia nedostali do vyrovnávacej pamäte servera. Všimnite si toho, že aj keď môžete javascript hostovať zo stránok Github, nemôžete to robiť priamo z bežného úložiska github.

Môj súbor fetch.js je hostený na adrese https://arpruss.github.io/fetch.js. Alebo môžete svoje rozšírenie previesť na dátovú adresu URL tak, že ho nahráte sem a potom skopírujete do schránky. Dátová adresa URL je obrovská adresa URL, ktorá obsahuje celý súbor.

Prejdite na režim SheepTester's Scratch. Kliknite na tlačidlo Pridať rozšírenie v dolnom ľavom rohu. Potom kliknite na „Vybrať rozšírenie“a zadajte svoju adresu URL (ak chcete, môžete vložiť celú obrovskú dátovú adresu URL).

Ak všetko prebehlo dobre, na ľavej strane obrazovky Scratch budete mať záznam pre svoje rozšírenie. Ak veci nefungujú dobre, mali by ste otvoriť konzolu Javascript (shift-ctrl-J v prehliadači Chrome) a pokúsiť sa problém odladiť.

Hore nájdete nejaký ukážkový kód, ktorý načítava a analyzuje údaje JSON zo stanice KNYC (v New Yorku) americkej národnej meteorologickej služby a zobrazuje ich pri otáčaní škriatka tvárou v tvár vetru. Vytvoril som to tak, že som načítal údaje do webového prehliadača a potom som zistil značky. Ak chcete vyskúšať inú meteorologickú stanicu, zadajte blízke PSČ do vyhľadávacieho poľa na stránke weather.gov a stránka s počasím pre vašu polohu by vám mala poskytnúť štvorpísmenný kód stanice, ktorý môžete použiť namiesto KNYC v kód.

Rozšírenie v izolovanej oblasti môžete tiež zahrnúť priamo do adresy URL režimu SheepTester pridaním argumentu „? Url =“. Napríklad:

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

Krok 5: Napíšte rozšírenie, ktoré nie je v karanténe: Úvod

Konštruktorovi rozšírenia bez schránky bude odovzdaný objekt Runtime. Môžete to ignorovať alebo použiť. Jedno použitie objektu Runtime je použiť jeho vlastnosť currentMSecs na synchronizáciu udalostí ("klobúkové bloky"). Pokiaľ môžem povedať, všetky operačné kódy blokov udalostí sa zisťujú pravidelne a každé kolo hlasovania má jednu hodnotu currentMSecs. Ak potrebujete objekt Runtime, pravdepodobne spustíte rozšírenie pomocou:

trieda ROZŠÍRENIE Trieda {

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

Všetky štandardné veci s okennými objektmi je možné použiť v rozšírení bez schránky. Nakoniec by sa vaše rozšírenie bez schránky malo končiť týmto kúzlom kúzelného kódu:

(funkcia () {

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

kde by ste mali nahradiť EXTENSIONCLASS triedou vášho rozšírenia.

Krok 6: Napíšte rozšírenie, ktoré nie je v karanténe: Jednoduchý gamepad

Teraz urobme jednoduché rozšírenie gamepadu, ktoré poskytuje blok jednej udalosti („klobúk“) po stlačení alebo uvoľnení tlačidla.

Počas každého cyklu pollingu bloku udalostí uložíme časovú pečiatku z objektu runtime a predchádzajúci a aktuálny stav gamepadu. Časová pečiatka sa používa na rozpoznanie, či máme nový cyklus hlasovania. Začíname teda s:

trieda ScratchSimpleGamepad {

constructor (runtime) {this.runtime = runtime this.currentMSecs = -1 this.previousButtons = this.currentButtons = }…} Budeme mať jeden blok udalostí s dvoma vstupmi-číslom tlačidla a ponukou na výber, či sa má udalosť spustiť stlačením alebo uvoľnením. Tu je teda naša metóda

dostať informácie() {

return {"id": "SimpleGamepad", "name": "SimpleGamepad", "blocks": [{"opcode": "buttonPressedReleased", "blockType": "hat", "text": "button [eventType] "," argumenty ": {" b ": {" type ":" number "," defaultValue ":" 0 "}," eventType ": {" type ":" number "," defaultValue ":" 1 "," menu ":" pressReleaseMenu "},},},]," menu ": {" pressReleaseMenu ": [{text:" press ", hodnota: 1}, {text:" release ", hodnota: 0}],}}; } Myslím si, že hodnoty v rozbaľovacej ponuke sa stále prenášajú do funkcie operačného kódu ako reťazce, napriek tomu, že sú deklarované ako čísla. Podľa potreby ich teda výslovne porovnajte s hodnotami uvedenými v ponuke. Teraz napíšeme metódu, ktorá aktualizuje stavy tlačidiel vždy, keď nastane nový cyklus zisťovania udalostí

aktualizovať () {

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 || gamepady [0] == null) {this.previousButtons = this.currentButtons = return} var gamepad = gamepads [0] if (gamepad.buttons.length! = This.previousButtons.length) { // rôzny počet tlačidiel, takže nový gamepad this.previousButtons = pre (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)} Nakoniec môžeme náš blok udalostí implementovať tak, že zavoláme metódu update () a potom skontrolujeme, či bolo požadované tlačidlo práve stlačené alebo uvoľnené, a to porovnaním súčasného a predchádzajúceho stavu tlačidiel.

buttonPressedReleased ({b, eventType}) {

this.update () if (b <this.currentButtons.length) {if (eventType == 1) {// poznámka: toto bude reťazec, takže je lepšie ho porovnať s 1, ako s ním zaobchádzať ako s booleovským, ak (this.currentButtons &&! this.previousButtons ) {return true}} else {if (! this.currentButtons && this.previousButtons ) {return true}}} return false} A nakoniec po definovaní triedy pridávame náš registračný kód magického rozšírenia

(funkcia () {

var extensionInstance = new ScratchSimpleGamepad (window.vm.extensionManager.runtime) var serviceName = window.vm.extensionManager._registerInternalExtension (extensionInstance) window.vm.extensionManager._loadedExtensions.set (extensionInstance.getIname ()} id, service)

Úplný kód získate tu.

Krok 7: Použitie rozšírenia, ktoré nie je v karanténe

Použitie rozšírenia, ktoré nie je v karanténe
Použitie rozšírenia, ktoré nie je v karanténe

Ešte raz niekde hostte svoje rozšírenie a tentoraz ho načítajte pomocou argumentu load_plugin = namiesto url = v programe Scepch SheepTester. Napríklad pre môj jednoduchý režim Gamepad navštívte:

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

(Mimochodom, ak chcete sofistikovanejší gamepad, odstráňte z vyššie uvedenej adresy URL „jednoduchý“a budete mať podporu rachotov a analógových osí.)

Rozšírenie by sa opäť malo objaviť na ľavej strane vášho editora Scratch. Hore je veľmi jednoduchý program Scratch, ktorý hovorí „ahoj“, keď stlačíte tlačidlo 0, a „zbohom“, keď ho pustíte.

Krok 8: Dvojitá kompatibilita a rýchlosť

Všimol som si, že rozširujúce bloky bežia rádovo rýchlejšie pomocou metódy načítania, ktorú som použil pre rozšírenia bez schránky. Ak vám teda nezáleží na bezpečnostných výhodách spustenia v karanténe Web Worker, vášmu kódu prospeje načítanie argumentu? Load_plugin = URL do režimu SheepTester.

Rozšírenie v karanténe môžete kompatibilné s oboma spôsobmi načítania pomocou nasledujúceho kódu po definovaní triedy rozšírenia (zmeňte CLASSNAME na názov svojej triedy rozšírení):

(funkcia () {

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

Odporúča: