فهرست مطالب:

برنامه های افزودنی Scratch 3.0: 8 مرحله
برنامه های افزودنی Scratch 3.0: 8 مرحله

تصویری: برنامه های افزودنی Scratch 3.0: 8 مرحله

تصویری: برنامه های افزودنی Scratch 3.0: 8 مرحله
تصویری: آموزش اسکرچ - جلسه 16 - مرور جلسات و تکمیل دستور غذا با اسکرچ 2024, نوامبر
Anonim
افزونه های Scratch 3.0
افزونه های Scratch 3.0

برنامه های افزودنی Scratch قطعاتی از کد جاوا اسکریپت هستند که بلوک های جدیدی به Scratch اضافه می کنند. در حالی که Scratch با مجموعه ای از برنامه های افزودنی رسمی همراه است ، مکانیسم رسمی برای افزودن برنامه های افزودنی ساخته شده توسط کاربر وجود ندارد.

هنگامی که در حال ساخت افزونه Minecraft خود برای کنترل Scratch 3.0 بودم ، شروع به کار برایم مشکل بود. این دستورالعمل اطلاعات را از منابع مختلف (به ویژه این) جمع آوری می کند ، به علاوه چند مورد که من خودم کشف کردم.

شما باید نحوه برنامه نویسی در Javascript و نحوه میزبانی Javascript خود در وب سایت را بدانید. برای مورد دوم ، GitHub Pages را توصیه می کنم.

ترفند اصلی استفاده از حالت Scratch SheepTester است که به شما امکان می دهد افزونه ها و افزونه ها را بارگیری کنید.

این دستورالعمل شما را در ساخت دو برنامه افزودنی راهنمایی می کند:

  • واکشی: بارگیری داده ها از URL و استخراج برچسب های JSON ، برای مثال برای بارگیری داده های آب و هوا
  • SimpleGamepad: استفاده از کنترلر بازی در Scratch (نسخه پیچیده تری در اینجا وجود دارد).

مرحله 1: دو نوع افزونه

دو نوع افزونه وجود دارد که من آنها را "unsandboxed" و "sandboxed" می نامم. افزونه های Sandboxed به عنوان Web Workers اجرا می شوند و در نتیجه دارای محدودیت های قابل توجهی هستند:

  • وب کارگران نمی توانند به سراسری در شیء پنجره دسترسی داشته باشند (در عوض ، آنها دارای یک شیء خودی جهانی هستند که بسیار محدودتر است) ، بنابراین نمی توانید از آنها برای مواردی مانند دسترسی به گیم پد استفاده کنید.
  • افزونه های سندباکس به شیء اجرای Scratch دسترسی ندارند.
  • افزونه های سندباکس بسیار کندتر عمل می کنند.
  • پیام های خطای کنسول جاوا اسکریپت برای افزونه های سندباکس در Chrome بیشتر رمزنگار هستند.

از سوی دیگر:

  • استفاده از برنامه های افزودنی جعبه سند دیگران ایمن تر است.
  • افزونه های سندباکس به احتمال زیاد با هرگونه پشتیبانی رسمی بارگیری برنامه افزودنی کار می کنند.
  • افزونه های سندباکس را می توان بدون بارگذاری در سرور وب با کدگذاری در داده ها: // URL آزمایش کرد.

برنامه های افزودنی رسمی (مانند موسیقی ، قلم و غیره) همه بدون جعبه هستند. سازنده افزونه ، زمان اجرا را از Scratch دریافت می کند و پنجره کاملاً در دسترس است.

افزونه Fetch در جعبه سند قرار دارد ، اما Gamepad یکی از پنجره به شیء ناوبری نیاز دارد.

مرحله 2: نوشتن افزونه Sandboxed: قسمت اول

برای ایجاد یک برنامه افزودنی ، یک کلاس ایجاد می کنید که اطلاعات مربوط به آن را رمزگذاری می کند ، و سپس کمی کد برای ثبت برنامه افزودنی اضافه می کنید.

نکته اصلی در کلاس افزونه یک متد () getInfo است که یک شی را با فیلدهای مورد نیاز برمی گرداند:

  • id: نام داخلی برنامه افزودنی ، باید برای هر افزونه منحصر به فرد باشد
  • name: نام دوستانه افزونه ، در لیست بلوک های Scratch نشان داده می شود
  • بلوک ها: لیستی از اشیاء است که بلوک سفارشی جدید را توصیف می کند.

و یک زمینه منوها اختیاری وجود دارد که در Fetch استفاده نمی شود اما در Gamepad استفاده می شود.

بنابراین ، در اینجا قالب اصلی برای واکشی است:

کلاس ScratchFetch {

constructor () {} getInfo () {return {"id": "Fetch"، "name": "Fetch"، "blocks": [/* بعداً اضافه کنید * /]}} / * افزودن روش برای بلوک * /} Scratch.extensions.register (جدید ScratchFetch ())

مرحله 3: نوشتن افزونه Sandboxed: قسمت دوم

حال ، ما باید لیستی از بلوک ها را در شیء getInfo () ایجاد کنیم. هر بلوک حداقل به این چهار فیلد نیاز دارد:

  • opcode: این نام متدی است که برای انجام کار بلاک فراخوانی می شود
  • blockType: این نوع بلوک است. رایج ترین آنها برای برنامه های افزودنی عبارتند از:

    • "command": کاری انجام می دهد اما مقدار را بر نمی گرداند
    • "reporter": یک رشته یا شماره را برمی گرداند
    • "بولی": یک بول را برمی گرداند (به حروف بزرگ توجه کنید)
    • "کلاه": بلوک گرفتن رویداد ؛ اگر کد Scratch شما از این بلوک استفاده می کند ، زمان اجرای Scratch به طور منظم از روش مربوطه نظرسنجی می کند که یک بول را باز می گرداند تا بگوید آیا رویداد اتفاق افتاده است
  • متن: این یک توصیف دوستانه از بلوک است ، با آرگومان ها در داخل پرانتز ، به عنوان مثال ، "واکشی داده ها از "
  • argument ها: این یک شیء است که برای هر استدلال یک میدان دارد (به عنوان مثال ، "url" در مثال بالا) ؛ این شی به نوبه خود دارای این فیلدها است:

    • نوع: یا "رشته" یا "شماره"
    • defaultValue: مقدار پیش فرض که باید از قبل پر شود.

به عنوان مثال ، در اینجا فیلد بلوک ها در پسوند Fetch من آمده است:

"بلوک": [{"opcode": "fetchURL" ، "blockType": "reporter" ، "text": "واکشی داده ها از " ، "argument": {"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 ": '{"temperature": 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") بازگشت اگر (t == "بولی") بازگشت t؟ 1: 0 بازگشت JSON.stringify (خارج)} else {return ""}}

کد فیلد نام را از داده های JSON خارج می کند. اگر فیلد شامل یک رشته ، شماره یا بولی باشد ، آن را برمی گردانیم. در غیر اینصورت ، دوباره فیلد را JSONify می کنیم. و اگر نامی در JSON وجود نداشته باشد ، یک رشته خالی را برمی گردانیم.

با این حال ، گاهی اوقات ، ممکن است بخواهید یک بلوک ایجاد کنید که از API ناهمزمان استفاده می کند. روش fetchURL () از واکشی API استفاده می کند که ناهمزمان است. در چنین شرایطی ، شما باید قولی را از روش خود بازگردانید که کار می کند. برای مثال:

fetchURL ({url}) {

بازگشت واکشی (url). سپس (reply => answer.text ())}

خودشه. پسوند کامل در اینجا است.

مرحله 4: استفاده از افزونه Sandboxed

استفاده از افزونه Sandboxed
استفاده از افزونه Sandboxed
استفاده از افزونه Sandboxed
استفاده از افزونه Sandboxed
استفاده از افزونه Sandboxed
استفاده از افزونه Sandboxed

دو روش برای استفاده از افزونه sandboxed وجود دارد. ابتدا می توانید آن را در یک سرور وب بارگذاری کنید ، و سپس آن را در حالت Scratch SheepTester بارگذاری کنید. دوم ، می توانید آن را در یک آدرس اینترنتی کدگذاری کرده و آن را در حالت Scratch بارگذاری کنید. من در واقع از روش دوم برای آزمایش بسیار استفاده می کنم ، زیرا از نگرانی در مورد ذخیره شدن نسخه های قدیمی افزونه توسط سرور جلوگیری می کند. توجه داشته باشید که در حالی که می توانید جاوا اسکریپت را از Github Pages میزبانی کنید ، نمی توانید مستقیماً از مخزن معمولی github این کار را انجام دهید.

fetch.js من در https://arpruss.github.io/fetch.js میزبانی می شود. یا می توانید افزونه خود را با بارگذاری در اینجا به URL داده تبدیل کنید و سپس آن را در کلیپ بورد کپی کنید. URL داده یک آدرس اینترنتی غول پیکر است که یک فایل کامل را در خود نگه می دارد.

به حالت Scratch SheepTester بروید. روی دکمه افزودن برنامه افزودنی در گوشه سمت چپ پایین کلیک کنید. سپس بر روی "Choose an extension" کلیک کنید و آدرس اینترنتی خود را وارد کنید (در صورت تمایل می توانید کل آدرس داده بزرگ را جایگذاری کنید).

اگر همه چیز خوب پیش رفت ، یک ورودی برای برنامه افزودنی خود در سمت چپ صفحه Scratch خود خواهید داشت. اگر همه چیز خوب پیش نرفت ، باید کنسول جاوا اسکریپت خود را (shift-ctrl-J در Chrome) باز کنید و سعی کنید مشکل را اشکال زدایی کنید.

در بالا تعدادی کد را می بینید که داده های JSON را از ایستگاه KNYC (در نیویورک) سرویس آب و هوایی ایالات متحده واکشی و تجزیه می کند و آنها را نمایش می دهد ، در حالی که اسپریت را به همان روشی که باد در حال وزش است ، رو به رو می کند. روشی که من ایجاد کردم این بود که داده ها را در یک مرورگر وب واکشی می کردم و سپس برچسب ها را پیدا می کردم. اگر می خواهید ایستگاه هواشناسی دیگری را امتحان کنید ، کد پستی در نزدیکی را در کادر جستجو در weather.gov وارد کنید و صفحه آب و هوا برای موقعیت مکانی شما باید یک کد ایستگاه چهار حرفی به شما بدهد که می توانید از آن به جای KNYC در کد

شما همچنین می توانید با افزودن یک آرگومان "؟ url =" ، برنامه افزودنی سندباکس خود را مستقیماً در URL مربوط به حالت SheepTester قرار دهید. برای مثال:

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

مرحله 5: نوشتن یک برنامه افزودنی بدون جعبه: مقدمه

سازنده یک برنامه افزودنی بدون جعبه از یک شیء اجرا عبور می کند. می توانید آن را نادیده بگیرید یا از آن استفاده کنید. یکی از موارد استفاده از شیء Runtime استفاده از ویژگی currentMSecs آن برای همگام سازی رویدادها ("بلوک های کلاه") است. تا جایی که می توانم بگویم ، همه کدهای رویداد به طور منظم نظرسنجی می شوند و هر دور از نظرسنجی دارای یک مقدار جاری MSECs است. اگر به شیء Runtime نیاز دارید ، احتمالاً پسوند خود را با موارد زیر شروع می کنید:

کلاس EXTENSIONCLASS {

سازنده (زمان اجرا) {this.runtime = زمان اجرا…}…}

همه موارد استاندارد شیء پنجره را می توان در برنامه افزودنی بدون جعبه استفاده کرد. در نهایت ، برنامه افزودنی بدون جعبه شما باید با این کمی کد جادویی به پایان برسد:

(عملکرد() {

var extensionInstance = جدید EXTENSIONCLASS (window.vm.extensionManager.runtime) var serviceName = window.vm.extensionManager._registerInternalExtension (extensionInstance) window.vm.extensionManager._loadedExtensions.set (extensionInstance.getInfo ())

جایی که باید EXTENSIONCLASS را با کلاس افزونه خود جایگزین کنید.

مرحله 6: نوشتن یک برنامه افزودنی بدون جعبه: گیم پد ساده

بیایید اکنون یک افزونه ساده گیم پد بسازیم که یک بلوک رویداد ("کلاه") را برای فشار دادن یا رها شدن یک دکمه فراهم می کند.

در طول هر چرخه نظرسنجی بلوک رویداد ، ما یک مهر زمان را از شیء اجرا و حالت های قبلی و فعلی گیم پد ذخیره می کنیم. از مهر زمان برای تشخیص چرخه نظرسنجی جدید استفاده می شود. بنابراین ، ما شروع می کنیم با:

کلاس 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 "}،}،}،]،" menus ": {" pressReleaseMenu ": [{text:" press "، value: 1}، {text:" release "، value: 0}]،}}؛ } من فکر می کنم مقادیر موجود در منوی کشویی با وجود اینکه به عنوان اعداد اعلام شده اند ، همچنان به عنوان رشته به تابع کد کد منتقل می شوند. بنابراین به صراحت آنها را با مقادیر مشخص شده در منو در صورت نیاز مقایسه کنید. ما در حال حاضر روشی را می نویسیم که هر زمان چرخه نظرسنجی رویداد جدیدی رخ می دهد ، وضعیت دکمه را به روز می کند

به روز رسانی() {

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) { // تعداد دکمه های مختلف ، بنابراین گیم پد جدید this.previousButtons = برای (var i = 0 ؛ i <gamepad.buttons.length؛ i ++) this.preciousButtons.push (false)} else {this.preciousButtons = this. currentButtons} this.currentButtons = برای (var i = 0؛ i <gamepad.buttons.length؛ i ++) this.currentButtons.push (gamepad.buttons .pressed)} سرانجام ، ما می توانیم بلوک رویداد خود را با فراخوانی روش update () و سپس بررسی اینکه آیا دکمه مورد نیاز به تازگی فشار داده شده یا آزاد شده است ، با مقایسه حالات قبلی و قبلی دکمه پیاده سازی کنیم.

buttonPressedReleased ({b، eventType}) {

this.update () if (b <this.currentButtons.length) {if (eventType == 1) {// توجه داشته باشید: این یک رشته خواهد بود ، بنابراین بهتر است آن را با 1 مقایسه کنید تا اینکه آن را به عنوان یک بولی (اگر) this.currentButtons &&! this.previousButtons ) {true true}} else {if (! this.currentButtons && this.preciousButtons ) {true true}}} false false} و در نهایت ما پس از تعریف کلاس ، کد ثبت افزونه جادویی خود را اضافه می کنیم

(عملکرد() {

var extensionInstance = جدید ScratchSimpleGamepad (window.vm.extensionManager.runtime) var serviceName = window.vm.extensionManager._registerInternalExtension (extensionInstance) window.vm.extensionManager._loadedExtensions.set (extensionInstance.get) ())

در اینجا می توانید کد کامل را دریافت کنید.

مرحله 7: استفاده از یک برنامه افزودنی بدون جعبه

استفاده از یک برنامه افزودنی بدون جعبه
استفاده از یک برنامه افزودنی بدون جعبه

یکبار دیگر ، برنامه افزودنی خود را در جایی میزبانی کنید و این بار آن را با load_plugin = به جای url = argument در حالت SheetTester's Scratch بارگذاری کنید. به عنوان مثال ، برای حالت ساده Gamepad من ، به آدرس زیر بروید:

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

(به هر حال ، اگر می خواهید یک گیم پد پیچیده تر داشته باشید ، فقط "ساده" را از آدرس فوق حذف کنید ، و از پشتیبانی رومبل و محور آنالوگ برخوردار خواهید شد.)

مجدداً ، برنامه افزودنی باید در سمت چپ ویرایشگر Scratch شما ظاهر شود. در بالا یک برنامه بسیار ساده Scratch وجود دارد که وقتی دکمه 0 را فشار می دهید "سلام" و هنگام آزاد کردن آن "خداحافظ" می گوید.

مرحله 8: سازگاری دوگانه و سرعت

من متوجه شده ام که بلوک های افزونه با استفاده از روش بارگذاری که برای برنامه های افزودنی بدون جعبه استفاده کردم ، مرتبه ای سریعتر اجرا می کنند. بنابراین مگر اینکه به مزایای امنیتی اجرا در سندباکس Web Worker اهمیت دهید ، کد شما از بارگیری با؟ argument_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)}})) ()

توصیه شده: