3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

JavaScriptでジャンプゲームを作りました。

Last updated at Posted at 2021-06-28

JavaScriptでジャンプゲームを作成しました!
ゲームの紹介と学んだところをまとめていきます。

■URL
https://js-2d-game.herokuapp.com/

ゲーム内容

シンプルなジャンプゲームで敵キャラを避けて、アイテムを取得して
どんどんスコアを伸ばしていくゲームです。
ステージ1と2はアイテムのぶどうを10個とったら次のステージに進めます。
そしてステージ3でスコアを伸ばしていきます。
ランキングもあるのでぜひハイスコアを目指してみてください!
ガラケー時代によく遊んでいた「おばちゃんが跳ぶ」を少し意識して作りました。

実装した内容

  • スコア登録機能
  • ランキング表示機能
  • BGM
  • PC/SP対応

一部HTMLとCSSで作っているところもありますが、ほぼJSで実装していて
ゲームの背景やキャラクターなどはcanvasAPIを使用して描画しています。

学んだこと

class構文

今までclass構文を使ったことがなかったのですが、ゲーム開発を通して学ぶことができました。
キャラクターやアイテムなどの動作・状態などclassを使って実装しています。

様々なMathオブジェクト

キャラクターとアイテム・敵との当たり判定や、アイテム・敵の出現座標、速度などに
様々なMathオブジェクトのメソッドを使用しMath.abs(), Math.pow(), Math.sqrt()を使って当たり判定を実装しました。

enemies.forEach((enemy) => { 
  const distanceX = Math.abs(this.x - enemy.x); 
  const distanceY = Math.abs(this.y - enemy.y);
  
  const distance = Math.sqrt(Math.pow(distanceX, 2) + Math.pow(distanceY, 2));
  if (distance <= 30) {
   this.hitObstacle();
  }
});

キャラクターと敵の距離を計算して、距離が一定の値以下になったら「当たった」という処理にしています。

Math.abs()
引数の絶対値を返すメソッドです。
キャラクターや敵は常に動いているので当たる位置によって座標がマイナスになることもあります。
絶対値にすることでより正確な距離がわかるようになります。

Math.pow()
第一引数を第二引数で累乗した値を返します。
ex. Math.pow(2, 2) → 4

Math.sqrt()
引数の平方根を返します。

Math.pow()Math.sqrt()を使うことで三平方の定理で2点間の距離、キャラクターと敵の距離を計算することができるようになります。

Gameの初期設定

今回作ったゲームはステージが3つあり、それぞれ敵数、アイテム数や動くスピードなどが違います。
初めはステージ情報を定義しているjsファイルにステージの設定を書いていましたが、jsonファイルにゲームの設定を書き、それを読み込むことでステージ情報の設定を行う方法を学びました。
ステージごとに設定する量は多くないのでjsファイルに直書きでもよかったかもしれませんが、
これをしたことで設定を変えたいと思った時に楽に変更することができるようになったと思います。

jsonではステージごとの背景や敵数、アイテム数、PC・SP時の大きさなどを定義しています。
読み込みはaxiosを使いました。

{
    "stage": {
        "first": {
            "background": "./image/bg.png",
            "enemy": 3,
            "increasedOfEnemy": 0,
            "item": 3
        },
        "second": {
            "background": "./image/bg_natural_sougen.jpg",
            "enemy": 4,
            "increasedOfEnemy": 1,
            "item": 3
        },
        "third": {
            "background": "./image/bg.png",
            "enemy": 5,
            "increasedOfEnemy": 4,
            "item": 2
        }
    },
    "enemyInfo": {
        "pcWidth": 70,
        "pcHeight": 70,
        "spWidth": 33,
        "spHeight": 33
    },
    "itemInfo": {
        "pcWidth": 36,
        "pcHeight": 36,
        "spWidth": 31,
        "spHeight": 31
    }
}
async function getStageJson() {
    // ステージ情報を取得
    await axios.get('http://localhost:5000/gameInfo.json')
        .then(response => {
            stage = new StageObject(response.data);
            stage.setStage();
        })
        .catch(error => {
            console.log(error);
        })
}

サウンド

素材は無料で使えるものをダウンロード、JavaScriptでaudioタグを作り再生をさせています。
BGMはPC・スマホ両方とも問題なかったのですがゲームオーバー時のサウンドで少し詰まりました。

というのもスマホで音を鳴らすにはユーザーアクションが必要になります。
このユーザーアクションというのがtouch/mouseイベントのハンドラー内でしか効きません。
ゲームオーバー時のサウンドはユーザーアクションによって発生しないため流れませんでした。

ただ対策は簡単で、ユーザーイベントが発生したタイミング(ゲームスタート)でゲームオーバーのサウンドをloadしておくことで、実際にゲームオーバーになったときにサウンドを流すことができました。

function gameStart() {
    document.getElementById('gameInfo').classList.add('is-hide');
    canvas.style.opacity = 1;
    countdown.start();
    requestAnimationFrame(draw);

    stageBgm.play(); // BGMはすぐ流れていいのでplay()
    gameOverSound.load(); // ← 事前にロード
    handleJump();
}

最後に

学ぶことが多く大変ではありましたが、ゲーム開発を通してプログラミングの基礎や考え方を学ぶことができたと思うし何より楽しく開発ができました。

ぜひ遊んでいただけると嬉しいです!
https://js-2d-game.herokuapp.com/

3
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?