جدول المحتويات:

ملحقات سكراتش 3.0: 8 خطوات
ملحقات سكراتش 3.0: 8 خطوات

فيديو: ملحقات سكراتش 3.0: 8 خطوات

فيديو: ملحقات سكراتش 3.0: 8 خطوات
فيديو: SCRATCH 2020 | شرح شامل ومفصل لبرنامج سكراتش 2024, يوليو
Anonim
ملحقات سكراتش 3.0
ملحقات سكراتش 3.0

امتدادات Scratch هي أجزاء من كود Javascript تضيف كتلًا جديدة إلى Scratch. بينما يتم تجميع Scratch مع مجموعة من الامتدادات الرسمية ، لا توجد آلية رسمية لإضافة امتدادات من صنع المستخدم.

عندما كنت أقوم بعمل ملحق التحكم في Minecraft الخاص بي لـ Scratch 3.0 ، وجدت صعوبة في البدء. يجمع Instructable المعلومات من مصادر مختلفة (خاصةً هذه) ، بالإضافة إلى بعض الأشياء التي اكتشفتها بنفسي.

أنت بحاجة إلى معرفة كيفية البرمجة في Javascript وكيفية استضافة Javascript على موقع ويب. بالنسبة لهذا الأخير ، أوصي بصفحات GitHub.

الحيلة الرئيسية هي استخدام تعديل SheepTester الخاص بـ Scratch والذي يتيح لك تحميل الإضافات والمكونات الإضافية.

سيرشدك هذا Instructable خلال إنشاء امتدادين:

  • الجلب: تحميل البيانات من عنوان URL واستخراج علامات JSON ، على سبيل المثال لتحميل بيانات الطقس
  • SimpleGamepad: استخدام وحدة تحكم في لعبة Scratch (يوجد هنا إصدار أكثر تعقيدًا).

الخطوة 1: نوعان من الامتدادات

هناك نوعان من الامتدادات التي سأسميها "غير محمية" و "صندوق حماية". تعمل ملحقات Sandboxed كعاملين على الويب ، ونتيجة لذلك لها قيود كبيرة:

  • لا يستطيع Web Workers الوصول إلى globals في كائن النافذة (بدلاً من ذلك ، لديهم كائن ذاتي عالمي ، وهو أكثر محدودية) ، لذلك لا يمكنك استخدامها لأشياء مثل الوصول إلى gamepad.
  • لا تمتلك ملحقات Sandboxed حق الوصول إلى كائن وقت تشغيل Scratch.
  • ملحقات Sandboxed أبطأ بكثير.
  • تعد رسائل خطأ وحدة تحكم Javascript الخاصة بملحقات وضع الحماية أكثر تشفيرًا في Chrome.

من ناحية أخرى:

  • يعد استخدام ملحقات وضع الحماية للأشخاص الآخرين أكثر أمانًا.
  • من المرجح أن تعمل ملحقات Sandboxed مع أي دعم تحميل ملحق رسمي نهائي.
  • يمكن اختبار امتدادات Sandboxed دون تحميلها إلى خادم ويب عن طريق الترميز في البيانات: // URL.

الملحقات الرسمية (مثل الموسيقى والقلم وما إلى ذلك) كلها بدون حماية. يحصل مُنشئ الامتداد على كائن وقت التشغيل من Scratch ، ويمكن الوصول إلى النافذة بالكامل.

يكون امتداد الجلب في وضع الحماية ، لكن Gamepad يحتاج إلى كائن الملاح من النافذة.

الخطوة 2: كتابة ملحق Sandboxed: الجزء الأول

لعمل امتداد ، يمكنك إنشاء فصل دراسي يقوم بترميز المعلومات المتعلقة به ، ثم إضافة القليل من التعليمات البرمجية لتسجيل الامتداد.

الشيء الرئيسي في فئة الامتداد هو طريقة getInfo () التي تُرجع كائنًا مع الحقول المطلوبة:

  • المعرّف: الاسم الداخلي للامتداد ، يجب أن يكون فريدًا لكل امتداد
  • الاسم: الاسم المألوف للامتداد ، ويظهر في قائمة كتل سكراتش
  • block: قائمة الكائنات التي تصف الكتلة المخصصة الجديدة.

وهناك حقل قوائم اختياري لا يتم استخدامه في الجلب ولكن سيتم استخدامه في Gamepad.

إذن ، هذا هو النموذج الأساسي لـ Fetch:

فئة ScratchFetch {

المُنشئ () {} getInfo () {return {"id": "Fetch"، "name": "Fetch"، "block": [/* add later * /]}} / * إضافة طرق للكتل * /} Scratch.extensions.register (جديد ScratchFetch ())

الخطوة 3: كتابة ملحق Sandboxed: الجزء الثاني

الآن ، نحتاج إلى إنشاء قائمة الكتل في كائن getInfo (). تحتاج كل كتلة إلى هذه الحقول الأربعة على الأقل:

  • كود التشغيل: هذا هو اسم الطريقة التي يتم استدعاؤها للقيام بعمل الكتلة
  • blockType: هذا هو نوع الكتلة ؛ الأكثر شيوعًا للإضافات هي:

    • "الأمر": يفعل شيئًا لكنه لا يُرجع قيمة
    • "مراسل": إرجاع سلسلة أو رقم
    • "Boolean": إرجاع قيمة منطقية (لاحظ الكتابة بالأحرف الكبيرة)
    • "القبعة": كتلة اصطياد الحدث ؛ إذا كان كود Scratch الخاص بك يستخدم هذه الكتلة ، فإن وقت تشغيل Scratch يستقصي بانتظام الطريقة المرتبطة التي تعيد قيمة منطقية لتحديد ما إذا كان الحدث قد حدث
  • النص: هذا وصف مألوف للكتلة ، مع وجود الوسيطات بين قوسين ، على سبيل المثال ، "جلب البيانات من "
  • الوسائط: هذا كائن به حقل لكل وسيطة (على سبيل المثال ، "url" في المثال أعلاه) ؛ هذا الكائن بدوره يحتوي على هذه الحقول:

    • النوع: إما "سلسلة" أو "رقم"
    • defaultValue: القيمة الافتراضية المراد تعبئتها مسبقًا.

على سبيل المثال ، هذا هو حقل الكتل في امتداد الجلب الخاص بي:

"كتل": [{"opcode": "fetchURL"، "blockType": "reporter"، "text": "جلب البيانات من "، "الوسيطات": {"url": {"type": "string"، "defaultValue ":" https://api.weather.gov/stations/KNYC/observations "}،}}، {" opcode ":" jsonExtract "،" blockType ":" reporter "،" text ":" extract [الاسم] من [البيانات] "،" الوسائط ": {" الاسم ": {" النوع ":" السلسلة "،" القيمة الافتراضية ":" درجة الحرارة "} ،" البيانات ": {" النوع ":" السلسلة "،" القيمة الافتراضية ": '{"temperature": 12.3}'}،}}،]

هنا ، حددنا كتلتين: fetchURL و jsonExtract. كلاهما صحفي. الأول يسحب البيانات من عنوان URL ويعيدها ، والثاني يستخرج حقلاً من بيانات JSON.

أخيرًا ، تحتاج إلى تضمين طرق كتلتين. تأخذ كل طريقة كائنًا كوسيطة ، مع احتواء الكائن على حقول لجميع الوسائط. يمكنك فك هذه باستخدام الأقواس المتعرجة في الحجج. على سبيل المثال ، إليك مثال واحد متزامن:

jsonExtract ({name، data}) {

var parsed = JSON.parse (البيانات) إذا كان (الاسم في التحليل) {var out = parsed [name] var t = typeof (out) if (t == "string" || t == "number") يعود إذا (ر == "منطقية") ترجع ر؟ 1: 0 إرجاع JSON.stringify (خارج)} وإلا {عودة ""}}

يسحب الرمز حقل الاسم من بيانات JSON. إذا كان الحقل يحتوي على سلسلة أو رقم أو قيمة منطقية ، فإننا نعيد ذلك. خلاف ذلك ، نقوم بإعادة JSONify الحقل. ونعيد سلسلة فارغة إذا كان الاسم مفقودًا من JSON.

ومع ذلك ، قد ترغب في بعض الأحيان في إنشاء كتلة تستخدم واجهة برمجة تطبيقات غير متزامنة. تستخدم طريقة fetchURL () واجهة برمجة تطبيقات الجلب غير المتزامنة. في مثل هذه الحالة ، يجب عليك العودة بوعد من طريقتك التي تؤدي العمل. على سبيل المثال:

fetchURL ({url}) {

إرجاع إحضار (url). ثم (response => response.text ())}

هذا كل شيء. التمديد الكامل هنا.

الخطوة 4: استخدام ملحق Sandboxed

باستخدام ملحق Sandboxed
باستخدام ملحق Sandboxed
باستخدام ملحق Sandboxed
باستخدام ملحق Sandboxed
باستخدام ملحق Sandboxed
باستخدام ملحق Sandboxed

هناك طريقتان لاستخدام ملحق وضع الحماية. أولاً ، يمكنك تحميله على خادم ويب ، ثم تحميله في وضع Scratch الخاص بـ SheepTester. ثانيًا ، يمكنك ترميزه في عنوان URL للبيانات ، وتحميله في تعديل Scratch. أنا في الواقع أستخدم الطريقة الثانية قليلاً للاختبار ، حيث إنها تتجنب القلق بشأن الإصدارات القديمة من الامتداد التي يتم تخزينها مؤقتًا بواسطة الخادم. لاحظ أنه بينما يمكنك استضافة جافا سكريبت من صفحات جيثب ، لا يمكنك القيام بذلك مباشرة من مستودع جيثب عادي.

تمت استضافة My fetch.js على https://arpruss.github.io/fetch.js. أو يمكنك تحويل الامتداد الخاص بك إلى عنوان URL للبيانات عن طريق تحميله هنا ثم نسخه إلى الحافظة. عنوان URL للبيانات هو عنوان URL عملاق يحتوي على ملف كامل فيه.

انتقل إلى وضع Scratch لـ SheepTester. انقر فوق الزر "إضافة ملحق" في الزاوية اليسرى السفلية. ثم انقر فوق "اختيار امتداد" ، وأدخل عنوان URL الخاص بك (يمكنك لصق عنوان URL للبيانات العملاقة بالكامل إذا أردت).

إذا سارت الأمور على ما يرام ، فسيكون لديك إدخال لتمديدك على الجانب الأيسر من شاشة سكراتش. إذا لم تسر الأمور على ما يرام ، يجب عليك فتح وحدة تحكم 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: كتابة ملحق Unsandboxed: مقدمة

يحصل مُنشئ الامتداد غير المحمي على كائن وقت التشغيل. يمكنك تجاهلها أو استخدامها. أحد استخدامات كائن وقت التشغيل هو استخدام خاصية MSecs الحالية الخاصة به لمزامنة الأحداث ("كتل القبعة"). بقدر ما أستطيع أن أقول ، يتم استقصاء جميع أكواد تشغيل كتلة الحدث بانتظام ، ولكل جولة من الاقتراع قيمة MSecs واحدة حالية. إذا كنت بحاجة إلى كائن Runtime ، فمن المحتمل أن تبدأ امتدادك بـ:

فئة EXTENSIONCLASS {

المُنشئ (وقت التشغيل) {this.runtime = runtime…}…}

يمكن استخدام جميع عناصر كائن النافذة القياسية في الامتداد غير المحمي. أخيرًا ، يجب أن ينتهي ملحقك غير المحمي بهذا الجزء من الشفرة السحرية:

(وظيفة() {

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

حيث يجب عليك استبدال EXTENSIONCLASS بفئة الملحق الخاص بك.

الخطوة 6: كتابة ملحق Unsandboxed: Simple Gamepad

لنقم الآن بإنشاء ملحق لوحة ألعاب بسيط يوفر كتلة حدث واحد ("قبعة") عند الضغط على الزر أو تحريره.

أثناء كل دورة استقصاء لكتلة الحدث ، سنحفظ طابعًا زمنيًا من كائن وقت التشغيل ، وحالات لوحة الألعاب السابقة والحالية. يتم استخدام الطابع الزمني للتعرف على ما إذا كانت لدينا دورة اقتراع جديدة. لذلك ، نبدأ بـ:

فئة ScratchSimpleGamepad {

المُنشئ (وقت التشغيل) {this.runtime = وقت التشغيل this.currentMSecs = -1 this.previousButtons = this.currentButtons = }…} سيكون لدينا كتلة حدث واحدة ، مع مدخلين - رقم زر وقائمة لتحديد ما إذا كنا نريد تشغيل الحدث عند الضغط أو الإصدار. إذن ، ها هي طريقتنا

يحصل على معلومات() {

إرجاع {"id": "SimpleGamepad"، "name": "SimpleGamepad"، "block": [{"opcode": "buttonPressedReleased"، "blockType": "hat"، "text": "الزر [eventType] "،" arguments ": {" 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) تُرجع // ليست دورة استقصاء جديدة 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.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) {// note: ستكون هذه سلسلة ، لذا من الأفضل مقارنتها بـ 1 بدلاً من معاملتها كسلسلة منطقية إذا (this.currentButtons &&! this.previousButtons ) {return true}} else {if (! this.currentButtons && this.previousButtons ) {return true}}} return false} وأخيرًا نضيف كود التسجيل الخاص بالملحق السحري بعد تحديد الفصل

(وظيفة() {

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

يمكنك الحصول على الكود الكامل هنا.

الخطوة 7: استخدام ملحق Unsandboxed

باستخدام ملحق Unsandboxed
باستخدام ملحق Unsandboxed

مرة أخرى ، استضف الامتداد الخاص بك في مكان ما ، وهذه المرة قم بتحميله باستخدام load_plugin = بدلاً من url = وسيطة إلى وضع Scratch الخاص بـ SheepTester. على سبيل المثال ، من أجل وضع Gamepad البسيط الخاص بي ، انتقل إلى:

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

(بالمناسبة ، إذا كنت تريد لوحة ألعاب أكثر تعقيدًا ، فما عليك سوى إزالة كلمة "بسيطة" من عنوان URL أعلاه ، وستحصل على دعم لمحور تناظري ومرن.)

مرة أخرى ، يجب أن يظهر الامتداد على الجانب الأيسر من محرر سكراتش. أعلاه هو برنامج Scratch بسيط للغاية يقول "مرحبًا" عند الضغط على الزر 0 و "وداعًا" عند تحريره.

الخطوة 8: التوافق المزدوج والسرعة

لقد لاحظت أن كتل الامتداد تعمل بترتيب أسرع من حيث الحجم باستخدام طريقة التحميل التي استخدمتها للإضافات غير المحمية. لذلك ، ما لم تكن مهتمًا بالمزايا الأمنية للتشغيل في وضع الحماية لـ Web Worker ، ستستفيد التعليمات البرمجية الخاصة بك من تحميلها مع وسيطة؟ 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)}}) ()

موصى به: