簡単なゲームをOCamlで作ります。

この記事はML Advent Calendar 2014の5日目の記事です。

そういうことで(どういう事だ?)、OCamlでゲームを作ってみました。 ボス的な動きを作り込もうという事で、色々弄ってみてたってだけですけど。

ビルド方法

$ ocamlopt -I `ocamlfind query lablgl` lablgl.cmxa lablglut.cmxa d.ml -o d
$ ./d

lablglとlablglutがインストールされていれば、上のように書いていろいろできます。

遊び方

    let enemy = Enemy.new_ ()
      
    let enemy = Boss.new_ ()
      
    let enemy = Enemy3.new_ ()
      
    let enemy = Boss2.new_ ()
      
    let enemy = Boss3.new_ ()

ソースのこの辺を弄ると、表示される敵が変わります。

ソースコード

d.ml

open Printf
  
let width = 400.0
  
let height = 400.0
  
let pi = 4.0 *. (atan 1.0)
  
let normalize v =
  v +.
    ((2.0 *. pi) *.
       (if v > pi then (-1.) else if v < (-. pi) then 1. else 0.))
  
type state = | Title | GameOver | Game

let state = ref Title
  
let gstring str x y size =
  let getChar t1' =
    match t1' with
    | '0' ->
        [ "0000000 "; "0     0 "; "0  0  0 "; "0     0 "; "0     0 ";
          "0000000 " ]
    | '1' ->
        [ "      0 "; "      0 "; "      0 "; "      0 "; "      0 ";
          "      0 " ]
    | '2' ->
        [ "0000000 "; "      0 "; "0000000 "; "0       "; "0       ";
          "0000000 " ]
    | '3' ->
        [ "0000000 "; "      0 "; "0000000 "; "      0 "; "      0 ";
          "0000000 " ]
    | '4' ->
        [ "0     0 "; "0     0 "; "0000000 "; "      0 "; "      0 ";
          "      0 " ]
    | '5' ->
        [ "0000000 "; "0       "; "0000000 "; "      0 "; "      0 ";
          "0000000 " ]
    | '6' ->
        [ "0000000 "; "0       "; "0000000 "; "0     0 "; "0     0 ";
          "0000000 " ]
    | '7' ->
        [ "0000000 "; "      0 "; "      0 "; "      0 "; "      0 ";
          "      0 " ]
    | '8' ->
        [ "0000000 "; "0     0 "; "0000000 "; "0     0 "; "0     0 ";
          "0000000 " ]
    | '9' ->
        [ "0000000 "; "0     0 "; "0000000 "; "      0 "; "      0 ";
          "      0 " ]
    | 'a' ->
        [ "   0000 "; "  0   0 "; " 000000 "; "0     0 "; "0     0 ";
          "0     0 " ]
    | 'b' ->
        [ "000000  "; "0     0 "; "000000  "; "0     0 "; "0     0 ";
          "000000  " ]
    | 'c' ->
        [ "  00000 "; " 0      "; "0       "; "0     0 "; "0     0 ";
          " 00000  " ]
    | 'd' ->
        [ "000000  "; "0     0 "; "0     0 "; "0     0 "; "0    0  ";
          "00000   " ]
    | 'e' ->
        [ "0000000 "; "0       "; "000000  "; "0       "; "0       ";
          "0000000 " ]
    | 'f' ->
        [ "0000000 "; "0       "; "000000  "; "0       "; "0       ";
          "0       " ]
    | 'g' ->
        [ "  00000 "; " 0      "; "0  0000 "; "0     0 "; "0     0 ";
          " 00000  " ]
    | 'h' ->
        [ "0     0 "; "0     0 "; "0000000 "; "0     0 "; "0     0 ";
          "0     0 " ]
    | 'i' ->
        [ " 00000  "; "   0    "; "   0    "; "   0    "; "   0    ";
          " 00000  " ]
    | 'j' ->
        [ "    000 "; "      0 "; "      0 "; "      0 "; "0    0  ";
          " 0000   " ]
    | 'k' ->
        [ "0    00 "; "0  00   "; "000     "; "0  0    "; "0   0   ";
          "0    00 " ]
    | 'l' ->
        [ "0       "; "0       "; "0       "; "0       "; "0       ";
          "0000000 " ]
    | 'm' ->
        [ "0     0 "; "000 000 "; "0  0  0 "; "0     0 "; "0     0 ";
          "0     0 " ]
    | 'n' ->
        [ "000   0 "; "0  0  0 "; "0   0 0 "; "0    00 "; "0     0 ";
          "0     0 " ]
    | 'o' ->
        [ " 00000  "; "0     0 "; "0     0 "; "0     0 "; "0    0  ";
          " 0000   " ]
    | 'p' ->
        [ "0000000 "; "0     0 "; "000000  "; "0       "; "0       ";
          "0       " ]
    | 'q' ->
        [ " 00000  "; "0     0 "; "0     0 "; "0   0 0 "; "0    0  ";
          " 0000 0 " ]
    | 'r' ->
        [ "0000000 "; "0     0 "; "000000  "; "0   0   "; "0    0  ";
          "0     0 " ]
    | 's' ->
        [ " 000000 "; "0       "; "000000  "; "      0 "; "0    0  ";
          " 0000   " ]
    | 't' ->
        [ "0000000 "; "0  0  0 "; "   0    "; "   0    "; "   0    ";
          " 00000  " ]
    | 'u' ->
        [ "0     0 "; "0     0 "; "0     0 "; "0     0 "; "0    0  ";
          " 0000   " ]
    | 'v' ->
        [ "0     0 "; "0     0 "; "0    0  "; "0   0   "; "0  0    ";
          "000     " ]
    | 'w' ->
        [ "0     0 "; "0     0 "; "0  0  0 "; "0 0 0 0 "; "00   00 ";
          "0     0 " ]
    | 'x' ->
        [ "00   00 "; "  0 0   "; "   0    "; "  0 0   "; " 0   0  ";
          "0     0 " ]
    | 'y' ->
        [ "00   00 "; "  0 0   "; "   0    "; "   0    "; "   0    ";
          "  000   " ]
    | 'z' ->
        [ "0000000 "; "    0   "; " 00000  "; "  0     "; " 0      ";
          "0000000 " ]
    | _ ->
        [ "        "; "        "; "        "; "        "; "        ";
          "        " ] in
  let gchar c x y size =
    ignore
      (List.fold_left
         (fun t1' t2' ->
            match (t1', t2') with
            | (n, s) ->
                let num = ref 0
                in
                  (String.iteri
                     (fun t1' t2' ->
                        match (t1', t2') with
                        | (i, c) ->
                            if c = '0'
                            then incr num
                            else
                              if !num > 0
                              then
                                (let i = float_of_int (x + (i * size)) in
                                 let n = float_of_int (y + (n * size)) in
                                 let s = float_of_int size
                                 in
                                   (GlDraw.rect
                                      ((i -. ((float_of_int (!num - 1)) *. s)),
                                       n)
                                      ((i +. s), (n +. s));
                                    num := 0))
                              else ())
                     s;
                   n + 1))
         0 (getChar c))
  in
    String.iteri
      (fun t1' t2' ->
         match (t1', t2') with
         | (i, c) -> gchar c ((i * size) * 7) size (size - 1))
      str
  
