136
101

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Scratch 3.0でオリジナルブロックをつくろう

Last updated at Posted at 2019-01-04

Scratch 3.0が正式版となって登場!

更新

  • 2019/1/16 Scratchで楽しく学ぶ アート&サイエンスの著者の石原さん@champierre 直々にコメントをいただいて、しかも修正箇所もご指摘いただきました。ありがとうございました!びっくりしたー
  • 2019/3/31 @mkisono から最新版に合わせたコメントいただきsrc/extension-support/extension-manager.js修正!ありがとうござました!
  • 2019/8/19 公開方法を追記しました。
  • 2019/9/7 作れるブロックのタイプ4種類をこちらにまとめました。

2019/1/3、ついにScratch 3.0がでました。

Scratch
https://scratch.mit.edu/

かっこいいですね~!

2019-01-04 (5).png

2020年からの小学校プログラミング必修化に向けて、タブレット対応も完了したことになります。
これで導入の拍車がかかるScratch 3.0。
実装もかなり洗練されていて、もうこどもの勉強道具の領域を超えています

Scratch 3.0の重要ポイントと、オリジナルブロック追加方法について説明します。

3.0の重要ポイント (使う人向け)

  • ブラウザだけで動作 (これは従来通り)
  • Flashなしで動作可能に :thumbsup:
    したがってiPad、タブレット、iPhoneなどどこでも使用可能
  • チュートリアルが豊富に。
    マニュアルなしでもとにかく触りながら覚えられる。
  • デザインが段違いに洗練された。

3.0の重要ポイント (Scratch3.0内実装)

  • 内部はNode.js。TypeScriptではない生のJavaScript。
  • 画面はReactで実装されていて、各パーツでちゃんとコンポーネント化されている。すばらしい。
  • ES2015(constなど)には対応。しかしES2017(asyncなど)は未対応。webpackでコンパイルしている。
  • 拡張機能の仕様のたたき台が公開されている。2から少し変わったらしい。
  • npmパッケージを導入可能。拡張機能にも利用できるらしい(公式には書いてないが私はできた)

オリジナルブロックをつくってみよう

わたしは、2つの方法でブロックをつくりました。

  • 方法1.感触を試すだけ
  • 方法2.ちゃんとしたオリジナルブロックを作る
    • 自分の開発環境を作る
    • ブロックを実装
    • GUI側を更新

方法1.お試しサイトで感触を試す

この方法の特徴

  • 雰囲気はつかめるので、入りとしてはよい
  • 単一JavaScriptファイルのみ読み込み可能
  • ブラウザリロードで消えてしまう
  • npmパッケージ利用不可

やりかた

以下の記事の通りに実施します。
すると、正式版ではないサイトで自作JavaScriptを読み込ませることで、オリジナルブロック追加の感触が試せます。
うまくいけば10分ほどでできます。

利用する正式版ではないサイト

試した結果

image.png

できた!!

方法2. ちゃんとしたオリジナルブロックをつくる

教えていただいたのは公式Wikiさんのツイート。

この方法の特徴

  • 開発環境が手に入る
  • npmなどを使い、自由にNode.jsの拡張機能を作れる
  • まだ開発済みブロックを共有・公開するまでには至らない
    公開はScratch開発チームにて実施。共有はこれからやり方が提供されるそう。公式Wiki

前提 [2019/09追記]

私が確認した環境は以下2つで、いずれも成功。

pattern 1 pattern 2
OS Windows 10 MacOS Mojave 10.14.6
npm 6.4.1 6.9.0
node 11.2.0 12.1.0
備考 WSL(ubuntu 18.04)上です

やりかた

公式Wikiの記事に記載の通りに実施しますが、途中から私のアレンジです。

今回は、ただ入力の文字列をログに吐き出すブロックを作ります。

1) 開発環境を整えます

2つのgitプロジェクト(scratch-vm, scratch-gui)をクローンします。
両方とも開発する部分があるので、同時にコンパイルできるように、scratch-guiを親として、scratch-vmを子供としてリンクして使用します。

## 以下yarn はnpmでも可能
$ 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 && yarn install && yarn link
## 上記でscratch-vmの依存パッケージがダウンロードされる
## 最後にnpmのリンクに追加される。
$ cd scratch-gui && yarn link scratch-vm && yarn install
## 上記で、scratch-vmを子供としてリンクし、ほかのパッケージをダウンロードする。

起動を確認します。

$ cd scratch-gui
$ yarn start

コンパイルが完了したら、

にアクセスして画面を見てみます。

image.png

いけましたね。

2) ブロックを実装します

今回はWikiに従い「newblocks」という新しい拡張機能を追加する。
拡張機能は複数のブロックを含むことができるが、今回のnewblocksは1つのブロックのみを持つ。

追加(★)および更新(★★)するファイルは以下。(scratch-vmのソースツリー)

.
├── LICENSE
├── node_modules
├── package.json
├── package-lock.json
├── README.md
├── src
│   ├── blocks
│   ├── dispatch
│   ├── engine
│   ├── extensions
│   │   ├── scratch3_ev3
│   │   ├── scratch3_newblocks 【★これを追加する】
│   │   │   └── index.js【★これを追加する → ファイル1】
│   │   ├── 【その他いくつか】
│   │   └── scratch3_wedo2
│   ├── extension-support
│   │   ├── argument-type.js
│   │   ├── extension-manager.js 【★★これを更新する → ファイル2】
│   │   └── 【その他いくつか】
│   ├── import
│   ├── index.js
│   ├── io
│   ├── playground
│   ├── serialization
│   ├── sprites
│   ├── util
│   └── virtual-machine.js
├── test
├── TRADEMARK
├── webpack.config.js
├── yarn-error.log
└── yarn.lock

さて、1の手順でダウンロードしてきたscratch-vm内に、ソースコードを追加・更新します。

ファイル1src/extensions/scratch3_newblocks/index.jsは、ブロックの処理を記載します。

src/extensions/scratch3_newblocks/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');

class Scratch3NewBlocks {
    constructor (runtime) {
        this.runtime = runtime;
    }

    getInfo () {
        return {
            id: 'newblocks',
            name: 'New Blocks',
            blocks: [
                {
                    opcode: 'writeLog',
                    blockType: BlockType.COMMAND,
                    text: 'log [TEXT]',
                    arguments: {
                        TEXT: {
                            type: ArgumentType.STRING,
                            defaultValue: "hello"
                        }
                    }
                }
            ],
            menus: {
            }
        };
    }

    writeLog (args) {
        const text = Cast.toString(args.TEXT);
        log.log(text);
    }
}

module.exports = Scratch3NewBlocks;

ファイル2src/extension-support/extension-manager.jsは、ブロックの一覧です。
そこに先ほどのscratch3_newblocksを追加します。

src/extension-support/extension-manager.js

const builtinExtensions = {
    coreExample: () => require('../blocks/scratch3_core_example'),
    pen: () => require('../extensions/scratch3_pen'),
    wedo2: () => require('../extensions/scratch3_wedo2'),
    music: () => require('../extensions/scratch3_music'),
    microbit: () => require('../extensions/scratch3_microbit'),
    text2speech: () => require('../extensions/scratch3_text2speech'),
    translate: () => require('../extensions/scratch3_translate'),
    videoSensing: () => require('../extensions/scratch3_video_sensing'),
    speech2text: () => require('../extensions/scratch3_speech2text'),
    ev3: () => require('../extensions/scratch3_ev3'),
    makeymakey: () => require('../extensions/scratch3_makeymakey'),
    gdxfor: () => require('../extensions/scratch3_gdx_for'), 【★最後のコンマを追加
    newblocks: () => require('../extensions/scratch3_newblocks')【★ この行を追加
};

これで、ブロックの実装は完了です。おめでとうございます。

3) GUIを更新します

ユーザがブロックを追加できるようにGUIを変更しましょう。

GUIの左下の「+」ボタンを押すと、メニューが出てきます。これをライブラリといいます。

image.png

ここに2)でつくったブロック処理を追加します。
scratch-guiのフォルダ内のsrc/lib/libraries/extensions/index.jsxの最後に以下を追加します。

src/lib/libraries/extensions/index.jsx



import wedoMenuImage from './peripheral-connection/wedo/wedo-small.svg';
import wedoButtonImage from './peripheral-connection/wedo/wedo-button-illustration.svg';

// 冒頭importが続く部分に以下の2行を追加
import newBlockImage from './newblocks/newblocks.png';
import newBlockButtonImage from './newblocks/newblocks-small.png';

export default [
    {
        中略
        connectingMessage: (
            <FormattedMessage
                defaultMessage="Connecting"
                description="Message to help people connect to their WeDo."
                id="gui.extension.wedo2.connectingMessage"
            />
        ),
        helpLink: 'https://scratch.mit.edu/wedo'

    }
// ここから下を追加
,
    {
        name: 'NewBlocks',
        extensionId: 'newblocks',
        collaborator: 'Me',
        iconURL: newBlockImage,
        insetIconURL: newBlockButtonImage,
        description: (
            <FormattedMessage
                defaultMessage="New blocks."
                description="my block"
                id="gui.extension.newblocks.description"
            />
        ),
        featured: true,
        disabled: false,
        internetConnectionRequired: true,
        bluetoothRequired: false,
        helpLink: 'https://scratch.mit.edu/wedo'

    }
// ここまでを追加
];

メニュー用の画像を追加します。
追加する場所として先程のsrc/lib/libraries/extensions/の下にnewblocksというフォルダを追加します。
メニューの背景用の画像として、同じフォルダに600 x 372のサイズのnewblocks.pngファイルを追加します。

newblocks.png

メニューのアイコン用画像として、同じフォルダに180 x 180のサイズのnewblocks-small.pngファイルを追加します。

newblocks-small.png

こんなフォルダ構成になっていればOK.

.
├── LICENSE
├── package.json
├── prune-gh-pages.sh
├── README.md
├── src
│   ├── components
│   ├── containers
│   ├── css
│   ├── examples
│   ├── index.js
│   ├── lib
│   │   ├── alerts
│   │   ├── libraries
│   │   │   └── extensions/
│   │   │   │   ├── index.jsx 【★ 更新された】
│   │   │   │   ├── newblocks【★追加された】
│   │   │   │   │   ├── newblocks.png 【★ 追加された】
│   │   │   │   │   └── newblocks-small.png 【★ 追加された】
│   │   │   │   └── 【その他】
│   │   ├── log.js
│   ├── playground
│   ├── reducers
│   └── test.js
├── static
├── test
├── TRADEMARK
├── translations
├── webpack.config.js
├── yarn-error.log
└── yarn.lock

ここまできたら最後。1)の最後と同じように、GUIを起動します。
これでコンパイルが走り、うまく2)のブロックと3)のGUIがコンパイルされれば成功。

$ cd scratch-gui
$ yarn start

結果:

メニューを開くと、自分で作った拡張機能「NewBlocks」が表示されるので、クリックします。

image.png

そうすると、元の画面のアイコンの一番下にNewBlocksが追加されていて、その中に、log(hello)があります。

image.png

この新しいブロックをプログラムに追加して、旗(スタート)ボタンをおすと、右下のデバッグ画面に

vm hello

と出ています。

デバッグ画面は、ブラウザごとに違いますので、出し方はこちらw3schoolを参考にしてください。ChromeならF12キーで出てきます。

目的の「ログに書き出す」を達成したことがわかります。

ブロックの中の文字を変えてみてスタートを押してもちゃんと値が変わることが確認できますよね。
ちゃんとブロックが動いていますね。

公開する

すでにscratchのソースコードには公開するための仕掛けがついています。
やり方はこちらのWikiに書いてあります。

私の場合は、GitHub上でもとのレポジトリ(LKK/scratch-gui)をフォークして自分のレポジトリ(onelittlenightmusic/scratch-gui)を作成します。
上記で作成した開発環境のoriginを自分のレポジトリに変更します。

git remote add origin2 https://github.com/onelittlenightmusic/scratch-gui.git
git remote remove origin
git remote rename origin2 origin
yarn run build
yarn run deploy

すると、自分のレポジトリのなかで作成されたgithub pagesに公開されます。
(私の場合はhttps://onelittlenightmusic.github.io/scratch-gui/)

image.png

まとめ

できました。これまで私いろんな記事書きましたが、これまでになかった興奮です。

Scratch 3.0のブロックが作れてしまいました。しかもこんなにかんたんに。

さて、私のほうでは、バックエンドにGraphQLサーバを置いておき、apollo-linkを使って天気を取得するブロックも作ってみたりしてます。

image.png

Scratch猫くんがリアルタイムにNew yorkの天気を教えてくれますよ。

このやり方はまた別の機会に。

残課題

  • せっかく作ったブロックはみなリリースしたいはず。GUIとVMにまたがるこの修正箇所をいかにリリースできるしかけにするのか。Scratch teamが鋭意検討中とのこと。期待しましょう。私自身は、node-REDのようにnpmパッケージとして公開すれば、動的にロードできる、というふうになっているとベストと思います。

備考

Scratch自体は今8歳の娘が昔から結構触ってたのですが、それでもこれまでベータ版で公開されていたScratch 3.0を触らず嫌い。。これからは積極的に触ってもらおうと思います。

136
101
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
136
101

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?