תוכן עניינים:

הרחבות Scratch 3.0: 8 שלבים
הרחבות Scratch 3.0: 8 שלבים

וִידֵאוֹ: הרחבות Scratch 3.0: 8 שלבים

וִידֵאוֹ: הרחבות Scratch 3.0: 8 שלבים
וִידֵאוֹ: MEGA Chia GPU Farming and Plotting Guide for Linux - Gigahorse Start to Finish - 2023 2024, יולי
Anonim
הרחבות Scratch 3.0
הרחבות Scratch 3.0

הרחבות שריטה הן חלקים של קוד Javascript שמוסיפים בלוקים חדשים ל- Scratch. למרות שסקראץ 'מצורף לחבורה של תוספים רשמיים, אין מנגנון רשמי להוספת הרחבות תוצרת משתמש.

כשעשיתי את תוסף השליטה שלי ב- Minecraft עבור Scratch 3.0, התקשיתי להתחיל. הוראה זו אוספת יחד מידע ממקורות שונים (במיוחד זה), בתוספת כמה דברים שגיליתי בעצמי.

עליך לדעת כיצד לתכנת ב- Javascript וכיצד לארח את ה- Javascript שלך באתר אינטרנט. עבור האחרון, אני ממליץ על דפי GitHub.

הטריק העיקרי הוא להשתמש במוד Scratch של SheepTester המאפשר לך לטעון הרחבות ותוספים.

מדריך זה ינחה אותך ביצירת שני הרחבות:

  • אחזור: טעינת נתונים מכתובת אתר וחילוץ תגי JSON, למשל לטעינת נתוני מזג אוויר
  • SimpleGamepad: שימוש בבקר משחק ב- Scratch (גרסה מתוחכמת יותר נמצאת כאן).

שלב 1: שני סוגי הרחבות

ישנם שני סוגים של הרחבות שאקרא להם "ללא ארגז" ו"ארגז חול ". תוספי ארגז חול פועלים כעובדי אינטרנט, וכתוצאה מכך יש להם מגבלות משמעותיות:

  • עובדי אינטרנט אינם יכולים לגשת לגלובוסים באובייקט החלון (במקום זאת, יש להם אובייקט עצמי גלובלי, שהוא הרבה יותר מוגבל), כך שלא תוכל להשתמש בהם לדברים כמו גישה למשחקי Gamepad.
  • לתוספים בארגז חול אין גישה לאובייקט זמן הריצה של Scratch.
  • הרחבות בארגז חול איטיות בהרבה.
  • הודעות השגיאה של מסוף Javascript עבור תוספי ארגז חול הם יותר קריפטיים ב- Chrome.

מצד שני:

  • שימוש בטוח יותר בארכיונות חול של אנשים אחרים.
  • סביר יותר שתוספים בארגז חול יעבדו עם כל תמיכה רשמית של טעינת תוספים רשמיים.
  • ניתן לבדוק הרחבות בארגז חול ללא העלאה לשרת אינטרנט על ידי קידוד לנתונים: // URL.