module Key =
  struct
    let up = ref false
      
    let down = ref false
      
    let left = ref false
      
    let right = ref false
      
    let z = ref false
      
    let tz = ref false
      
    let onSpKeyDown ~key ~x ~y =
      match key with
      | Glut.KEY_UP -> up := true
      | Glut.KEY_DOWN -> down := true
      | Glut.KEY_LEFT -> left := true
      | Glut.KEY_RIGHT -> right := true
      | _ -> ()
      
    let onSpKeyUp ~key ~x ~y =
      match key with
      | Glut.KEY_UP -> up := false
      | Glut.KEY_DOWN -> down := false
      | Glut.KEY_LEFT -> left := false
      | Glut.KEY_RIGHT -> right := false
      | _ -> ()
      
    let onKeyDown ~key ~x ~y =
      match char_of_int key with | 'z' -> (tz := true; z := true) | _ -> ()
      
    let onKeyUp ~key ~x ~y =
      match char_of_int key with | 'z' -> z := false | _ -> ()
      
    let reset () = tz := false
      
    let init () =
      (Glut.specialFunc onSpKeyDown;
       Glut.specialUpFunc onSpKeyUp;
       Glut.keyboardFunc onKeyDown;
       Glut.keyboardUpFunc onKeyUp)
      
  end
  
