レガシーコード生産ガイド

私に教えられることなら

Smalltalk(Squeak)でちょっと待つ

Squeak触っておこうと思って、自由自在 Squeakプログラミング PDF版を読み始めた。そのときやりたくなったことのメモ。

最初の方にこういうカンジのコードが出てきて

joe := Morph new.
joe openInWorld.
joe flash.
joe delete.

1行ずつ実行すると何やら物体が出てきて点滅するはずなんだけど、点滅だけしない。

システムブラウザでMorphを確認するとちゃんとflashしそうなコードがあるんだけど、眺めると色を変える事に成功した瞬間に次のメッセージを送ってるように見える。

高速過ぎて描画できてるかわからないのかな?と思って何度かflashメッセージを送ると、たまーに点滅してるのが分かる瞬間がある。色を変えたらsleep的なもので一瞬待つように書き換えれば、点滅がわかりそうだ。

できるだけシステム内で調べたいな、とDelayやPromise、waitで検索したけど使い方がよくわからなかった。全ソース中でDelay使ってるとこを調べる方法とか無いのかな?とりあえずSqueak Etoys4のスレッド化 - PukiWikiを参考にして書いてみる。

リンク先にも書いてある通り、

  • Delay forMilliseconds: nなどでdelayインスタンスを作る
  • そのインスタンスwaitメッセージを送ると、メッセージを送ったプロセスが一時停止する
  • GUIを動かしているプロセスが止まると何もできなくなるので、ブロックと、ブロックへのforkメッセージを使って別プロセスを作り、それを止める

という手段で目的は達成できた。

ちょっとメソッドが大きくなるので、Morphに今の色から反転させるnegateColorメソッドも追加する。

negateColor
    | negatedColor |
    negatedColor := (self color
            ifNil: [ Color black ]
            ifNotNil: [ ((self color) alpha: 1) negated ]).
    self color: negatedColor.

flash
    | originalColor |
    originalColor := self color.
    [ self negateColor ]
        ensure:
            [ [ (Delay forMilliseconds: 30) wait.
                self world ifNotNil: [ : w | w displayWorldSafely ].
                self color: originalColor. ] fork ]

試してみる。ついでに色もランダムに変える。

joe := Morph new.
joe openInWorld.
joe color: (Color random).
joe flash.
joe delete.

楽しい!

ゲームのupdateループなんかは、forkさせてdelayさせればいいのかな。でもせっかくなので、そういう手続きを重視した作り方するよりも、時間オブジェクトとか時間を監視してキャラクタを動かすObserverとかで組んだほうが楽しいかもしれない。

広告を非表示にする