GHCで直接アニメーションできるようにする


2013年 01月 17日

今回、第6週は、今までの復習なので、無視して第7週に進むのだが、ちょっとだけ取り上げることがある。
それは、前回、星条旗の宿題が出たが、これに対して、こんなキーボードをSophiaは描いたのだ。
う?む、まだわずかな知識しかあたえていないのに、こういう絵を作るセンスの良さに感心だ。

keyboard.png
さて、第7週に入る。ここで、やっと絵が動き出すのだ。

ここでも、Haskell+Glossで試せるページ
http://dac4.designacourse.com:8000/sim
が利用されるのだが、ちょっとだけ違う。
今までは、Pictureアイコンをクリックして、ソースを入れるページを出していたのだが、
今度は、Animationアイコンをクリックするのだ。

すると、以下のソースが出てくる。

import Graphics.Gloss

data BallState = BallAt Float Float
initial _           = BallAt 100 0
step t (BallAt x v) = BallAt (x+v*t) (0.99*v-x*t)
draw   (BallAt x v) = translate x x (circle 20)

右下の [Run]ボタンを押すと、円が 右上⇔左下 を往復運動する。動きは徐々に悪くなり、そのうち画面中央に停止する。

ということで、とりあえず、以上のような書き方で、アニメーションができるようなのだ。

さて、授業で教える最初のアニメーションのソースはこれなのだ。
importの行だけを残し、残りを

animation t = rotate (60 * t) (rectangleSolid 100 100)

に置き換えるだけで、一辺100の黒い正方形が、反時計回りにぐるぐる回りつづけるのだ。

今は、ブラウザ上で動いているだけなのだが、これを、Pictureでやったときと同様にGHC単独で動くようにしたいのだ。

そうなると、日本語での説明を無駄に探すより、Graphics.Gloss のちゃんとしたドキュメントを読むべきだ。
このところHaskell関係はバージョンがよく変わっているので要注意である。
探し当てたのが、つぎのドキュメントだ。

gloss-1.7.4.1: Painless 2D vector graphics, animations and simulations

これにより、今までの 関数displayの代わりに、animateを使わないといけないことが分かる。
まず、関数animateの型定義を見てみよう。

Prelude Graphics.Gloss > :t animate
animate :: Display - > Color - > (Float - > Picture) - > IO ()

さらに、Display を調べようとすると、

Prelude Graphics.Gloss > :t Display

<interactive >:1:1: Not in scope: data constructor `Display'
Prelude Graphics.Gloss > 

となって、叱られてしまった。
ドキュメントを見ると、Displayは静止画用の関数displayのときと同じということが分かって、一件落着。

以上をまとめて、1つのhsファイルにしてみた。

import Graphics.Gloss

animation t = rotate (60 * t) (rectangleSolid 100 100)

main = animate (InWindow "Animation" (200, 200) (10,10)) white animation

最初はライブラリのインポート、最後はmainの行で、関数animateを使って、アニメーションを実現している。
この最後の関数型の引数の名前を animation にすることで、授業のプログラムとの整合性をとっている。

animation t の定義は、授業と一緒なので、この部分を次々と変更していけば、良いはずだ。

これを動かすと、こんな絵が得られる。

sample13.png
やはり、一辺100の黒い正方形が、時計回りにぐるぐる回りつづけるのだ。

ん、でもおかしい。
Web上のでやったときは、反時計回りだったのに、今度は時計回り、つまり回転方向が逆になってしまった。
なぜだろう。理由が分からないので、今日はここまでとしよう。