スマホで遊べるゲームをスマホで作る方法

この記事ではゲームと言っておきながらウェブアプリの作り方を解説します。
(ネイティブアプリに見せかけてその中身はWebアプリなんていうハイブリットアプリがあるくらいなのでいいかなと…)

# 必要なもの

- ブラウザ

だけです。
codepenを使用するため特殊な開発環境を必要としません！
**スマホ**からでも作れます。

# 制作するアプリ
スマホの傾きを使ってボールを転がし、ゴールの穴に落とすゲームを作ります。
何処かで見たことあるようなゲームです。

最終的にはこんな感じのものを作ります。
http://codepen.io/daikinissan/full/RopOxV/

# 開発の流れ

1. codepenに登録する
2. 画像を用意する
3. 画像を表示する
4. 加速度で画像を動かす
5. ゲームでゴールできるようにする

これが今回制作する流れになります。

# codepenに登録する
まずは会員登録が必要なのでSign Upします。
GitHubやTwitter, Facebookのアカウントなどを利用しても登録できます。
登録が完了したら"+New Pen"をクリックして新しいプロジェクトを開始します。

# 画像を用意する
最終的にimgタグで読みこむのですがcodepenにアップロードするのは有料会員限定の機能となるのでなんとかしてURLを手に入れるかする必要があります。
必要となる画像は「背景」「ボール」「穴」です。
デモでは[いらすとや](http://www.irasutoya.com/)からデータをお借りしています。

# 画像を表示する
背景はCSSに、ボールと穴はHTMLに記述します。

```css:CSS
body {
  background-image: url("ここに画像のURLを記入");
}
```

```html:HTML
<img id="hole" src="ここに画像のURLを記入" alt="hole">
<img id="ball" src="ここに画像のURLを記入" alt="ball">
```

# 加速度で画像を動かす
まずは画像の位置を自由に動かすためにCSSを追記します。

```css:CSS(追加分)
#ball {
  position: absolute;
  width: 10%;
}

#hole {
  position: absolute;
  width: 12%;
}
```

加速度を取得するコードを追記します。

```js:JS
var scale = 0.01;
window.addEventListener("deviceorientation", onSensorChanged);
function onSensorChanged(event) {
  accel_x = event.gamma * scale;
  accel_y = event.beta * scale;
}
```

これでスマホの傾きを取ることができます。
`accel_x`,`accel_y`という変数にそれぞれ加速度を保存しています。
そのままの値をしようすると動きが機敏すぎるので、scaleという変数を用意して少し値を下げました。

次にボールを動かす部分を追記します。
最初の位置を中央に設定します。
`window.innerWidth`や`window.innerHeight`で表示しているエリア全体の大きさが取ることができます。

```js:JS(追加分)
var ball = document.getElementById("ball");
var maxX = window.innerWidth - ball.width;
var maxY = window.innerHeight - ball.height;
var x = maxX / 2;
var y = maxY / 2;
```

加速度を使用するためx, y軸に対し座標、速度を示す変数をそれぞれ用意します。

```js:JS(追加分)
var accel_x = 0;
var accel_y = 0;
var speed_x = 0;
var speed_y = 0;
```

そして0.02秒ごとに加速度を速度に加算し、その速度をもとに次の座標を求めます。

```js:JS(追加分)
var interval = setInterval(function() {
  speed_x += accel_x;
  speed_y += accel_y;
  x += speed_x;
  y += speed_y;
  ball.style.left = x + "px";
  ball.style.top = y + "px";
}, 20);
```

これで加速度をもとに移動するようになりました。
しかし、これでは画面の外側へと転がっていってしまうので壁で跳ね返るようにします。

```js:JS(追加分)
var bounds = 0.5; // 反射係数的な変数

var interval = setInterval(function() {
  speed_x += accel_x;
  speed_y += accel_y;
  x += speed_x;
  y += speed_y;

  /* ここから追加 */
  if (x < 0) {
    x = 0;
    speed_x = -speed_x * bounds;
  } else if (x > maxX) {
    x = maxX;
    speed_x = -speed_x * bounds;
  }
  if (y < 0) {
    y = 0;
    speed_y = -speed_y * bounds;
  } else if (y > maxY) {
    y = maxY;
    speed_y = -speed_y * bounds;
  }
  /* ここまで追加 */

  ball.style.left = x + "px";
  ball.style.top = y + "px";
}, 20);
```

これで画面の外側に出ようとした時に跳ね返るようになります。
`bounds`は反射係数を示すので1に近いほどよく跳ね返るようになります。

これでボールが画面内で転がるようになりました。

# ゲームでゴールできるようにする
最後にゴールできるようにプログラムします。
さすがに毎回穴の位置が同じではつまらないので穴の位置もランダムに移動するようにします。

まずは穴の位置をランダムに変更する部分を追加します。

```js:JS(追加分)
var hole = document.getElementById("hole");
var hole_x = Math.random() * (window.innerWidth - hole.width);
var hole_y = Math.random() * (window.innerHeight - hole.height);
hole.style.left = hole_x + "px";
hole.style.top = hole_y + "px";
```

これでアクセスするたびにランダムに穴の位置が変更されるようになりました。

それでは次にボールを移動するたびに穴との距離を計算し、その距離がどのくらい近いかで動きを止めます。

```js:JS
var interval = setInterval(function() {
  /* 省略 */

  /* ここから追加 */
  if (Math.sqrt(Math.pow(x - hole_x, 2) + Math.pow(y - hole_y, 2)) < ball.width / 3) {
    clearInterval(interval);
  }
  /* ここまで追加 */
}, 20);
```

JavaScriptのMathを利用すれば2乗や平方根を求められるので簡単に距離が計算できます。
このプログラムではボールの幅の3分の1以下の距離になったときにボールの動きを止めています。

これでデモと同じ状況になりました。

# 最後に
PCの方はChangeViewをクリック
スマホの方はActionsをタップして
FullPageを選択します。
こうすることで実際に遊ぶことができるURLがわかります。
※PCには加速度センサが搭載されていないのでなにも動きません...

全部合わせても100行に満たないプログラムで簡単なゲームが完成しました。
このくらいでしたらスマホでちまちまと開発することもできますね。
ゲームと言ってもWebアプリですが、こんなに簡単に開発できると楽しくなってしまいます。

最後まで読んでいただきありがとうございました。

最後にデモを改造してよりゲームっぽくしたものを載せておきます。
PCでも矢印キーで遊べるようにしました。
http://codepen.io/daikinissan/full/PbmmWd/