壁を侵略しなイカ?
http://partake.in/events/5784afd8-d43b-4cbe-9256-430d5ababa2bに参加でゲソ。
この画像は、関数型イカ娘が触手を使って壁を侵略するゲームでゲソ。壁が下から上に強制スクロールするので、触手はそれを左右に避けて進むでゲソ!前にも見たことある人は気にしないでいいんじゃなイカ。今回は、このゲーム作成に使っているfunctionalなテクニックを紹介するでゲソ!
ソースコードは、[ccell] View of /trunk/example/downdown.mlに置いてあるでゲソ。実際に動かしてみないと解説が分かりにくいかもしれないでゲソ。動画を撮ってアップする余力はosiireには無いんじゃなイカ?そういえば、触手を青くするのを忘れていて悔やんでいるでゲソ。
中央の触手は赤い部分が先頭で、そこから後ろの部分は先頭の矢印の軌跡でゲソ。そのロジックを表現しているのがこれでゲソ。
ps = (* 触手. (int * int) list R.tでゲソ *) pos (* 先頭の矢印の位置でゲソ. (int*int) R.tでゲソ *) (* x座標が変わった時だけをイベントとして抽出するでゲソ *) +> R.changes ~eq:(fun loc1 loc2 -> (fst loc1) = (fst loc2)) +> E.react init_loc (* イベントを値に変換するでゲソ *) +> R.history arrow_height (* arrow_hight個だけ矢印の移動の歴史をとるでゲソ. *) (* 歴史だからlistでゲソ *)
ポイントは、元の触手先頭(pos)がreactiveな値なので、posが変わると自動的に触手(ps)も変わるところだゲソ!で、このpsを使っての画面表示は簡単じゃなイカ。
let draw color t = (* 触手を描画するでゲソ *) iteri (draw_v color) (R.read t.ps) (* reactiveな値(ps)をread関数で読み出して描画するでゲソ *)
他にも、キーボードからの入力はfilter_mapで処理しているでゲソ。
key_event (* キーボードイベントでゲソ *) +> E.fmap (fun c -> if (Mode.get ()) = Mode.Playing then if c = 'j' then (* 矢印を左へ動かす関数でゲソ *) Some Arrow.move_left else if c = 'k' then (* 矢印を右へ動かす関数でゲソ *) Some Arrow.move_right else None (* filter_mapなので、Noneを返すとイベントが上がらないでゲソ *) else None) +> E.listen (fun f -> f env.arrow) (* 矢印を動かすでゲソ *)
イベント処理も関数型イカ娘が侵略したでゲソ!