התוספים הרשמיים (כגון המוזיקה, העט וכו ') כולם ללא ארגז. בונה ההרחבה מקבל את אובייקט זמן הריצה מ- Scratch והחלון נגיש במלואו.

התוסף Fetch הוא ארגז חול, אך Gamepad צריך את אובייקט הניווט מהחלון.

שלב 2: כתיבת הרחבה בארגז חול: חלק א '

כדי ליצור הרחבה, אתה יוצר מחלקה המקודדת מידע עליה ולאחר מכן מוסיפה מעט קוד לרישום התוסף.

הדבר העיקרי במחלקת הסיומות הוא שיטת getInfo () שמחזירה אובייקט עם השדות הנדרשים:

  • id: השם הפנימי של התוסף חייב להיות ייחודי לכל הרחבה
  • name: השם הידידותי של התוסף, שמופיע ברשימת הבלוקים של Scratch
  • בלוקים: רשימה של אובייקטים המתארים את הבלוק המותאם אישית החדש.

ויש שדה תפריטים אופציונלי שאינו מתרגל ב- Fetch אך ישמש ב- Gamepad.

אז הנה התבנית הבסיסית של Fetch:

class ScratchFetch {

קונסטרוקטור () {} getInfo () {return {"id": "אחזור", "שם": "אחזור", "בלוקים": [/* הוסף מאוחר יותר * /]}} / * הוסף שיטות לחסימות * /} Scratch.extensions.register (חדש ScratchFetch ())

שלב 3: כתיבת הרחבה בארגז חול: חלק ב '

כעת עלינו ליצור את רשימת הבלוקים באובייקט של getInfo (). כל בלוק צריך לפחות את ארבעת השדות הבאים:

  • opcode: זהו שם השיטה שנקראת לבצע את עבודת הבלוק
  • blockType: זהו סוג הבלוק; הנפוצים ביותר להרחבות הם:

    • "פקודה": עושה משהו אבל לא מחזיר ערך
    • "כתב": מחזיר מחרוזת או מספר
    • "בוליאני": מחזיר בוליאני (שימו לב לאותיות רישיות)
    • "כובע": בלוק תופס אירוע; אם קוד ה- Scratch שלך משתמש בבלוק זה, זמן הריצה של Scratch סוקר באופן קבוע את השיטה המשויכת המחזירה בוליאני כדי לומר אם האירוע קרה
  • טקסט: זהו תיאור ידידותי של הבלוק, עם הארגומנטים בסוגריים, למשל, "אחזר נתונים מ "
  • ארגומנטים: זהו אובייקט בעל שדה עבור כל ארגומנט (למשל, "כתובת אתר" בדוגמה שלמעלה); לאובייקט זה בתורו יש שדות אלה:

    • סוג: או "מחרוזת" או "מספר"
    • defaultValue: ערך ברירת המחדל שיש למלא מראש.

לדוגמה, להלן שדה הבלוקים בהרחבה שלי אחזור:

"בלוקים": [{"opcode": "fetchURL", "blockType": "reporter", "text": "אחזר נתונים מ- ", "ארגומנטים": {"url": {"type": "string", "defaultValue ":" https://api.weather.gov/stations/KNYC/observations "},}}, {" opcode ":" jsonExtract "," blockType ":" reporter "," text ":" extract [name] מ [data] "," ארגומנטים ": {" name ": {" type ":" string "," defaultValue ":" temperature "}," data ": {" type ":" string "," defaultValue ": '{"טמפרטורה": 12.3}'},}},]

כאן הגדרנו שני בלוקים: fetchURL ו- jsonExtract. שניהם כתבים. הראשון שולף נתונים מכתובת אתר ומחזיר אותם, והשני מחלץ שדה מנתוני 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 if if (t == "בוליאני") להחזיר t? 1: 0 החזר JSON.stringify (החוצה)} אחר {החזר ""}}

הקוד שואב את שדה השם מנתוני JSON. אם השדה מכיל מחרוזת, מספר או בוליאני, אנו מחזירים זאת. אחרת, אנו מחדש את JSONify השדה. ואנו מחזירים מחרוזת ריקה אם השם חסר ב- JSON.

אולם לפעמים ייתכן שתרצה ליצור בלוק המשתמש בממשק API אסינכרוני. שיטת fetchURL () משתמשת ב- API אחזור שהוא אסינכרוני. במקרה כזה, עליך להחזיר הבטחה מהשיטה שלך שעושה את העבודה. לדוגמה:

fetchURL ({url}) {

החזר אחזור (url). ואז (response => response.text ())}

זהו זה. ההרחבה המלאה כאן.

שלב 4: שימוש בתוסף ארגז חול

שימוש בתוסף ארגז חול
שימוש בתוסף ארגז חול
שימוש בתוסף ארגז חול
שימוש בתוסף ארגז חול
שימוש בתוסף ארגז חול
שימוש בתוסף ארגז חול

ישנן שתי דרכים לשימוש בתוסף ארגז חול. ראשית, תוכל להעלות אותו לשרת אינטרנט ולאחר מכן לטעון אותו למוד Scratch של SheepTester. שנית, אתה יכול לקודד אותו לתוך כתובת URL של נתונים, ולהעלות אותו למוד Scratch. אני בעצם משתמש בשיטה השנייה לא מעט לבדיקה, מכיוון שהיא מונעת דאגות בנוגע לגירסאות ישנות יותר של התוסף שהמטמון יימצא במטמון על ידי השרת. שים לב שבעוד שאתה יכול לארח javascript מדפי Github, אינך יכול לעשות זאת ישירות ממאגר github רגיל.

ה- fetch.js שלי מתארח בכתובת https://arpruss.github.io/fetch.js. או שתוכל להמיר את התוסף שלך לכתובת אתר נתונים על ידי העלאתו לכאן ולאחר מכן העתק אותו ללוח. כתובת אתר נתונים היא כתובת אתר ענקית המכילה בתוכה קובץ שלם.

עבור למוד Scratch של SheepTester. לחץ על הלחצן הוסף תוסף בפינה השמאלית התחתונה. לאחר מכן לחץ על "בחר תוסף" והזן את כתובת האתר שלך (תוכל להדביק את כל כתובת האתר הענקית אם תרצה).

אם הכל הלך כשורה, תהיה לך ערך להרחבה בצד שמאל של מסך ה- Scratch. אם הדברים לא הלכו טוב, עליך לפתוח את מסוף ה- Javascript שלך (shift-ctrl-J ב- Chrome) ולנסות לאתר את הבעיה.

למעלה תמצא קוד דוגמה שאוסף ונתח נתוני JSON מתחנת KNYC (בניו יורק) של שירות מזג האוויר הלאומי בארה ב, ומציג אותם, תוך הפניית הספרייט לאותה הדרך שבה הרוח נושבת. הדרך בה עשיתי זאת הייתה על ידי שליפת הנתונים לדפדפן אינטרנט ולאחר מכן הבנת התגים. אם אתה רוצה לנסות תחנת מזג אוויר אחרת, הזן מיקוד סמוך לתיבת החיפוש בכתובת weather.gov, ודף מזג האוויר של המיקום שלך אמור לתת לך קוד תחנה בן ארבע אותיות, שבו תוכל להשתמש במקום KNYC ב קוד.

תוכל גם לכלול את התוסף שלך בארגז חול ישירות בכתובת האתר של mod של SheepTester על ידי הוספת ארגומנט "? Url =". לדוגמה:

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

שלב 5: כתיבת תוסף לא מוכר: מבוא

הבונה של סיומת שאינה נשלחת במארז מועבר אובייקט Runtime. אתה יכול להתעלם מזה או להשתמש בו. שימוש אחד באובייקט Runtime הוא שימוש במאפיין currentMSecs שלו לסנכרן אירועים ("חסימות כובע"). למיטב ידיעתי, כל קוד האופק של בלוק האירועים נסקרים באופן קבוע, ולכל סיבוב בסקר יש ערך יחיד MSECs הנוכחי. אם אתה זקוק לאובייקט Runtime, סביר להניח שתתחיל את הסיומת שלך עם:

class EXTENSIONCLASS {

קונסטרוקטור (זמן ריצה) {this.runtime = זמן ריצה …}…}

ניתן להשתמש בכל החפצים הסטנדרטיים של אובייקט החלון בהרחבה ללא ארגז. לבסוף, התוסף הבלתי -ארגזי שלך אמור להסתיים בקוד הקסם הזה:

(פונקציה () {

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

היכן עליך להחליף את EXTENSIONCLASS בכיתה של התוסף שלך.

שלב 6: כתיבת הרחבה שאינה נשלחת בארגז: Gamepad פשוט

בואו נכין כעת הרחבת gamepad פשוטה המספקת בלוק אירוע יחיד ("כובע") בעת לחיצה או שחרור כפתור.

במהלך כל מחזור סקר של חסימת אירועים, נשמור חותמת זמן מהאובייקט זמן הריצה וממצבי לוח המשחקים הקודם והנוכחי. חותמת הזמן משמשת לזיהוי אם יש לנו מחזור סקרים חדש. אז נתחיל עם:

class ScratchSimpleGamepad {

קונסטרוקטור (זמן ריצה) {this.runtime = 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 ", ערך: 0}],}}; } אני חושב שהערכים בתפריט הנפתח עדיין מועברים לפונקציית האופוד כמחרוזות, למרות שהוכרזו כמספרים. אז השווה אותם במפורש מול הערכים המצוינים בתפריט לפי הצורך. כעת אנו כותבים שיטה המעדכנת את מצבי הכפתורים בכל פעם שמתרחש מחזור סקר אירועים חדש

עדכון() {

אם (this.runtime.currentMSecs == this.currentMSecs) מחזירה // לא מחזור סקר חדש 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.previousButtons.push (false)} else {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) {// הערה: זו תהיה מחרוזת, לכן עדיף להשוות אותה ל- 1 מאשר להתייחס אליה כאל בוליאני אם (this.currentButtons &&! this.previousButtons ) {return true}} else {if (! this.currentButtons && this.previousButtons ) {return true}}} return false} ולבסוף אנו מוסיפים את קוד ההרשמה להרחבת הקסם שלנו לאחר הגדרת המעמד

(פונקציה () {

var extensionInstance = ScratchSimpleGamepad חדש (window.vm.extensionManager.runtime) var serviceName = window.vm.extensionManager._registerInternalExtension (extensionInstance) window.vm.extensionManager._loadedExtensions.set (extensionInstance.getInfo ()} id, service))

תוכל לקבל את הקוד המלא כאן.

שלב 7: שימוש בהרחבה ללא ארגז

שימוש בתוסף ללא ארגז
שימוש בתוסף ללא ארגז

שוב, אירח את הסיומת שלך איפשהו, והפעם טען אותה עם הטענת load_plugin = ולא url = ל- Scratch mod של SheepTester. לדוגמה, עבור mod gamepad הפשוט שלי, עבור אל:

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

(אגב, אם אתה רוצה משחקי משחק מתוחכמים יותר, פשוט הסר את ה"פשוט "מכתובת האתר שלמעלה, ותקבל תמיכה של רעש וציר אנלוגי.)

שוב, הסיומת אמורה להופיע בצד שמאל של עורך ה- Scratch שלך. למעלה תוכנת Scratch פשוטה מאוד שאומרת "שלום" כאשר אתה לוחץ על כפתור 0 ועל "להתראות" כאשר אתה משחרר אותו.

שלב 8: תאימות כפולה ומהירות

שמתי לב שבלוקי הרחבה פועלים בסדר גודל מהיר יותר בשיטת הטעינה בה השתמשתי עבור תוספים שאינם נרכזים. אז אלא אם כן אכפת לך מיתרונות האבטחה של הפעלה בארגז חול של Worker Web, הקוד שלך ירוויח מטעינת הארגומנט? Load_plugin = URL למוד של SheepTester.

אתה יכול להפוך תוסף ארגז חול תואם לשתי שיטות הטעינה על ידי שימוש בקוד הבא לאחר הגדרת מחלקת הסיומות (שנה את 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)}}) ()

מוּמלָץ: