1.概略
キーボードの利用の仕方を覚えたので、石の発射位置を右矢印キーと左矢印キーで変えられるようにする。ゲームのデモを見たほうが早いので、ゲームを行っているときのビデオを下に挙げておく(発射位置の設定が悪く、今回は鳥にうまく当たっていない。この結果を見て、次の試行では、発射位置を少し変えればよい。これまでのプログラムはゲームとは言えないものだったが、今回の新しい機能が加わったことで、はじめてゲーム的な要素が加味された)。
このビデオで、右矢印キーを押し下げるたびごとにと右側に0.5mずつ進む。左矢印キーを押し下げたときは反対側に同じように進む。発射位置を定めた後、PgUpキーを押し下げると石が発射される。
2.プログラム化
修正しなければならない場所は、石を発射させるまでの振舞いを記述した信号関数stayingBallだけである。この信号関数で、PgUpキーに加えて、右矢印きーと左矢印キーが押し下げられたかを検出する。右矢印キーが押し下げられた場合には、発射位置を0.5m右にずらす。左矢印キーが押し下げられた場合にも同様の処理をする。その後、どちらの場合にも、新たな位置を入力としてstayingBallを実行する。
なお、イベントが3種類あるので、どのイベントが発生したかがわかるようにする必要がある。そこで、イベントからの戻りに対しては、イベントの番号を教えるnoを用意した。これによって、イベントが発生したときにswitchで切り替わる信号関数が確実に得られるようになった。
プログラムは次のようになる。比較のため、変更前も一緒に挙げた。
stayingBall :: Pos -> Vel -> SF ObjEvents (Pos, Vel) stayingBall pos0 vel0 = switch (flyaway pos0 vel0) (\ (pos, vel, no) -> if no == 3 then bouncingBall pos vel else stayingBall pos vel) where flyaway :: Pos -> Vel -> SF ObjEvents ((Pos, Vel), Event(Pos, Vel, Integer)) flyaway pos0' vel0' = proc input -> do rec evt1 <- edge -< isEvent (rightEvs (oeInput input)) evt2 <- edge -< isEvent (leftEvs (oeInput input)) evt3 <- edge -< isEvent (upEvs (oeInput input)) returnA -< ((pos0', vel0'), if evt1 /= NoEvent then evt1 `tag` (((fst pos0') + 0.5, snd pos0'), vel0', 1) else if evt2 /= NoEvent then evt2 `tag` (((fst pos0') - 0.5, snd pos0'), vel0', 2) else evt3 `tag` (pos0', vel0', 3)) {-- stayingBall :: Pos -> Vel -> SF ObjEvents (Pos, Vel) stayingBall pos0 vel0 = switch (flyaway pos0 vel0) (\ (pos, vel) -> bouncingBall pos vel) where flyaway pos0' vel0' = proc input -> do rec evt <- edge -< isEvent (upEvs (oeInput input)) returnA -< ((pos0', vel0'), evt `tag` (pos0', vel0')) --}
なお、鳥が飛ぶ立つ位置よりも石の発射場所が右側にあることを想定し、石が鳥に当ることが起こりえるように、先のデモでは、mainに記載される鳥の速度を4から6に変更した。