JK 13 Kゲームジャムのための13 Kでゲームを書くためのJSHERN OFSCAI OCAMLの使用

10006 ワード

このポストは、JAM 13 KゲームジャムのOCamlで作ったゲームの結果です.私は、ゲームを作るとき、私が持った若干の観察を共有します.
でもまず簡単に紹介しますjs13k .
JS 13 KはJavaScript開発者向けのコーディングコンテストです.目標は、与えられたテーマに従って1ヶ月でゲームを作成することです.課題は、ZIPパッケージ全体が13 KB以上でなければならないことです.ゲームを実行するために必要なすべてのパッケージに含まれている必要があります-ゲームは、Webから任意のリソースを読み込むことができない外部サービスにアクセスすることはできません.
これが初めての使用だったのでOCaml , 私は、私がそれを作るつもりであることを確認するために単純な何かを構築したかったです、そして、必要なサイズを越えないでしょう.今年のテーマは“404 NOT発見”だったので、私はプレイヤーが文字を推測することによって単語やフレーズを明らかにする必要が推測ゲームを作成-絞首刑執行人のゲームに似ています.これはかなり基本的なので、私はそれぞれの正しい推測後にアニメーションを追加しました.それぞれのフレーズはそれ自身のアニメーションであり、これはコードサイズの約1/4を取ることが判明した.
提出されたゲームはJavaScriptで実装されなければなりません.JavaScriptに転送できる限り、任意の言語で書くことができます.私は前の年に純粋なJavaScriptゲームを提出しました、しかし、今回は、コンパイルされて、静的タイピングをしている言語を試してみたかったです.
JavaScriptでの私の主な問題は、それが動的に、弱いタイプです.これは、実行時にのみ発見することができる奇妙なエラーにつながる可能性があります.また、すべての作業がまだ動作しているかどうかをチェックするために、アプリケーションを再実行する必要があるので、どんな些細なリファクタリングもずっと難しくなります.最後に、静的なタイピングには追加の利点があります.
JavaScriptで入手できる奇妙な結果があります.
'a' + 1   // 'a1'
'a' - 1   // NaN
'a' + NaN // 'aNaN'
[] == []  // false
[] == ![] // true
これらのすべては非常に意外な驚きか本当の意味をしないでください.
対照的に、ocamlは静的で強く型付けされた言語です.これにより、以下のような構文が得られます"a" + 1 単にコンパイルエラーであること.floatに整数を加えてもコンパイルされないので、両方の引数を同じ型にキャストする必要があります.これは開発を簡素化します.なぜなら、それは驚くべき振る舞いをもたらさないからです.コンパイラは、少なくとも部分的に正確性をチェックするため、リファクタリングも非常に簡単です.
OcAMLはJavaScriptからコンパイルされていませんが、そのためだけにライブラリがあります.js_of_ocaml .
これは、OCamlツールを使用すると、OPAMパッケージマネージャを使用してインストールすることができますopam install js_of_ocaml js_of_ocaml-ppx js_of_ocaml 基本パッケージjs_of_ocaml-ppx OCamlコードの構文拡張機能を提供します.追加機能を提供するパッケージがいくつかあります.
一旦インストールされるならば、あなたは通常、例えばocamlc :
ocamlfind ocamlc -package js_of_ocaml -package js_of_ocaml-ppx -linkpkg -o script.byte script.ml
それから、あなたはjs_of_ocaml OCamlバイトコードからJavaScriptを生成するにはjs_of_ocaml script.bytedune , OCamlのための一般的に使用されるビルドツールも、JavaScriptjs_of_ocaml .
関数js_of_ocaml はいくつかのモジュールに分割されます:module Js - JavaScriptのバインディングmodule Dom_html - HTML結合module Firebug - デバッグコンソール
その他多数
すべての関数はjs_of_ocaml , どちらがJs.number Js.date Js.regex Js.js_string Js.opt Js.optdef number , date and regex JavaScriptから既知の型へのマップ.またjs_string , JavaScriptの文字列型です.これは、JavaScript文字列があるすべてのメソッドを提供し、したがって、OCML文字列型と互換性がありません.そういうわけで、2つのタイプの間で変換をするのがしばしば必要です.opt and optdef NULLと未定義の値を扱う特別な型です.opt おそらくNULL値を表します.optdef - 定義されていない値.このように、NULLと未定義の両方の型の概念はありません.
すべてのタイプjs_of_ocaml パッケージはオブジェクト指向の方法で設計されていますので、メソッドを呼び出して、型のプロパティを読み込み/設定します.これらの型の型シグネチャはいくぶん複雑ですので、容易にするためにjs_of_ocaml-ppx パッケージ.これにより、通常のオブジェクト指向のocamlコードとかなり似た構文が得られます.
element##method_name arg1 arg2 (* method call *)
let foo = element##.property (* read value of a property *)
element##.property := new_value (* set new value for a property *)
例えば、ここで電話しますquerySelector クラスを持つすべての要素を取得するにはbig :
Html.document##querySelector (Js.string ".big")
ここでは、いくつかのDOM要素の現在の色を取得する方法を示しますelem :
let color = elem##.style##.color
そして、現在の色を変更することができます.
elem##.style##.color := Js.string "black"
イベントハンドラを割り当てることもできます.
Html.document##.onkeydown := Html.handler keypressed
CSSクラスを与えられた要素に追加する関数です.
let jstr s = Js.string s
let nullstr () = jstr ""
let addClass (elem: Html.element Js.t) cls =
        let class_str = (jstr "class") in
        let current_cls = (elem##getAttribute class_str |> Js.Opt.get) nullstr in  (* 1 *)
        let new_cls = current_cls##concat_2 (jstr " ") (jstr cls) in  (* 2 *)
        elem##setAttribute class_str new_cls  (* 3 *)
アット(* 1 *) 現在のCSSクラスを要素に割り当てます.The getAttribute メソッドの結果Js.Opt 型を指定できます.実際の値を取得するにはJs.Opt.get 関数が格納された値を返します.それ以外の場合、nullstr 関数.空の文字列です.
アット(* 2 *) クラスのリストに新しいクラスを追加します(* 1 *) .
アット(* 3 *) 最後に、新しく構築した文字列を要素のカレントとして設定します.
目を離さないことは、結果として生じるパッケージサイズです.すべてが13 KBであるとき、偶数のバイトも数えられる.残念ながらjs_of_ocaml 約6 KBのオーバーヘッドを追加します.それはWebベースのゲームを作成するために余分な機能を提供していないので、特に、それは非常に多くのです.また、いくつかの追加のocaml関数を使用する場合は、さらに成長することができます.私が使おうとしたときPrintf.printf 関数の結果、パッケージサイズは15 KB増加した.単純な文字列連結に戻る必要がありました.
私がコードサイズで問題があったとき、もう一つのケースは、私がOCamlストリングをJs.js_string . そのためには、両方とも同じ型を持つように変換する必要があります.OCaml文字列をJs.js_string 私が変換したときよりパッケージサイズが大きかったJs.js_string ocaml文字列.差は~ 4 KBで、確かに目立つ.
それを合計するには、OcAMLでJavaScriptゲームをしようとするのはとても楽しい.厳密なタイプチェッカーを持って確かに助けた.私は全体的にランタイムエラーが1つしかありませんでした.これは純粋なJavaScriptではできません.繰り返しサイクルはかなり速かったですが、Javascriptよりも明らかに遅いです.コンパイル時間はかなり速いが顕著だった.
主な問題はJavaScriptのコードサイズを生成されます.しかし、JavaScriptのコードサイズが重要でないなら-それは通常ではありません-js_of_ocaml JavaScriptコードを書くことは実行可能です.