type actor =
  | BG
  | Enemy of (((actor -> actor) ref) * (float ref) * (float ref))
  | Enemy2 of
              (((actor -> actor) ref) * (float ref) * (float ref) *
               ((int ref) * (float ref)))
  | Enemy3 of
              (((actor -> actor) ref) * (float ref) * (float ref) *
               ((int ref) * (float ref)))
  | Child of ((float ref) * (float ref))
  | Boss of
            (((actor -> actor) ref) * (float ref) * (float ref) *
             ((float ref) * (((float * float) list) ref) *
              ((actor list) ref)))
  | Boss2 of
             (((actor -> actor) ref) * (float ref) * (float ref) *
              ((float ref) * (((float * float) list) ref) *
               ((actor list) ref)))
  | Child3 of ((float ref) * (float ref))
  | Boss3 of
             (((actor -> actor) ref) * (float ref) * (float ref) *
              ((float ref) * (((float * float) list) ref) *
               ((actor list) ref)))

module Actor =
  struct
    let move e =
      match e with
      | BG -> (printf "BG\n"; e)
      | Enemy (m, _, _) -> !m e
      | Enemy2 (m, _, _, _) -> !m e
      | Enemy3 (m, _, _, _) -> !m e
      | Child (_, _) -> e
      | Child3 (_, _) -> e
      | Boss (m, _, _, _) | Boss2 (m, _, _, _) -> !m e
      | Boss3 (m, _, _, _) -> !m e
      
    let rec draw e =
      match e with
      | BG -> ()
      | Enemy (m, x, y) ->
          (GlDraw.color (1.0, 0.0, 0.0);
           let rsize = 10.
           in GlDraw.rect ((!x), (!y)) ((!x +. rsize), (!y +. rsize)))
      | Child (x, y) ->
          (GlDraw.color (1.0, 0.0, 0.0);
           let rsize = 10.
           in
             GlDraw.rect ((!x -. rsize), (!y -. rsize))
               ((!x +. rsize), (!y +. rsize)))
      | Enemy2 (m, x, y, _) | Enemy3 (m, x, y, _) ->
          (GlDraw.color (1.0, 0.0, 0.0);
           let rsize = 10.
           in GlDraw.rect ((!x), (!y)) ((!x +. rsize), (!y +. rsize)))
      | Boss (m, x, y, (cnt, _, cs)) ->
          (GlDraw.color (1.0, 0.0, 0.0);
           let rsize = 10.
           in
             (GlDraw.rect ((!x -. rsize), (!y -. rsize))
                ((!x +. rsize), (!y +. rsize));
              List.iter (fun t1' -> match t1' with | c -> draw c) !cs))
      | Boss2 (m, x, y, (cnt, _, cs)) ->
          (GlDraw.color (1.0, 0.0, 0.0);
           let rsize = 20.
           in
             (GlDraw.rect ((!x -. rsize), (!y -. rsize))
                ((!x +. rsize), (!y +. rsize));
              List.iter (fun t1' -> match t1' with | c -> draw c) !cs))
      | Child3 (x, y) ->
          (GlDraw.color (1.0, 0.0, 0.0);
           let rsize = 15.
           in
             GlDraw.rect ((!x -. rsize), (!y -. rsize))
               ((!x +. rsize), (!y +. rsize)))
      | Boss3 (m, x, y, (cnt, _, cs)) ->
          (GlDraw.color (0.7, 0.7, 0.7);
           let h = 10. in
           let w = 240.
           in
             (GlDraw.rect ((!x -. w), (!y -. h)) ((!x +. w), (!y +. h));
              GlDraw.color (0.8, 0.8, 0.8);
              let h = 50. in
              let w = 40.
              in
                (List.iter
                   (fun t1' ->
                      match t1' with
                      | Child3 (x, y) ->
                          GlDraw.rect ((!x -. w), (!y -. h))
                            ((!x +. w), (!y +. h)))
                   !cs;
                 List.iter
                   (fun t1' ->
                      match t1' with | (Child3 (x, y) as c) -> draw c)
                   !cs)))
      
  end
  
module BG = struct let new_ () = BG
                      end
  
module Enemy =
  struct
    let rec new_ () = Enemy ((ref move1), (ref 0.), (ref 0.))
    and move1 e =
      match e with
      | Enemy (m, x, y) ->
          (x := !x +. 5.; if !x > height then m := move2 else (); e)
      | _ -> assert false
    and move2 e =
      match e with
      | Enemy (m, x, y) ->
          (x := !x -. 5.; if !x <= 0. then m := move1 else (); e)
      | _ -> assert false
      
  end
  
module Child = struct let rec new_ x y = Child ((ref x), (ref y))
                         end
  
module Boss =
  struct
    let poses = ref
      
    let rec new_ () =
      let rec list_make t1' t2' t3' =
        match (t1', t2', t3') with
        | (0, ls, v) -> ls
        | (n, ls, v) -> list_make (n - 1) ((v ()) :: ls) v in
      let n = 10 in
      let childs =
        list_make n [] (fun t1' -> match t1' with | () -> Child.new_ 10. 10.) in
      let lasts =
        list_make (3 * n) [] (fun t1' -> match t1' with | () -> (10., 10.))
      in
        Boss ((ref move1), (ref 10.), (ref 10.),
          ((ref 0.), (ref lasts), (ref childs)))
    and moveChilds ls childs =
      let _ =
        List.fold_left
          (fun t1' t2' ->
             match (t1', t2') with
             | (n, Child (x, y)) ->
                 let _ =
                   (match List.nth ls n with | (x1, y1) -> (x := x1; y := y1))
                 in n + 3
             | _ -> assert false)
          0 childs
      in ()
    and move1 this =
      match this with
      | Boss (m, x, y, (c, ls, childs)) ->
          (c := !c +. 0.1;
           ls := (List.tl !ls) @ [ ((!x), (!y)) ];
           x := !x +. 5.;
           y := !y +. ((sin !c) *. 10.);
           if !x > (width -. 20.) then m := move2 else ();
           moveChilds !ls !childs;
           this)
      | _ -> assert false
    and move2 this =
      match this with
      | Boss (m, x, y, (c, ls, childs)) ->
          (c := !c +. 0.1;
           ls := (List.tl !ls) @ [ ((!x), (!y)) ];
           x := !x -. 5.;
           y := !y +. ((sin !c) *. 10.);
           if !x <= 10. then m := move1 else ();
           moveChilds !ls !childs;
           this)
      | _ -> assert false
      
  end
  
module Shots =
  struct
    let shots = ref []
      
    let add x y =
      if (List.length !shots) < 16 then shots := (x, y) :: !shots else ()
      
    let move () =
      let ss =
        List.map (fun t1' -> match t1' with | (x, y) -> (x, (y -. 20.)))
          !shots
      in
        shots :=
          List.filter (fun t1' -> match t1' with | (x, y) -> y > 0.) ss
      
    let draw () =
      let rsize = 2.0
      in
        (GlDraw.color (1.0, 1.0, 0.0);
         List.iter
           (fun t1' ->
              match t1' with
              | (x, y) ->
                  GlDraw.rect ((x -. rsize), (y -. rsize))
                    ((x +. rsize), (y +. rsize)))
           !shots)
      
  end
  
module Child3 = struct let rec new_ x y = Child3 ((ref x), (ref y))
                          end
  
module Boss3 =
  struct
    let rec new_ () =
      let lasts =
        [ ((-80.), (-20.)); ((-30.), 20.); (30., 20.); (80., (-20.)) ] in
      let n = 3 in
      let childs =
        [ Child3.new_ (-0.) 0.; Child3.new_ 0. 0.; Child3.new_ 0. 0.;
          Child3.new_ 0. 0. ]
      in
        Boss3 ((ref move1), (ref 10.), (ref 10.),
          ((ref 0.), (ref lasts), (ref childs)))
    and moveChilds xa ya ls childs =
      let _ =
        List.fold_left
          (fun t1' t2' ->
             match (t1', t2') with
             | (n, Child (x, y)) ->
                 let _ =
                   (match List.nth ls n with
                    | (x1, y1) -> (x := xa +. x1; y := ya +. y1))
                 in n + 1
             | (n, Child3 (x, y)) ->
                 let _ =
                   (match List.nth ls n with
                    | (x1, y1) -> (x := xa +. x1; y := ya +. y1))
                 in n + 1
             | _ -> assert false)
          0 childs
      in ()
    and move1 this =
      match this with
      | Boss3 (m, x, y, (c, ls, childs)) ->
          (c := !c +. 0.1;
           x := !x +. 5.;
           y := !y +. ((sin !c) *. 10.);
           if !x > (width -. 20.) then m := move2 else ();
           moveChilds !x !y !ls !childs;
           this)
      | _ -> assert false
    and move2 this =
      match this with
      | Boss3 (m, x, y, (c, ls, childs)) ->
          (c := !c +. 0.1;
           x := !x -. 5.;
           y := !y +. ((sin !c) *. 10.);
           if !x <= 10. then m := move1 else ();
           moveChilds !x !y !ls !childs;
           this)
      | _ -> assert false
      
  end
  
module Ship =
  struct
    let rsize = 25.
      
    let x = ref ((width -. rsize) /. 2.)
      
    let y = ref (height -. (rsize *. 2.0))
      
    let speed = 5.
      
    let bllets = ref
      
    let move () =
      let m = 5 in
      let m = if !Key.left then m - 1 else m in
      let m = if !Key.right then m + 1 else m in
      let m = if !Key.up then m - 3 else m in
      let m = if !Key.down then m + 3 else m
      in
        (if !Key.z then Shots.add !x !y else ();
         Shots.move ();
         let speed =
           match m with | 1 | 3 | 7 | 9 -> speed /. 1.4 | _ -> speed in
         let (nx, ny) =
           match m with
           | 1 -> ((!x -. speed), (!y -. speed))
           | 2 -> ((!x), (!y -. speed))
           | 3 -> ((!x +. speed), (!y -. speed))
           | 4 -> ((!x -. speed), (!y))
           | 5 -> ((!x), (!y))
           | 6 -> ((!x +. speed), (!y))
           | 7 -> ((!x -. speed), (!y +. speed))
           | 8 -> ((!x), (!y +. speed))
           | 9 -> ((!x +. speed), (!y +. speed))
           | _ -> ((!x), (!y))
         in
           (x := min (max nx 0.) (width -. rsize);
            y := min (max ny 0.) (height -. rsize)))
      
    let draw () =
      (GlDraw.rect ((!x -. (rsize /. 2.)), (!y -. (rsize /. 2.)))
         ((!x +. (rsize /. 2.)), (!y +. (rsize /. 2.)));
       Shots.draw ())
      
  end
  
module Boss2 =
  struct
    let speed = 3.0
      
    let r = 0.025
      
    let span = 15
      
    let fabs a = if a < 0. then -. a else a
      
    let poses = ref
      
    let move m rad x y x1 y1 next =
      let rad2 = atan2 (y1 -. !y) (x1 -. !x) in
      let rad2 =
        if (normalize (!rad -. rad2)) <= 0. then !rad +. r else !rad -. r in
      let rad2 = normalize rad2
      in
        (x := !x +. ((cos rad2) *. speed);
         y := !y +. ((sin rad2) *. speed);
         if ((fabs (!x -. x1)) < 10.) && ((fabs (!y -. y1)) < 10.)
         then m := next
         else ();
         rad := rad2)
      
    let rec new_ () =
      let rec list_make t1' t2' t3' =
        match (t1', t2', t3') with
        | (0, ls, v) -> ls
        | (n, ls, v) -> list_make (n - 1) ((v ()) :: ls) v in
      let x = 200. in
      let y = (-10.) in
      let n = 14 in
      let childs =
        list_make n [] (fun t1' -> match t1' with | () -> Child.new_ x y) in
      let lasts =
        list_make (span * n) [] (fun t1' -> match t1' with | () -> (x, y))
      in
        Boss2 ((ref move1), (ref x), (ref y),
          ((ref 0.), (ref lasts), (ref childs)))
    and moveChilds ls childs =
      let _ =
        List.fold_left
          (fun t1' t2' ->
             match (t1', t2') with
             | (n, Child (x, y)) ->
                 let _ =
                   (match List.nth ls n with | (x1, y1) -> (x := x1; y := y1))
                 in n + span
             | _ -> assert false)
          0 childs
      in ()
    and move1 this =
      match this with
      | Boss2 (m, x, y, (rad, ls, childs)) ->
          (ls := (List.tl !ls) @ [ ((!x), (!y)) ];
           move m rad x y 20. 380. move2;
           moveChilds !ls !childs;
           this)
      | _ -> assert false
    and move2 this =
      match this with
      | Boss2 (m, x, y, (rad, ls, childs)) ->
          (ls := (List.tl !ls) @ [ ((!x), (!y)) ];
           move m rad x y !Ship.x !Ship.y move1;
           moveChilds !ls !childs;
           this)
      | _ -> assert false
      
  end
  
module Enemy3 =
  struct
    let speed = 6.0
      
    let r = 0.15
      
    let fabs a = if a < 0. then -. a else a
      
    let move m rad cnt mx x y x1 y1 next =
      let rad2 = atan2 (y1 -. !y) (x1 -. !x) in
      let rad2 =
        if (normalize (!rad -. rad2)) <= 0. then !rad +. r else !rad -. r in
      let rad2 = normalize rad2
      in
        (x := !x +. ((cos rad2) *. speed);
         y := !y +. ((sin rad2) *. speed);
         cnt := !cnt + 1;
         if
           (!cnt > (mx * 10)) ||
             (((fabs (!x -. x1)) < 10.) && ((fabs (!y -. y1)) < 10.))
         then (cnt := 0; m := next)
         else ();
         rad := rad2)
      
    let rec new_ () =
      Enemy3 ((ref move1), (ref 0.), (ref 300.), ((ref 0), (ref 0.)))
    and move1 e =
      match e with
      | Enemy3 (m, x, y, (cnt, rad)) ->
          (move m rad cnt 60 x y 310. 30. move2; e)
      | _ -> assert false
    and move2 e =
      match e with
      | Enemy3 (m, x, y, (cnt, rad)) ->
          (move m rad cnt 50 x y 200. 300. move3; e)
      | _ -> assert false
    and move3 e =
      match e with
      | Enemy3 (m, x, y, (cnt, rad)) ->
          (move m rad cnt 50 x y (-20.) (-20.) move4; e)
      | _ -> assert false
    and move4 e =
      match e with
      | Enemy3 (m, x, y, (cnt, rad)) ->
          (x := 0.; y := 300.; rad := 0.; cnt := 0; m := move1; e)
      | _ -> assert false
      
  end
  
module Enemy2 =
  struct
    let speed = 6.0
      
    let r = 0.15
      
    let fabs a = if a < 0. then -. a else a
      
    let move m rad cnt mx x y x1 y1 next =
      let rad2 = atan2 (y1 -. !y) (x1 -. !x) in
      let rad2 =
        if (normalize (!rad -. rad2)) <= 0. then !rad +. r else !rad -. r in
      let rad2 = normalize rad2
      in
        (x := !x +. ((cos rad2) *. speed);
         y := !y +. ((sin rad2) *. speed);
         cnt := !cnt + 1;
         if
           (!cnt > (mx * 10)) ||
             (((fabs (!x -. x1)) < 10.) && ((fabs (!y -. y1)) < 10.))
         then (cnt := 0; m := next)
         else ();
         rad := rad2)
      
    let rec new_ () =
      Enemy2 ((ref move1), (ref 0.), (ref (-30.)), ((ref 0), (ref 0.)))
    and move1 e =
      match e with
      | Enemy2 (m, x, y, (cnt, rad)) ->
          (move m rad cnt 60 x y 10. 350. move2; e)
      | _ -> assert false
    and move2 e =
      match e with
      | Enemy2 (m, x, y, (cnt, rad)) ->
          (move m rad cnt 50 x y 300. 30. move3; e)
      | _ -> assert false
    and move3 e =
      match e with
      | Enemy2 (m, x, y, (cnt, rad)) ->
          (move m rad cnt 50 x y 300. 400. move4; e)
      | _ -> assert false
    and move4 e =
      match e with
      | Enemy2 (m, x, y, (cnt, rad)) ->
          (x := 0.; y := (-30.); rad := 0.; cnt := 0; m := move1; e)
      | _ -> assert false
      
  end
  
module Game =
  struct
    let enemy = Enemy.new_ ()
      
    let enemy = Boss.new_ ()
      
    let enemy = Enemy3.new_ ()
      
    let enemy = Boss2.new_ ()
      
    let enemy = Boss3.new_ ()
      
    let draw () =
      (GlClear.clear [ `color ];
       GlDraw.color (1.0, 0.0, 0.0);
       (match !state with
        | Game -> (Actor.draw enemy; Ship.draw ())
        | Title -> gstring "push z" 0. 0. 6
        | _ -> ());
       Glut.swapBuffers ())
      
    let rec move ~value =
      (Glut.postRedisplay ();
       (match !state with
        | Title -> if !Key.z then state := Game else ()
        | _ -> (Ship.move (); let _ = Actor.move enemy in ()));
       Glut.timerFunc ~ms: 15 ~cb: move ~value: 1)
      
    let resize ~w ~h =
      let h = max h 1
      in
        (GlDraw.viewport ~x: 0 ~y: 0 ~w: w ~h: h;
         GlMat.mode `projection;
         GlMat.load_identity ();
         let ortho = GlMat.ortho ~z: (1.0, (-1.0)) in
         let x = (0.0, width) in
         let y = (height, (-0.0))
         in
           (ortho ~x: x ~y: y; GlMat.mode `modelview; GlMat.load_identity ()))
      
    let main =
      let _ = Glut.init Sys.argv
      in
        (Glut.initDisplayMode ~double_buffer: true ~alpha: true ();
         Glut.initWindowSize ~w: (int_of_float width)
           ~h: (int_of_float height);
         let _ = Glut.createWindow "Game01"
         in
           (Glut.displayFunc draw;
            Glut.reshapeFunc resize;
            Key.init ();
            Glut.timerFunc ~ms: 33 ~cb: move ~value: 1;
            GlClear.color ~alpha: 1.0 (0.1, 0.1, 0.1);
            Glut.mainLoop ()))
      
  end

明日は、masquerade0324さんのSMLの記事です。