ゲーム一覧へスキップ
Hadukis

ブログ

エンジンもフレームワークも使わずにHTML5ゲームを作る

· 約3分で読めます

ゲーム一覧ページの最初の9本のうち6本は、依存関係をいっさい持たずに公開しています。エンジンもフレームワークも、ビルド時のライブラリもありません。いちばん小さい Reefhold はディスク上で63KB。アートも含めたゲーム全体でこのサイズです。新しい3本はあえてこのルールを破っていて、どちらを選んだ理由も書いておく価値があると思います。

「エンジンなし」の中身

実際には3つだけです。<canvas> 要素がひとつ、requestAnimationFrame で回すループ、そして画面上の形はすべて画像を読み込まずにコードで描くこと。シーングラフもエンティティ・コンポーネント・システムもアセットパイプラインもありません。スプライトは、コンテキストといくつかの数値を受け取って fillRect を何回か呼ぶ関数です。

原始的に聞こえますし、実際に原始的です。それでも、タイトルを読み終わる前に Reefhold の読み込みが終わっているのは、このおかげです。

結局自分で書くことになる3つ

エンジンを使えば最初から付いてくるものです。使わない場合は、最初に書く3つのファイルになり、どのゲームでも同じ3ファイルです。

  • 固定タイムステップのループ。 requestAnimationFrame が渡してくるのは実時間の差分で、ティックではありません。その差分でそのまま物を動かすと、60Hzのノートパソコンと144Hzのモニターでゲームの挙動が変わり、テストでは自然だった物理がプレイヤーの環境ではおかしくなります。対策は、実時間をためておいて一定の刻みでシミュレーションを進め、描画では直前の2ステップの間を補間することです。
  • タッチでもキーボードでも同じになる入力。 トラフィックの半分はスマホです。keydown しか読まないゲームはその人たちには遊べませんし、あちこちでタッチを特別扱いすればコードが倍になります。コツは、両方を小さな「意図」オブジェクト(方向と、押しっぱなしの操作の集合)にまとめて、ゲームのほかの部分はそれだけを読むようにすることです。
  • 自動再生ポリシーに負けない音。 ブラウザは、ユーザーがページを操作するまで音を鳴らさせてくれません。読み込み時に AudioContext を作ると、停止状態で始まったまま二度と戻りません。最初のポインターかキーのイベントで作り、それ以降の音はすべてそれを条件にします。

全部でおよそ150行で、使っているゲームのあいだでそのまま共有しています。

得られるもの

  • ポータルに何も言われないサイズ。 キュレーション型のポータルには厳しいサイズ上限があり、超えれば問答無用で却下されます。63KBのゲームなら、そもそも話題にもなりません。
  • 一瞬で終わる初回読み込み。 モバイル回線では、これがプレイヤーになってもらえるか、すぐ離脱されるかの分かれ目です。
  • ライセンスで悩むものがない。 これらのゲームのライセンスについて相談が来ても、読み上げるべき第三者のライセンスも、クレジット表記のファイルもありません。「ええと、Phaser に依存していて、Phaser は MIT なんですが……」という話も不要です。

どこで線を引くか

Scrapforge、ScaleSling、Husktide は Phaser で作っていて、3本ともそれが正解でした。Scrapforge と ScaleSling には本物の物理ソルバーが必要で、2Dの拘束ソルバーは、わざわざ下手に書き直すようなものではありません。Husktide は画面に数百のエンティティを同時に出すので、テクスチャアトラスと調整済みのレンダラーに頼っています。

振り返るとパターンははっきりしています。素の作り方が通用するのは、「配置とタイミング」が中心のゲームです(パズルの大半、放置ゲームの大半、スコアを競うアーケードゲームの大半)。たくさんの物体が互いにぶつかり合うときや、角のある物体を扱う物理モデルが必要になったとたんに通用しなくなります。そこまで来ると、エンジンはもう余計な荷物ではありません。手作りで書いた場合よりもバンドルを小さく保ってくれるのは、むしろエンジンのほうです。

ゲームごとのサイズはすべてライセンスのページに載せています。実際の数字はそちらで確認できます。