読者です 読者をやめる 読者になる 読者になる

osiire’s blog

ふしぎなそふとやさん

壁を侵略しなイカ?


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)  (* 矢印を動かすでゲソ *)

イベント処理も関数型イカ娘が侵略したでゲソ!