SmalltalkからScratchをいじる(4) スプライトをドラッグさせた時の軌道を記録/再生

[前回](http://qiita.com/maeda_/items/0a9ddc5c3816d4a94463)はスプライトの位置をトランススクリプトに出力していましたが、今回はスプライトの位置をScratchのリストに追加します。
（Smalltalkを使えるようにする方法等は[こちら](http://qiita.com/maeda_/items/7a525cae6b3c1ca45773)を参照）

※今回はScratchのコードをいじりませんが、必ずバックアップはとっておきましょう。（バックアップ手順は[こちら](http://qiita.com/maeda_/items/7076dc32816259a0117a)）

# やりたいこと
下記のスクリプトがあるとします。（[ここ](https://dl.dropboxusercontent.com/u/55482425/path.sb)からダウンロードできます。）
![script.png](https://qiita-image-store.s3.amazonaws.com/0/12251/f64652c5-9686-aeac-3cdc-1d98c55228bf.png)


paths-xとpaths-yというリストの値を順に取り出して、X座標,Y座標として移動します。(このスクリプトだと、リストの最後の要素を見る前にindexが1に戻ってしまいますが、細かいことは気にしない)

リストの値を一つ一つ入力してたら大変です。今回は、スプライトをドラッグした時の軌道をスプライトの変数に格納するSmalltalkのコードを記述します。

# 手順
1. 背景をクリックし、open → transcript からトランスクリプトを表示しておきます。
![transcript.png](https://qiita-image-store.s3.amazonaws.com/0/12251/6f39aaa6-a15f-1446-f552-291175aa321c.png)

2. スプライトのハロを開き、レンチのアイコンからインスペクタを開きます。
![1_halo.png](https://qiita-image-store.s3.amazonaws.com/0/12251/51e2a53b-b707-90ce-e42e-1f0cd63a8c0c.png)
3. インスペクタから下記のコードを入力し、実行(do it)します。(Alt/Command + d)

    ```lang:インスペクタの中で実行.st
    [
      #('paths-x'  'paths-y') do:[:variableName|
        [(self lineCountOfList: variableName) = 0] whileFalse:[
          self deleteLine: 1 ofList: variableName
        ]
      ].
      
      Transcript show: 'recording.'.
      100 timesRepeat:[
        (self owner isKindOf: HandMorph) ifTrue:[
          self append: self xpos toList: 'paths-x'.
          self append: self ypos toList: 'paths-y'.
          Transcript show: '.'
        ].
        (Delay forMilliseconds: 100) wait
      ].
      Transcript show: 'done!';cr
    ] fork
```

4. 実行してからの10秒間のうちにスプライトをドラッグすると、随時、スプライトの位置がリストに追加されていきます。トランスクリプトに記録開始時には'recording.'と表示され、位置が記録される度に'.'を追加、10秒たつと'done!'と表示されて記録が終了します。
5. 旗をクリックすると、記録された軌道にそってスプライトが動きます。
![path.png](https://qiita-image-store.s3.amazonaws.com/0/12251/7d1a9fb9-1617-9b34-4406-c04dbc91d238.png)

# 解説
doitなどで実行すると、実行したコードが完了するまで待ちます。```[ ... ] fork ```で囲うとその中の処理の完了を待たずに、裏で実行されます。```[ ... ] fork```なしで実行してみると処理が終わるまでの10秒間動かなくなることが確認できます。

forkの中身はリストの内容を削除する部分とリストに現在位置を入れる部分に分かれます。
リストの要素の削除のSmalltalkのコードをScratchのブロックと対応させるとこんな感じです。
![delete.png](https://qiita-image-store.s3.amazonaws.com/0/12251/aa97d709-2472-ec2f-97ff-0149ea1f80a9.png)

```リストの全要素削除.st
[(self lineCountOfList: 'paths-x') = 0] whileFalse:[
  self deleteLine: 1 ofList: 'paths-x'
]
```
手順3.で実行したコードは、'paths-x'と'paths-y'という”変数名”をvariableNameという変数に入れて、要素の削除をしています。

一方、リストに値を格納する部分をSmalltalkとScratchで対応させるとこんな感じです。
![add-list.png](https://qiita-image-store.s3.amazonaws.com/0/12251/6ec75c2a-cbb5-4ab9-72da-a47fed32831d.png)

```リストの要素追加.st
100 timesRepeat:[
  (self owner isKindOf: HandMorph) ifTrue:[
    self append: self xpos toList: 'paths-x'.
    self append: self ypos toList: 'paths-y'
  ].
  (Delay forMilliseconds: 100) wait
]
```
```(self owner isKindOf: HandMorph)```の部分がドラッグ中かどうかの判断になります。ドラッグ中かの判断は親モーフのクラスで判断しています。ステージ上にスプライトが置かれている状態では親モーフはステージになりますが、ドラッグを開始するとHandMorphというカーソルを表すモーフが親モーフになります。(インスペクタでownerの値を見ることで確認できます。)
isKindOf: メソッドで親モーフがHandMorphなのかを調べます。

リストに値を追加したり、値を削除したりするSmalltalkのコードは実際のScratchのブロックの中身を見て調べました。次回はブロックの中身からSmalltalkのどのコードが呼ばれるかを確認する方法を紹介します。