JavaScriptでフルスクラッチゲーム開発しよう 第1回 準備編

## HTML5のゲーム開発向けフレームワークの乱立

昨今、HTML5のCanvas, WebGL, WebAudioAPiなど、Webフロントエンド技術でのゲーム開発に向いた技術が増えて、Webブラウザ向けのゲーム開発界隈が盛り上がりを見せています。

それに合わせて、JavaScriptによるゲーム開発向けフレームワークも広がりを見せ、どれを選べばいいか迷ってしまうほど、多くのフレームワークが登場しています。

## 習熟の道

しかし、HTML5ゲームの開発をする際にそういったフレームワークを使用することを選択した場合、CanvasやWebGLなどの特性を学ぶ他、そのフレームワークの使用方法や設計理念も学ぶ必要があり、目の前に登場する大きな要塞に立ちくらみを覚える人も居るかと思います。

「[フロー体験](http://ja.wikipedia.org/wiki/%E3%83%95%E3%83%AD%E3%83%BC_%28%E5%BF%83%E7%90%86%E5%AD%A6%29)」という考え方があり、技術の習熟においては、自分の現在の習熟レベルに合わせて技術を学習する必要があります。

もし「HTML5ゲーム開発自体の習熟レベルが低い」という場合、ベースとなっているCanvasやWebGL、さらにはJavaScriptやDOMなどの基礎知識すら習熟レベルが低いという状態では、フレームワークの使用方法や設計理念の学習というのは、フロー体験を妨げるものとなります。

「ただ散歩がしたかっただけなのに、歩き方トレーナーや健康講座、休憩の仕方の話など、色んな知識を押し付けられて萎えた……」みたいな状態になります。ただ散歩がしたかっただけなのに……。

関連キーワード：[YAGNI](http://ja.wikipedia.org/wiki/YAGNI)

## フルスクラッチという選択

そこで、フルスクラッチです。

[フルスクラッチとは 【 full scratch 】 - 意味/解説/説明/定義 ： IT用語辞典](http://e-words.jp/w/%E3%83%95%E3%83%AB%E3%82%B9%E3%82%AF%E3%83%A9%E3%83%83%E3%83%81.html)

> 既存のものを一切流用せずにまったく新規に開発すること。

フレームワークレスでゲーム開発することにより、必要な知識を最小限に抑えながら、学習を進める、という攻め方です。

あくまで学習を進めるための有効な攻め方の1つと考えるものであり、実際のプロダクト開発においては、有効な手段とならない場合もあるので注意が必要です。

しかし、これを一度体験すると、フルスクラッチで開発することに魅了されることでしょう。

## Webブラウザはすでにある種のゲームエンジンである

私個人は、Webブラウザはすでにある種のゲームエンジンであると考えています。

UnityやUnreal Engineのような高級なゲーム開発向けツール群がWebブラウザに揃えられているわけではありませんが、DOMという仕組みや、各種APIがすでに高級なものであり（ここで言う”高級”は、OSの低レベルAPIを直接触る必要が無い層という意味）、JavaScriptというプログラミング言語自体も、メモリについて深く考慮しなくても良い高級なもの、という意味で、すでにゲーム開発を楽にする仕組みが用意されている、とも捉えることができます。

このへんについて感動するためには、一度CやC++で、フレームワークを使わずに直接OSのAPIを叩いてゲーム開発をしてみる経験が必要かもしれません。

また、昨今のモダンなWebブラウザには、高機能なデバッグツールが標準で備えられており、ゲーム開発の助けになります。

余談になりますが、ゲーム開発向けツールはゲームを実行させるためのエンジンとは別物になるべきだという考えを私は持っており、ツールとエンジンが仕様で深く結びついたようなオールインワンタイプのツールは好きになれません。

ゲーム開発向けツールは、そこで作成したデータがポータブル（オープンな仕様の特定のエンジンに依存しないデータフォーマット）になるべきです。そこに政治的事情が絡めば話は別ですが。

ではさっそくフルスクラッチでのゲーム開発をしてみましょう。

## htmlファイルとjsファイルを用意する

というわけで、さっそくフルスクラッチでゲーム開発していきましょう。

まずはhtmlファイルです。`index.html`ファイルを作成します。

```html:index.html
<!DOCTYPE>
<html>
<head>
<title>ゲーム</title>
</head>
<body>
</body>
</html>
```

JavaScriptを実行するため、`<script>`タグを追加しておきます。

```html:index.html
 :
<head>
<title>
<script src="main.js"></script>
</head>
 :
```

実行されるjsファイルを用意し、基本的なコードを書きます。

```js:main.js
window.addEventListener('load', init);

/**
 * 初期化
 */
function init() {
  // ここに初期化処理を書く
}
```

HTMLページが読み込まれたときに初期化処理が実行されるように、`window.addEventListener('load', init)`で、`init`関数が呼ばれるようにしています。

## Canvasを用意する

`<canvas>`タグを追加します。

```index.html
 :
<body>
  <canvas id="maincanvas"></canvas>
</body>
 :
```

JavaScript側でCanvasとRenderingContextを取り出して扱えるようにしておきます。

```js:main.js
var canvas;
var ctx;

function init() {
  canvas = document.getElementById('maincanvas');
  ctx = canvas.getContext('2d');
}
```

Canvasのサイズを定義しておき、

```js:main.js
var SCREEN_WIDTH = 800;
var SCREEN_HEIGHT = 600;
 :
```

Canvasにサイズを設定します。

```js:main.js
function init() {
 :
  canvas.width = SCREEN_WIDTH;
  canvas.height = SCREEN_HEIGHT;
}
```

## 毎フレーム更新処理を作成する

毎フレーム更新処理用にWeb標準APIとして`requestAnimationFrame`というメソッドが用意されています。

こちらは`window`オブジェクトのメソッドとして用意され、`window`オブジェクトはJavaScriptコンテキストのグローバルオブジェクトでもあるので、`window.requestAnimationFrame`というように`window`を付けなくても呼び出すことができます。

グローバルオブジェクトについての参考記事
[[JavaScript] グローバル変数とグローバルオブジェクトを取得する方法 - Qiita](http://qiita.com/LightSpeedC/items/ce4b46cbdefd168b30ef)

`requestAnimationFrame`の仕様については、以下が参考になります。

[window.requestAnimationFrame - Web API インターフェイス | MDN](https://developer.mozilla.org/ja/docs/Web/API/Window/requestAnimationFrame)

第1引数に関数を与えることで、次回フレームの更新が必要なタイミングで関数を呼んでくれます。

```js:main.js
function init() {
 :
  requestAnimationFrame(update);
}

function update() {
  requestAnimationFrame(update);
}
```

注意点としては、あくまで「次回フレームの更新が必要なタイミング」なので、更新処理毎に、また次回フレームの更新が必要なタイミングで関数を呼んでもらう必要があるため、毎フレーム`requestAnimationFrame`を呼ぶ必要がある、という点です。

## 描画

描画が必要になる処理は`render`関数で処理することにします。

```js:main.js
function update() {
 :
  render();
}

function render() {
  // ここで描画処理する
}
```

描画については、毎フレームでCanvas全体を描画し直していく必要があるため、RenderContextの`clearRect`メソッドを使って全体のクリアから行います。

```js:main.js
function render() {
  // 全体をクリア
  ctx.clearRect(0, 0, canvas.width, canvas.height);
}
```

`clearRect`メソッドの仕様は、こちらが参考になります。

[CanvasRenderingContext2D.clearRect() - Web API インターフェイス | MDN](https://developer.mozilla.org/ja/docs/Web/API/CanvasRenderingContext2D/clearRect)

これで基本的な準備は整いました。

ファイル全体は以下のようになります。

```html:index.html
<!DOCTYPE>
<html>
<head>
<title>ゲーム</title>
<script src="main.js"></script>
<body>
  <canvas id="maincanvas"></canvas>
</body>
</html>
```

```js:main.js
var SCREEN_WIDTH = 800;
var SCREEN_HEIGHT = 600;

window.addEventListener('load', init);

var canvas;
var ctx;

function init() {
  canvas = document.getElementById('maincanvas');
  ctx = canvas.getContext('2d');

  canvas.width = SCREEN_WIDTH;
  canvas.height = SCREEN_HEIGHT;

  requestAnimationFrame(update);
}

function update() {
  requestAnimationFrame(update);

  render();
}

function render() {
  // 全体をクリア
  ctx.clearRect(0, 0, canvas.width, canvas.height);
}
```

長くなるので、また次回から続きを進めます。

次回: [JavaScriptでフルスクラッチゲーム開発しよう 第2回 画像読み込み編 - Qiita](http://qiita.com/zukkun/items/f0348a8cc14090f184b8)