Scratch 1.4 は Smalltalkで実装されており、モードを切り替えるとSmalltalkの開発環境を使うこともできます。GUIでは手間のかかる作業も、Smalltalkのコードを実行すれば簡単に一括処理できます。
注意
Smalltalkはとても自由度が高く、システムのコアな部分もいじることができます。その代償として壊れやすい環境でもあります。こまめな保存を心がけましょう。また、いじるまえの綺麗な環境も別途保管しておきましょう。
環境の保管方法はこちらを参照してください。
やりたいこと
例として、下記のスクリプトを持ったスプライトがあるとします。(このプロジェクトはこちらから取得できます)
変数"y"と"step"で表示位置や移動の速さが決まります。(この変数は「このスプライト用」)
このスプライトを何個もコピーして、それぞれのスプライトの変数y/step に異なる値を設定するのは手間ですね。Smalltalkを使えば一括でできます。
手順
-
Scratchを起動して、画面右上のSCRATCHのロゴの"R"の部分をShiftキーを押しながらクリックするとメニューが開きます。一番上の"turn fill screen off"をクリックします。
-
Smalltalkの開発環境が使えるモードになります。windowsの場合はAltを押しながらScratchのウィンドウをクリック(macの場合は右クリック)するとウィンドウのまわりに様々な色の丸が表示されます。この丸をハロ(halo)と言います。
-
ステージ上のスプライトを何回かAltクリック(macの場合は右クリック)してください。ハロが表示される箇所が狭まっていき、数回繰り返すと、スプライトのまわりにハロが表示され、スプライトの下に"ScratchSprite"と表示された状態になります。
-
ハロの右端の上から2番目のレンチのアイコンをクリックしてください。メニューが開くので、上から2番目の"inspect morph"をクリックします。
-
インスペクター(inspector)が開きます。画面上部でハロを表示していたものの中身の値が表示されます。画面下部の四角にはSmalltalkのコードを書いて、実行させることができます。枠をドラッグするとサイズの変更が可能です。
-
画面下部の四角に下記のコードをコピペしてください。
-
注意1: アンダースコアを入力すると矢印(←)が入力されます(2行目)。これは、Scratchを実行しているSmalltalkはかなり古いため、現在の流れにのれていない部分です。
-
注意2: マウスカーソルが枠外に出るとフォーカスが外れてしまうので注意してください。
インスペクタの中で実行.st(1 to: 10) do: [:i||sprite| sprite _ self fullCopy. sprite objName: 'copy-', i asString. sprite setVar: 'y' to: i*20; setVar: 'step' to: i*2. self owner addMorphFront: sprite. self owner sprites addLast: sprite. ]
7. 書いたコードをすべて選択してください。その後、Windowsの場合は右クリック、Macの場合はoption+クリックをしてメニューを開きます。メニューの真ん中あたりの"do it"をクリックすると、選択部分のコードが実行されます。選択された文字列がない場合はカーソル行が実行されます。また、Alt/Command + d のショートカットキーも用意されています。
![6_doit.png](https://qiita-image-store.s3.amazonaws.com/0/12251/659b6bf1-9156-8e65-533f-ad00ec1bbfcd.png)
8. スプライトがコピーされたはずです。旗をクリックすると、10個のスプライトが異なる位置と速さで移動します。
![7_run.png](https://qiita-image-store.s3.amazonaws.com/0/12251/1c23a40c-9e0b-e1c5-9642-84f233700ac5.png)
# 解説
今回の手順ではハロを使って対象を決めて、インスペクタを使ってその対象の中からSmalltalkのコードを実行しました。ハロが表示されたひとつひとつの対象はモーフ(Morph)と呼ばれます。モーフの中に子のモーフを持たせることができます。複数回ハロを表示する度にモーフが表示される範囲が狭まりましたが、それは親モーフから子モーフへ潜っていたのです。
インスペクタを開くとモーフの中身を覗くことができます。画面上部左側が何をもっているかの項目の一覧で、それをクリックすると、その内容が右側に表示されます。一番上の"self"は自分自身、上から二番目は"all inst vars"はすべての値を一辺に眺めるためのものです。3番目以降の項目を選択した状態で、Alt/Command+クリックでメニューを開き、"inspect"を選択すると、さらに別のインスペクタを開いて、その値の中身を覗くことができます。(Alt/Command+iのショートカットキーも用意されています。)
今、インスペクタで見ているデータをひとまとめにしたものを**オブジェクト(object)**と呼びます。モーフもオブジェクトですし、モーフが持っている値も数字や文字列もすべてオブジェクトです。Smalltalkはオブジェクトに対し、メッセージを送ることでプログラミングをします。
Smalltalkの文法の説明は割愛しますが、ざっくり何をやっているか、雰囲気だけ説明します。
```lang:インスペクタの中で実行.st
1 to: 10 do: [:i||sprite|
sprite _ self fullCopy.
sprite objName: 'copy-', i asString.
sprite setVar: 'y' to: i*20; setVar: 'step' to: i*2.
self owner addMorphFront: sprite.
self owner sprites addLast: sprite.
]
1行目は、1から10まで角カッコの中を繰り返すという意味です。"i" に1〜10の値が順番に入ります。spriteはローカル変数というもので角カッコの中で値を保持するために使用します。
2行目は、selfは自分自身を指します。インスペクタから実行しているので、selfはインスペクタで覗いているもの自身になります。self にfullCopyというメッセージを送ることで、コピーが生成され、spriteという変数に格納しています。このコピーはまだメモリ上にコピーされるだけで画面上には現れません。
3行目は、コピーに対してスプライトの名前を設定しています。実行される順番をわかりやすくするためにカッコをつけると下記のようになります。
sprite objName: ('copy-', (i asString)).
iという数字を文字にして'copy-'という文字とくっつけて、それをスクリプトの名前として設定しています。
4行目は、変数yとstepの値を設定しています。iは1〜10の値なので、iが大きい数字ほど上の方に表示されて、移動速度は速くなります。
5行目と6行目はスプライト名と変数を設定したコピーのスプライトを実際に画面上に配置しています。self owner
はこのスプライトの親モーフであるステージになります(ownerは所有者の意味)。ここで親モーフに対して、子モーフとしてコピーしたスプライトを配置され、実際に画面に表示されます。