Πίνακας περιεχομένων:

Επεκτάσεις Scratch 3.0: 8 Βήματα
Επεκτάσεις Scratch 3.0: 8 Βήματα

Βίντεο: Επεκτάσεις Scratch 3.0: 8 Βήματα

Βίντεο: Επεκτάσεις Scratch 3.0: 8 Βήματα
Βίντεο: Πώς να κόψετε τις περικοπές των ανδρών! Πώς να κόψετε ένα μουστάκι και γενειάδα! 2024, Νοέμβριος
Anonim
Επεκτάσεις Scratch 3.0
Επεκτάσεις Scratch 3.0

Οι επεκτάσεις Scratch είναι κομμάτια κώδικα Javascript που προσθέτουν νέα μπλοκ στο Scratch. Ενώ το Scratch συνοδεύεται από μια δέσμη επίσημων επεκτάσεων, δεν υπάρχει επίσημος μηχανισμός για την προσθήκη επεκτάσεων που γίνονται από το χρήστη.

Όταν έκανα την επέκταση ελέγχου Minecraft για το Scratch 3.0, δυσκολεύτηκα να ξεκινήσω. Αυτό το Instructable συλλέγει πληροφορίες από διάφορες πηγές (ειδικά αυτό), καθώς και μερικά πράγματα που ανακάλυψα ο ίδιος.

Πρέπει να γνωρίζετε πώς να προγραμματίζετε σε Javascript και πώς να φιλοξενείτε το Javascript σε έναν ιστότοπο. Για το τελευταίο, προτείνω τις σελίδες GitHub.

Το κύριο κόλπο είναι να χρησιμοποιήσετε τη λειτουργία Scratch του SheepTester που σας επιτρέπει να φορτώσετε επεκτάσεις και προσθήκες.

Αυτό το Instructable θα σας καθοδηγήσει κάνοντας δύο επεκτάσεις:

  • Λήψη: φόρτωση δεδομένων από μια διεύθυνση URL και εξαγωγή ετικετών JSON, για παράδειγμα για τη φόρτωση δεδομένων καιρού
  • SimpleGamepad: χρησιμοποιώντας ένα χειριστήριο παιχνιδιών στο Scratch (μια πιο εξελιγμένη έκδοση είναι εδώ).

Βήμα 1: Δύο τύποι επεκτάσεων

Υπάρχουν δύο τύποι επεκτάσεων τις οποίες θα ονομάσω "unsandboxed" και "sandboxed". Οι επεκτάσεις Sandboxed εκτελούνται ως Web Workers και ως εκ τούτου έχουν σημαντικούς περιορισμούς:

  • Οι εργαζόμενοι στο Διαδίκτυο δεν μπορούν να έχουν πρόσβαση στα παγκόσμια στο αντικείμενο του παραθύρου (αντίθετα, έχουν ένα καθολικό αντικείμενο self, το οποίο είναι πολύ πιο περιορισμένο), οπότε δεν μπορείτε να τα χρησιμοποιήσετε για πράγματα όπως η πρόσβαση στο gamepad.
  • Οι επεκτάσεις Sandboxed δεν έχουν πρόσβαση στο αντικείμενο εκτέλεσης Scratch.
  • Οι επεκτάσεις sandbox είναι πολύ πιο αργές.
  • Τα μηνύματα σφάλματος της κονσόλας Javascript για επεκτάσεις sandbox είναι πιο κρυφά στο Chrome.

Αφ 'ετέρου:

  • Η χρήση επεκτάσεων δοκιμών άλλων ατόμων είναι ασφαλέστερη.
  • Οι επεκτάσεις sandbox είναι πιο πιθανό να λειτουργήσουν με τυχόν επίσημη υποστήριξη φόρτωσης επέκτασης.
  • Οι επεκτάσεις Sandbox μπορούν να δοκιμαστούν χωρίς μεταφόρτωση σε διακομιστή ιστού με κωδικοποίηση σε δεδομένα: // URL.

Οι επίσημες επεκτάσεις (όπως η Μουσική, το Pen, κ.λπ.) είναι όλες χωρίς αποθήκευση. Ο κατασκευαστής για την επέκταση λαμβάνει το αντικείμενο εκτέλεσης από το Scratch και το παράθυρο είναι πλήρως προσβάσιμο.

Η επέκταση Fetch είναι δοκιμασμένη, αλλά το Gamepad χρειάζεται το αντικείμενο πλοήγησης από το παράθυρο.

Βήμα 2: Γράφοντας μια επέκταση Sandboxed: Μέρος I

Για να δημιουργήσετε μια επέκταση, δημιουργείτε μια κλάση που κωδικοποιεί πληροφορίες σχετικά με αυτήν και, στη συνέχεια, προσθέτετε ένα κομμάτι κώδικα για να καταχωρίσετε την επέκταση.

Το κύριο πράγμα στην κλάση επέκτασης είναι μια μέθοδος getInfo () που επιστρέφει ένα αντικείμενο με τα απαιτούμενα πεδία:

  • id: το εσωτερικό όνομα της επέκτασης, πρέπει να είναι μοναδικό για κάθε επέκταση
  • όνομα: το φιλικό όνομα της επέκτασης, που εμφανίζεται στη λίστα μπλοκ του Scratch
  • μπλοκ: μια λίστα αντικειμένων που περιγράφουν το νέο προσαρμοσμένο μπλοκ.

Και υπάρχει ένα προαιρετικό πεδίο μενού που δεν χρησιμοποιείται στο Fetch αλλά θα χρησιμοποιηθεί στο Gamepad.

Λοιπόν, εδώ είναι το βασικό πρότυπο για την Ανάκτηση:

class ScratchFetch {

constructor () {} getInfo () {return {"id": "Ανάκτηση", "όνομα": "Ανάκτηση", "αποκλεισμοί": [/* προσθήκη αργότερα * /]}} / * προσθήκη μεθόδων για μπλοκ * /} Scratch.extensions.register (νέο ScratchFetch ())

Βήμα 3: Γράφοντας μια επέκταση Sandboxed: Μέρος II

Τώρα, πρέπει να δημιουργήσουμε τη λίστα μπλοκ στο αντικείμενο του getInfo (). Κάθε μπλοκ χρειάζεται τουλάχιστον αυτά τα τέσσερα πεδία:

  • opcode: αυτό είναι το όνομα της μεθόδου που καλείται να κάνει τη δουλειά του μπλοκ
  • blockType: αυτός είναι ο τύπος μπλοκ. τα πιο συνηθισμένα για επεκτάσεις είναι:

    • "εντολή": κάνει κάτι αλλά δεν επιστρέφει μια τιμή
    • "ρεπόρτερ": επιστρέφει μια συμβολοσειρά ή έναν αριθμό
    • "Boolean": επιστρέφει ένα boolean (σημειώστε την κεφαλαιοποίηση)
    • "καπέλο": μπλοκ σύλληψης συμβάντων. εάν ο κωδικός Scratch χρησιμοποιεί αυτό το μπλοκ, ο χρόνος εκτέλεσης του Scratch διερευνά τακτικά τη σχετική μέθοδο η οποία επιστρέφει ένα boolean για να πει εάν έχει συμβεί το συμβάν
  • κείμενο: αυτή είναι μια φιλική περιγραφή του μπλοκ, με τα ορίσματα σε αγκύλες, π.χ. "ανάκτηση δεδομένων από "
  • ορίσματα: αυτό είναι ένα αντικείμενο που έχει ένα πεδίο για κάθε όρισμα (π.χ. "url" στο παραπάνω παράδειγμα). αυτό το αντικείμενο με τη σειρά του έχει αυτά τα πεδία:

    • τύπος: είτε "συμβολοσειρά" είτε "αριθμός"
    • defaultValue: η προεπιλεγμένη τιμή που πρέπει να συμπληρωθεί εκ των προτέρων.

Για παράδειγμα, εδώ είναι το πεδίο μπλοκ στην επέκταση Λήψη μου:

"μπλοκ": [{"opcode": "fetchURL", "blockType": "reporter", "text": "fetch data from ", "argumentments": {"url": {"type": "string", "defaultValue ":" https://api.weather.gov/stations/KNYC/observations "},}}, {" opcode ":" jsonExtract "," blockType ":" reporter "," text ":" extract [name] από [data] "," argument ": {" name ": {" type ":" string "," defaultValue ":" temperature "}," data ": {" type ":" string "," defaultValue ": '{"θερμοκρασία": 12.3}'},}},]

Εδώ, ορίσαμε δύο μπλοκ: fetchURL και jsonExtract. Και οι δύο είναι δημοσιογράφοι. Το πρώτο τραβάει δεδομένα από μια διεύθυνση URL και τα επιστρέφει και το δεύτερο εξάγει ένα πεδίο από δεδομένα JSON.

Τέλος, πρέπει να συμπεριλάβετε τις μεθόδους για δύο μπλοκ. Κάθε μέθοδος λαμβάνει ένα αντικείμενο ως όρισμα, με το αντικείμενο να περιλαμβάνει πεδία για όλα τα ορίσματα. Μπορείτε να τα αποκωδικοποιήσετε χρησιμοποιώντας σγουρά στηρίγματα στα ορίσματα. Για παράδειγμα, εδώ είναι ένα σύγχρονο παράδειγμα:

jsonExtract ({όνομα, δεδομένα}) {

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") επιστροφή t; 1: 0 επιστροφή JSON.stringify (out)} else {return ""}}

Ο κώδικας τραβά το πεδίο ονόματος από τα δεδομένα JSON. Εάν το πεδίο περιέχει μια συμβολοσειρά, έναν αριθμό ή ένα boolean, το επιστρέφουμε. Διαφορετικά, κάνουμε εκ νέου JSONify το πεδίο. Και επιστρέφουμε μια κενή συμβολοσειρά εάν το όνομα λείπει από το JSON.

Μερικές φορές, ωστόσο, μπορεί να θέλετε να δημιουργήσετε ένα μπλοκ που χρησιμοποιεί ένα ασύγχρονο API. Η μέθοδος fetchURL () χρησιμοποιεί το API ανάκτησης το οποίο είναι ασύγχρονο. Σε μια τέτοια περίπτωση, θα πρέπει να επιστρέψετε μια υπόσχεση από τη μέθοδό σας που κάνει τη δουλειά. Για παράδειγμα:

fetchURL ({url}) {

επιστροφή ανάκτηση (url).then (reply => respond.text ())}

Αυτό είναι. Η πλήρης επέκταση είναι εδώ.

Βήμα 4: Χρήση επέκτασης Sandboxed

Χρήση επέκτασης Sandboxed
Χρήση επέκτασης Sandboxed
Χρήση επέκτασης Sandboxed
Χρήση επέκτασης Sandboxed
Χρήση επέκτασης Sandboxed
Χρήση επέκτασης Sandboxed

Υπάρχουν δύο τρόποι χρήσης της επέκτασης sandboxed. Αρχικά, μπορείτε να το ανεβάσετε σε έναν διακομιστή ιστού και, στη συνέχεια, να το φορτώσετε στο Scetch mod του SheepTester. Δεύτερον, μπορείτε να το κωδικοποιήσετε σε μια διεύθυνση URL δεδομένων και να το φορτώσετε στο mod Scratch. Στην πραγματικότητα χρησιμοποιώ αρκετά τη δεύτερη μέθοδο για δοκιμή, καθώς αποφεύγει τις ανησυχίες για παλαιότερες εκδόσεις της επέκτασης που αποθηκεύονται προσωρινά στον διακομιστή. Λάβετε υπόψη ότι ενώ μπορείτε να φιλοξενήσετε javascript από τις σελίδες Github, δεν μπορείτε να το κάνετε απευθείας από ένα συνηθισμένο αποθετήριο github.

Το fetch.js φιλοξενείται στη διεύθυνση https://arpruss.github.io/fetch.js. Or μπορείτε να μετατρέψετε την επέκτασή σας σε μια διεύθυνση URL μεταφορτώνοντάς την εδώ και στη συνέχεια να την αντιγράψετε στο πρόχειρο. Ένα URL δεδομένων είναι ένα γιγαντιαίο URL που περιέχει ένα ολόκληρο αρχείο σε αυτό.

Μεταβείτε στο mod Scratch του SheepTester. Κάντε κλικ στο κουμπί Προσθήκη επέκτασης στην κάτω αριστερή γωνία. Στη συνέχεια, κάντε κλικ στο "Επιλογή επέκτασης" και εισαγάγετε τη διεύθυνση URL (μπορείτε να επικολλήσετε ολόκληρη τη γιγαντιαία διεύθυνση URL δεδομένων, αν θέλετε).

Εάν όλα πήγαν καλά, θα έχετε μια καταχώριση για την επέκτασή σας στην αριστερή πλευρά της οθόνης Scratch. Εάν τα πράγματα δεν πήγαν καλά, θα πρέπει να ανοίξετε την κονσόλα Javascript (shift-ctrl-J στο Chrome) και να προσπαθήσετε να διορθώσετε το πρόβλημα.

Πάνω θα βρείτε κάποιο παράδειγμα κώδικα που συλλέγει και αναλύει δεδομένα JSON από το σταθμό KNYC (στη Νέα Υόρκη) της Εθνικής Μετεωρολογικής Υπηρεσίας των ΗΠΑ και τον εμφανίζει, ενώ γυρίζει το σπράιτ προς την ίδια όψη που φυσάει ο άνεμος. Ο τρόπος που το έφτιαξα ήταν η ανάκτηση των δεδομένων σε ένα πρόγραμμα περιήγησης ιστού και στη συνέχεια η εύρεση των ετικετών. Εάν θέλετε να δοκιμάσετε έναν διαφορετικό μετεωρολογικό σταθμό, εισαγάγετε έναν κοντινό ταχυδρομικό κώδικα στο πλαίσιο αναζήτησης στο weather.gov και η σελίδα καιρού για την τοποθεσία σας θα σας δώσει έναν κωδικό σταθμού τεσσάρων γραμμάτων, τον οποίο μπορείτε να χρησιμοποιήσετε στη θέση του KNYC στο κώδικας.

Μπορείτε επίσης να συμπεριλάβετε την επέκτασή σας στο πλαίσιο δοκιμών στη διεύθυνση URL για τη λειτουργία του SheepTester προσθέτοντας ένα επιχείρημα "? Url =". Για παράδειγμα:

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

Βήμα 5: Γράψιμο μιας επέκτασης χωρίς αποθήκευση: Εισαγωγή

Ο κατασκευαστής μιας επέκτασης χωρίς αποθήκευση περνά ένα αντικείμενο Runtime. Μπορείτε να το αγνοήσετε ή να το χρησιμοποιήσετε. Μια χρήση του αντικειμένου Runtime είναι η χρήση της ιδιότητας currentMSecs για συγχρονισμό συμβάντων ("μπλοκ καπέλων"). Από όσο μπορώ να πω, όλοι οι κωδικοί μπλοκ συμβάντων διεξάγονται τακτικά δημοψήφισμα και κάθε γύρος της ψηφοφορίας έχει μια μοναδική τιμή currentMSecs. Εάν χρειάζεστε το αντικείμενο Runtime, πιθανότατα θα ξεκινήσετε την επέκτασή σας με:

τάξη EXTENSIONCLASS {

κατασκευαστής (χρόνος εκτέλεσης) {this.runtime = χρόνος εκτέλεσης…}…}

Όλα τα τυπικά αντικείμενα αντικειμένου παραθύρου μπορούν να χρησιμοποιηθούν στην επέκταση χωρίς αποθήκευση. Τέλος, η επέκτασή σας χωρίς αποθήκευση πρέπει να τελειώσει με αυτό το κομμάτι μαγικού κώδικα:

(λειτουργία() {

var extensionInstance = new EXTENSIONCLASS (window.vm.extensionManager.runtime) var serviceName = window.vm.extensionManager._registerInternalExtension (extensionInstance) window.vm.extensionManager._loadedExtensions.set (extensionInstance.get, serviceInfo ())

όπου πρέπει να αντικαταστήσετε το EXTENSIONCLASS με την κλάση της επέκτασής σας.

Βήμα 6: Γράψιμο μιας επέκτασης χωρίς αποθήκευση: Απλό Gamepad

Ας κάνουμε τώρα μια απλή επέκταση gamepad που παρέχει ένα αποκλειστικό μπλοκ συμβάντων ("καπέλο") όταν πατάτε ή αφήνετε ένα κουμπί.

Κατά τη διάρκεια κάθε κύκλου ψηφοφορίας αποκλεισμού συμβάντων, θα αποθηκεύσουμε μια χρονική σήμανση από το αντικείμενο εκτέλεσης και τις προηγούμενες και τρέχουσες καταστάσεις του gamepad. Η χρονική σήμανση χρησιμοποιείται για την αναγνώριση εάν έχουμε νέο κύκλο ψηφοφορίας. Ξεκινάμε λοιπόν με:

κλάση ScratchSimpleGamepad {

κατασκευαστής (χρόνος εκτέλεσης) {this.runtime = χρόνος εκτέλεσης this.currentMSecs = -1 this.previousButtons = this.currentButtons = }…} Θα έχουμε ένα μπλοκ συμβάντων, με δύο εισόδους-έναν αριθμό κουμπιού και ένα μενού για να επιλέξουμε αν θέλουμε να ενεργοποιηθεί το συμβάν κατά το πάτημα ή την απελευθέρωση. Λοιπόν, εδώ είναι η μέθοδος μας

Πάρτε πληροφορίες() {

return {"id": "SimpleGamepad", "name": "SimpleGamepad", "blocks": [{"opcode": "buttonPressedReleased", "blockType": "hat", "text": "κουμπί [eventType] "," argument ": {" b ": {" type ":" number "," defaultValue ":" 0 "}," eventType ": {" type ":" number "," defaultValue ":" 1 "," menu ":" pressReleaseMenu "},},},]," μενού ": {" pressReleaseMenu ": [{text:" press ", value: 1}, {text:" release ", value: 0}],}}; } Νομίζω ότι οι τιμές στο αναπτυσσόμενο μενού εξακολουθούν να περνούν στη λειτουργία opcode ως συμβολοσειρές, παρά το γεγονός ότι δηλώνονται ως αριθμοί. Έτσι, συγκρίνετε τα ρητά με τις τιμές που καθορίζονται στο μενού, όπως απαιτείται. Γράφουμε τώρα μια μέθοδο που ενημερώνει τις καταστάσεις του κουμπιού κάθε φορά που συμβαίνει ένας νέος κύκλος ψηφοφορίας συμβάντων

ενημέρωση () {

if (this.runtime.currentMSecs == this.currentMSecs) return // όχι νέος κύκλος δημοσκοπήσεων 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) { // διαφορετικός αριθμός κουμπιών, τόσο νέο gamepad this.previousButtons = για (var i = 0; i <gamepad.buttons.length; i ++) this.preciousButtons.push (false)} αλλιώς {this.previousButtons = this currentButtons} this.currentButtons = για (var i = 0; i <gamepad.buttons.length; i ++) this.currentButtons.push (gamepad.buttons .pressed)}} Τέλος, μπορούμε να εφαρμόσουμε το μπλοκ συμβάντων μας, καλώντας τη μέθοδο ενημέρωσης () και στη συνέχεια ελέγχοντας εάν το απαραίτητο κουμπί μόλις έχει πατηθεί ή απελευθερωθεί, συγκρίνοντας την τρέχουσα και την προηγούμενη κατάσταση κουμπιών

buttonPressedReleased ({b, eventType}) {

this.update () if (b <this.currentButtons.length) {if (eventType == 1) {// σημ. this.currentButtons &&! this.previousButtons ) {return true}} else {if (! this.currentButtons && this.previousButtons ) {return true}}} επιστροφή false} Και τέλος προσθέτουμε τον μαγικό κωδικό εγγραφής επέκτασης αφού ορίσουμε την τάξη

(λειτουργία() {

var extensionInstance = νέο ScratchSimpleGamepad (window.vm.extensionManager.runtime) var serviceName = window.vm.extensionManager._registerInternalExtension (extensionInstance) window.vm.extensionManager._loadedExtensions.set (extensionInstance.get) service (info))

Μπορείτε να λάβετε τον πλήρη κωδικό εδώ.

Βήμα 7: Χρήση μιας επέκτασης χωρίς πλαίσιο

Χρήση μιας επέκτασης χωρίς αποθήκευση
Χρήση μιας επέκτασης χωρίς αποθήκευση

Για άλλη μια φορά, φιλοξενήστε κάπου την επέκτασή σας και αυτή τη φορά φορτώστε την με το load_plugin = αντί για το url = όρισμα στο SheepTester's Scratch mod. Για παράδειγμα, για το απλό mod Gamepad, μεταβείτε στη διεύθυνση:

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

(Παρεμπιπτόντως, αν θέλετε ένα πιο εξελιγμένο gamepad, απλώς αφαιρέστε το "απλό" από το παραπάνω URL και θα έχετε υποστήριξη αναβολής και αναλογικού άξονα.)

Και πάλι, η επέκταση θα πρέπει να εμφανίζεται στην αριστερή πλευρά του προγράμματος επεξεργασίας Scratch. Πάνω υπάρχει ένα πολύ απλό πρόγραμμα Scratch που λέει "γεια" όταν πατάτε το κουμπί 0 και "αντίο" όταν το αφήνετε.

Βήμα 8: Διπλή συμβατότητα και ταχύτητα

Παρατήρησα ότι τα μπλοκ επέκτασης εκτελούν μια τάξη μεγέθους γρηγορότερα χρησιμοποιώντας τη μέθοδο φόρτωσης που χρησιμοποίησα για επεκτάσεις χωρίς αποθήκευση. Επομένως, εκτός εάν ενδιαφέρεστε για τα οφέλη ασφάλειας της εκτέλεσης σε ένα sandbox του Web Worker, ο κωδικός σας θα επωφεληθεί από τη φόρτωση του ορίσματος? Load_plugin = URL στη λειτουργία SheepTester.

Μπορείτε να κάνετε μια επέκταση sandbox που να είναι συμβατή και με τις δύο μεθόδους φόρτωσης, χρησιμοποιώντας τον ακόλουθο κώδικα μετά τον ορισμό της κλάσης επέκτασης (αλλάξτε CLASSNAME στο όνομα της κλάσης επέκτασής σας):

(λειτουργία() {

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

Συνιστάται: