親子プログラミングはGitとNode.jsが使えることが前提になっている?
小学校でのプログラミング教育の必須化に伴って、子供たちがScratch 3.0に触れる機会も増えるかと思います。そんな中、ブロックをくっつけるだけのお遊びツールだとあなどっていると、次のような連載が始まりました。
「親子でできる!Scratch と AWS を使った "ものづくり" 体験 - 1. 準備 〜 疎通確認編」
2020-09-01
How to be a Developer
金澤 圭
この連載の「2. 作業の前提について」で、衝撃的な次の一文があります。
PC に Git と Node.js がインストールされている必要があります。
保護者の方も、GitやNode.jsを当たり前のようにインストールしなければいけない時代になりましたね。でも、安心してください。Dockerという便利なツールがありますので、簡単に開発環境を整えることができます。
本記事では、Webベースの統合開発環境であるcode-server
とScratch 3.0 拡張機能の開発と実行に必要なソースコード(scratch-vm/scratch-gui
)を詰め合わせたDockerコンテナ(jprad/s3coder
)を使って、Windowsパソコン上で、Scratch 3.0 GUI
サーバーを起動できるようにします。
後半では、「Scratch 3.0の拡張機能を作ってみよう」を参考にして、拡張機能を追加します。
拡張機能を追加して、Scratch 3.0 GUIでコーディング
必要なもの
- Windows 10 パソコン
- Docker Desktop on Windows または Docker Desktop on Windows Home
Windows 10 パソコンにDockerをインストールしてください。Dockerのインストール方法は、リンク先や各種記事を参照してください。
セットアップと起動
Dockerイメージ(jprad/s3coder
)を元にDockerコンテナを起動し、Scratch 3.0 GUI
サーバーをWindowパソコンで実行できるようにします。
1. 共有フォルダの作成とDockerコンテナの初回起動
Windows 10 で、コマンドプロンプトを起動し、次の一連のコマンドを入力します。
cd c:\
mkdir scratch-ws
docker run --name s3coder -d -p 8080:8080 -p 8601:8601 ^
-v C:/scratch-ws:/home/coder/s3/scratch-ws -e PASSWORD=password ^
jprad/s3coder /home/coder/s3
REM docker run ... のコマンドが長いので「^(キャレット)」で改行しています。
C\scratch-ws
フォルダは、Dockerコンテナにマウントされる共有フォルダです(/home/coder/s3/scratch-ws)。
docker run
コマンドを開始すると、必要なDockerイメージ(合計:844.17 MB)のダウンロードが始まり、Dockerコンテナが起動されます(コンテナ名:s3coder
)。
Dockerコンテナの初回起動時に、共有フォルダへのアクセスを許可するかどうかの確認通知が表示されますので、[Share it]
で許可します。
2.code-severへのログインとScratch 3.0 GUIの起動
Dockerコンテナの起動完了後、code-server
( http://localhost:8080 ) へアクセスし、ログインします(パスワードは、password
です)。統合開発環境が開きますので、Dockerイメージに同梱されている scratch-gui
を起動します。起動方法が構成ファイル(./s3/.vscode/launch.json)に設定されていますので、クリック操作のみで起動できます。scratch-gui
の起動完了後、Scratch 3.0 GUI
( http://localhost:8601 ) へアクセスすると、公式ページとは少しばかり異なっていますが、使い慣れたScratch 3.0
でのコーディングが行えます。
手順
-
code-server
( http://localhost:8080 ) へアクセスする。 - パスワードに
password
と入力し、[SUBMIT]
ボタンをクリックし、ログインする。 -
[Run (Ctrl + Shift + D)]
アイコンをクリックする。 - ドロップダウンリストで
'Run Scratch 3.0 GUI'
(既定)を選択する。 -
[Start Debuging]
アイコンをクリックする。 -
[TERMINAL]
タブをクリックし、ビルド完了後の'Compiled successfully'
が表示されるのを待つ。 -
Scratch 3.0 GUI
( http://localhost:8601 ) へアクセスする。
3.停止・再開
scratch-guiの再開・停止
scratch-guiを停止せずに再開するには、coder-serverの[Restart (Ctrl+Shift+F5)]
アイコンをクリックします。
scratch-guiを停止するには、code-serverの[Stop (Shift+F5)]
アイコンをクリックします。
scratch-guiの開始
-
[Run (Ctrl + Shift + D)]
アイコンをクリックする。 - ドロップダウンリストで
'Run Scratch 3.0 GUI'
(既定)を選択する。 -
[Start Debuging]
アイコンをクリックする。 -
[TERMINAL]
タブをクリックし、ビルド完了後の'Compiled successfully'
が表示されるのを待つ。
Dockerコンテナの停止
コマンドプロンプトで次のコマンドを実行するとDockerコンテナ(コンテナ名:s3coder
)が停止します。
docker stop s3coder
Dockerコンテナの再開
コマンドプロンプトで次のコマンドを実行するとDockerコンテナ(コンテナ名:s3coder
)が再開します。
docker start s3coder
拡張機能の開発
Scratch 3.0 Extensions の開発に関する情報には、次のようなものがあります。
-
「子供の科学 2020年9月号, p.p.66-69, ジャバスクリプトでスクラッチを拡張しよう」
子供向けの月刊誌の記事です。 -
「Scratch を改造しよう」
Strecth3として、Scratch3.0で機械学習をプログラミングできる開発環境を提供する石原 淳也(いしはら じゅんや)氏の有償コンテンツです(一部無料公開あり)。 -
「Scratch 3.0 Extensions」
LLK公式の拡張機能に関するページです。 -
「Scratch 3.0の拡張機能を作ってみよう」
Scratch 3.0の拡張機能の作り方をその下準備から説明しています。
ここでは、「Scratch 3.0の拡張機能を作ってみよう」を参考にログを出力する拡張機能(ブロック)を実装(コピペ)してみます。
拡張機能に必要なファイル
拡張機能(s3coder_newblocks
)を実装するには、次のファイルを追加・編集します。
scratch-vm
# | フォルダ | ファイル | 追加 | 編集 | 説明 |
---|---|---|---|---|---|
1 | scratch-vm/src/extensions/s3coder_newblocks | index.js | 〇 | 拡張機能(newblocks )の本体です。 |
|
2 | scratch-vm/src/extension-support | extension-manager.js | 〇 | 追加した拡張機能(s3coder_newblocks )をbuiltinExtensions に追加登録します。 |
scratch-gui
# | フォルダ | ファイル | 追加 | 編集 | 説明 |
---|---|---|---|---|---|
1 | scratch-gui/src/lib/libraries/extensions/s3coder_newblocks | newblocks.png | 〇 | 600x372ピクセルのPNG形式ファイルです。拡張機能の選択時にバナーとして表示されます。 | |
2 | scratch-gui/src/lib/libraries/extensions/s3coder_newblocks | newblocks-small.png | 〇 | 80x80ピクセルのPNG形式ファイルです。ブロックのアイコンとして表示されます。 | |
3 | scratch-gui/src/lib/libraries/extensions | index.js | 〇 | PNG形式ファイルの読込定義と拡張ブロックの定義を設定します。 |
scratch-vm での実装
scratch-vmで、拡張機能そのものを実装します。
フォルダ作成
拡張機能用のフォルダを次の手順で作成します。
-
code-server
のEXPLORERで、s3/scratch-vm/src/extensions
フォルダを選択します。 - 右クリックで、コンテキストメニューから
New Folder
を選択し、's3coder_newblocks'
フォルダを作成します。
index.jsファイルの実装
次の手順で、index.js
ファイルを実装します。
- 作成した
's3coder_newblocks'
フォルダで右クリックし、New File
を選択し、ファイル名をindex.js
とします。 -
「Scratch 3.0の拡張機能を作ってみよう/基本の書式 - 拡張機能の追加」から
index.js
のソースコードをコピー&ペーストします。
index.js
const ArgumentType = require('../../extension-support/argument-type');
const BlockType = require('../../extension-support/block-type');
const Cast = require('../../util/cast');
const log = require('../../util/log');
/**
* Icon svg to be displayed at the left edge of each extension block, encoded as a data URI.
* @type {string}
*/
// eslint-disable-next-line max-len
const blockIconURI = 'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHdpZHRoPSI0MCIgaGVpZ2h0PSI0MCIgdmlld0JveD0iMCAwIDQwIDQwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj48ZyBpZD0iSUQwLjA4NjgyNDQzOTAwMDMzODMyIiB0cmFuc2Zvcm09Im1hdHJpeCgwLjQ5MTU0NjY2MDY2MTY5NzQsIDAsIDAsIDAuNDkxNTQ2NjYwNjYxNjk3NCwgLTY0LjUsIC03Ny4yNSkiPjxwYXRoIGlkPSJJRDAuNTcyMTQ2MjMwMzc3MjU2OSIgZmlsbD0iI0ZGOTQwMCIgc3Ryb2tlPSJub25lIiBkPSJNIDE4OCAxNDEgTCAyNTAgMTQxIEwgMjUwIDIwMyBMIDE4OCAyMDMgTCAxODggMTQxIFogIiB0cmFuc2Zvcm09Im1hdHJpeCgxLjI4NzkwMzMwODg2ODQwODIsIDAsIDAsIDEuMjg3OTAzMzA4ODY4NDA4MiwgLTExMC45LCAtMjQuNCkiLz48cGF0aCBpZD0iSUQwLjYzODMzNjEzNTA3NDQ5NjMiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIGQ9Ik0gMTk2IDIwNCBDIDE5NiAyMDQgMTkyLjcwNiAxOTAuMDU4IDE5MyAxODMgQyAxOTMuMDc0IDE4MS4yMzYgMTk1Ljg4NiAxNzguNDU4IDE5NyAxODAgQyAyMDEuNDU1IDE4Ni4xNjggMjAzLjQ0MyAyMDMuNzU0IDIwNiAyMDEgQyAyMDkuMjExIDE5Ny41NDIgMjEwIDE2NiAyMTAgMTY2ICIgdHJhbnNmb3JtPSJtYXRyaXgoMSwgMCwgMCwgMSwgLTU3LCAxNS44KSIvPjxwYXRoIGlkPSJJRDAuNzU4NzMwMzU2NTgxNTA5MSIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgZD0iTSAyMTUgMTY5IEMgMjE1IDE2OSAyMTguMzY3IDE2OS41MzQgMjIwIDE3MCBDIDIyMC43MTYgMTcwLjIwNSAyMjEuMjc4IDE3MC44MTkgMjIyIDE3MSBDIDIyMi42NDYgMTcxLjE2MiAyMjMuMzY4IDE3MC43ODkgMjI0IDE3MSBDIDIyNC40NDcgMTcxLjE0OSAyMjUgMTcyIDIyNSAxNzIgIiB0cmFuc2Zvcm09Im1hdHJpeCgxLCAwLCAwLCAxLCAtNTcsIDE1LjgpIi8+PHBhdGggaWQ9IklEMC4yNDM2NzMwNzMxMjc4NjU4IiBmaWxsPSJub25lIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBkPSJNIDIyNyAxNTQgQyAyMjcgMTU0IDIxOC41NTUgMTQ3Ljg5MCAyMTcgMTUxIEMgMjEyLjM0NSAxNjAuMzEwIDIxMS4yODkgMTcxLjczMyAyMTMgMTgyIEMgMjEzLjYxMiAxODUuNjcyIDIyMyAxODcgMjIzIDE4NyAiIHRyYW5zZm9ybT0ibWF0cml4KDEsIDAsIDAsIDEsIC01NywgMTUuOCkiLz48cGF0aCBpZD0iSUQwLjc5MzkzOTQ4MTk1NTAyMTYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIGQ9Ik0gMTc1IDIwMC41MDAgQyAxNzUgMjAwLjUwMCAxNjkuODA1IDIyMS45MTMgMTcxIDIyMi43NTAgQyAxNzIuMTk1IDIyMy41ODcgMTc4Ljc5NSAyMDUuMjk1IDE4Mi41MDAgMjA1Ljc1MCBDIDE4NS45MjAgMjA2LjE3MCAxODEuODU5IDIyNC41MDAgMTg1LjI1MCAyMjQuNTAwIEMgMTg5LjIxMyAyMjQuNTAwIDE5Ny4yNTAgMjA1Ljc1MCAxOTcuMjUwIDIwNS43NTAgIi8+PC9nPjwvc3ZnPg==';
/**
* Icon svg to be displayed in the category menu, encoded as a data URI.
* @type {string}
*/
// eslint-disable-next-line max-len
const menuIconURI = 'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHdpZHRoPSI0MCIgaGVpZ2h0PSI0MCIgdmlld0JveD0iMCAwIDQwIDQwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj48ZyBpZD0iSUQwLjA4NjgyNDQzOTAwMDMzODMyIiB0cmFuc2Zvcm09Im1hdHJpeCgwLjQ5MTU0NjY2MDY2MTY5NzQsIDAsIDAsIDAuNDkxNTQ2NjYwNjYxNjk3NCwgLTY0LjUsIC03Ny4yNSkiPjxwYXRoIGlkPSJJRDAuNTcyMTQ2MjMwMzc3MjU2OSIgZmlsbD0iI0ZGOTQwMCIgc3Ryb2tlPSJub25lIiBkPSJNIDE4OCAxNDEgTCAyNTAgMTQxIEwgMjUwIDIwMyBMIDE4OCAyMDMgTCAxODggMTQxIFogIiB0cmFuc2Zvcm09Im1hdHJpeCgxLjI4NzkwMzMwODg2ODQwODIsIDAsIDAsIDEuMjg3OTAzMzA4ODY4NDA4MiwgLTExMC45LCAtMjQuNCkiLz48cGF0aCBpZD0iSUQwLjYzODMzNjEzNTA3NDQ5NjMiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIGQ9Ik0gMTk2IDIwNCBDIDE5NiAyMDQgMTkyLjcwNiAxOTAuMDU4IDE5MyAxODMgQyAxOTMuMDc0IDE4MS4yMzYgMTk1Ljg4NiAxNzguNDU4IDE5NyAxODAgQyAyMDEuNDU1IDE4Ni4xNjggMjAzLjQ0MyAyMDMuNzU0IDIwNiAyMDEgQyAyMDkuMjExIDE5Ny41NDIgMjEwIDE2NiAyMTAgMTY2ICIgdHJhbnNmb3JtPSJtYXRyaXgoMSwgMCwgMCwgMSwgLTU3LCAxNS44KSIvPjxwYXRoIGlkPSJJRDAuNzU4NzMwMzU2NTgxNTA5MSIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgZD0iTSAyMTUgMTY5IEMgMjE1IDE2OSAyMTguMzY3IDE2OS41MzQgMjIwIDE3MCBDIDIyMC43MTYgMTcwLjIwNSAyMjEuMjc4IDE3MC44MTkgMjIyIDE3MSBDIDIyMi42NDYgMTcxLjE2MiAyMjMuMzY4IDE3MC43ODkgMjI0IDE3MSBDIDIyNC40NDcgMTcxLjE0OSAyMjUgMTcyIDIyNSAxNzIgIiB0cmFuc2Zvcm09Im1hdHJpeCgxLCAwLCAwLCAxLCAtNTcsIDE1LjgpIi8+PHBhdGggaWQ9IklEMC4yNDM2NzMwNzMxMjc4NjU4IiBmaWxsPSJub25lIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBkPSJNIDIyNyAxNTQgQyAyMjcgMTU0IDIxOC41NTUgMTQ3Ljg5MCAyMTcgMTUxIEMgMjEyLjM0NSAxNjAuMzEwIDIxMS4yODkgMTcxLjczMyAyMTMgMTgyIEMgMjEzLjYxMiAxODUuNjcyIDIyMyAxODcgMjIzIDE4NyAiIHRyYW5zZm9ybT0ibWF0cml4KDEsIDAsIDAsIDEsIC01NywgMTUuOCkiLz48cGF0aCBpZD0iSUQwLjc5MzkzOTQ4MTk1NTAyMTYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIGQ9Ik0gMTc1IDIwMC41MDAgQyAxNzUgMjAwLjUwMCAxNjkuODA1IDIyMS45MTMgMTcxIDIyMi43NTAgQyAxNzIuMTk1IDIyMy41ODcgMTc4Ljc5NSAyMDUuMjk1IDE4Mi41MDAgMjA1Ljc1MCBDIDE4NS45MjAgMjA2LjE3MCAxODEuODU5IDIyNC41MDAgMTg1LjI1MCAyMjQuNTAwIEMgMTg5LjIxMyAyMjQuNTAwIDE5Ny4yNTAgMjA1Ljc1MCAxOTcuMjUwIDIwNS43NTAgIi8+PC9nPjwvc3ZnPg==';
/**
* Class for the new blocks in Scratch 3.0
* @param {Runtime} runtime - the runtime instantiating this block package.
* @constructor
*/
class Scratch3NewBlocks {
constructor (runtime) {
/**
* The runtime instantiating this block package.
* @type {Runtime}
*/
this.runtime = runtime;
//this._onTargetCreated = this._onTargetCreated.bind(this);
//this.runtime.on('targetWasCreated', this._onTargetCreated);
}
/**
* @returns {object} metadata for this extension and its blocks.
*/
getInfo () {
return {
id: 'newblocks',
name: 'New Blocks',
menuIconURI: menuIconURI,
blockIconURI: blockIconURI,
blocks: [
{
opcode: 'writeLog',
blockType: BlockType.COMMAND,
text: 'log [TEXT]',
arguments: {
TEXT: {
type: ArgumentType.STRING,
defaultValue: "hello"
}
}
},
{
opcode: 'getBrowser',
text: 'browser',
blockType: BlockType.REPORTER
}
],
menus: {
}
};
}
/**
* Write log.
* @param {object} args - the block arguments.
* @property {number} TEXT - the text.
*/
writeLog (args) {
const text = Cast.toString(args.TEXT);
log.log(text);
}
/**
* Get the browser.
* @return {number} - the user agent.
*/
getBrowser () {
return navigator.userAgent;
}
}
module.exports = Scratch3NewBlocks;
extension-manager.jsファイルの変更
scratch-vm/src/extension-support
フォルダのextension-manager.js
ファイルを開き、builtinExtensions
に、次のように拡張機能(s3coder_newblocks
)を追加登録します。
※カンマで区切ることを忘れないでください。
const builtinExtensions = {
...
gdxfor: () => require('../extensions/scratch3_gdx_for'),
newblocks: () => require('../extensions/s3coder_newblocks'),
};
scratch-gui での設定
scratch-guiで、拡張機能を選択できるように設定します。
フォルダ作成
画像保存用のフォルダを次の手順で作成します。
-
code-server
のEXPLORERで、s3/scratch-gui/src/lib/libraries/extensions
フォルダを選択します。 - 右クリックで、コンテキストメニューから
New Folder
を選択し、's3coder_newblocks'
フォルダを作成します。
画像ファイル
画像ファイルをダウンロードし、作成したフォルダへ保存します。
- 2つの画像ファイルをダウンロードし、
C:\scratch-ws
フォルダへ保存します。 -
code-server
のEXPLORERで、s3/scratch-ws
フォルダを開き、2つの画像ファイルを選択し、右クリックでコンテキストメニューからCopy
します。 -
s3/scratch-gui/src/lib/libraries/extensions/s3coder_newblocks
フォルダを選択し、右クリックでコンテキストメニューからPaste
します。
index.jsファイルの設定
s3/scratch-gui/src/lib/libraries/extensions
フォルダのindex.js
ファイルを開き、次のように拡張機能の設定を行います。これにより、Scratch 3.0 GUI
の拡張機能の追加で、拡張機能を選択できるようになります。
...
import gdxforConnectionSmallIconURL from './gdxfor/gdxfor-small.svg';
import newblocksImage from './s3coder_newblocks/newblocks.png';
import newblocksInsetImage from './s3coder_newblocks/newblocks-small.png';
export default [
...
),
helpLink: 'https://scratch.mit.edu/vernier'
},
{
name: (
<FormattedMessage
defaultMessage="New Blocks"
description="Name for the 'New Blocks' extension"
id="gui.extension.newblocks.name"
/>
),
extensionId: 'newblocks',
iconURL: newblocksImage,
insetIconURL: newblocksInsetImage,
description: (
<FormattedMessage
defaultMessage="New extension"
description="Description for the 'New Blocks' extension"
id="gui.extension.newblocks.description"
/>
),
featured: true
},
];
動作確認
scratch-gui
を開始し、Scratch 3.0 GUI
を開きなおすと、「拡張機能を追加」で、新しい拡張機能を選択できます。
logブロック
を実行すると、ブラウザのConsoleにhello
と出力されます。
おわりに
- Dockerイメージ(jprad/s3coder)を使って、Scratch 3.0 Extentionsの開発環境と動作環境を構築しました。
- 「Scratch 3.0の拡張機能を作ってみよう」を参考にして、拡張機能を追加しました。
**【メモ】Dockerイメージの作成**
cd c:\
mkdir scratch-ws
docker run -it -p 8080:8080 -p 8601:8601 -v C:/scratch-ws:/home/coder/s3/scratch-ws -e PASSWORD=password codercom/code-server /home/coder/s3
http://localhost:8080/ へアクセス
sudo apt-get update -y
sudo apt-get install -y nodejs npm
sudo npm install -g npm
sudo chown -R coder:coder /home/coder/s3
git clone --depth 1 https://github.com/llk/scratch-vm.git
git clone --depth 1 https://github.com/llk/scratch-gui.git
cd scratch-vm
npm ci
sudo npm link
cd ../scratch-gui
npm ci
sudo npm link scratch-vm
npm start
--->> [Ctrl]+[C]で中断
http://localhost:8601/ へアクセス
- scratch-guiのポート
ENV環境変数で設定可能
Dockerfile の記述
docker build -t test-image .
docker run --name test-container -it -p 8080:8080 -p 8601:8601 -v C:/scratch-ws:/home/coder/s3/scratch-ws -e PASSWORD=password test-image /home/coder/s3