[連載]スーパーマリオ的なゲームをjavascriptで作ってみる 初級編 〜5章〜 休憩

## 本連載について
- プログラミング初心者がスーパーマリオ的なゲームを作成するのに情報をまとめたものです
- 不明点や不備あれば、なんでもコメントいただけると大変嬉しいです！！！<br/>
より良いものにしたいので！
- 一番最初の連載は[こちら](https://qiita.com/hockeyarchitecture/items/139c27ff4806eaf2367f)から確認お願いします！<br/>
▼ゲームイメージ<br/>
![ゲームイメージ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499206/949bb1ad-7109-1c70-b116-36ef83df3aa9.gif)<br/>
<br/>
▼目次<br/>
[1章 準備する](https://qiita.com/hockeyarchitecture/items/139c27ff4806eaf2367f)<br/>
[2章 簡単なページ作ってみる](https://qiita.com/hockeyarchitecture/items/76e0e90c1883d91b3e87)<br/>
[3章 画像を動かしてみる](https://qiita.com/hockeyarchitecture/items/c526e2345cb512109e18)<br/>
[3章 落ちちゃダメ！！](https://qiita.com/hockeyarchitecture/items/bea44d14aa16aa7f916e)<br/>

## 本章の概要
前回までで動く状態ができあがり多少はゲームっぽさが出てきたと思います。
が、キャラクターが動いている感がなかったり、空中でジャンプしつづけられてしまったりするので
この辺を修正してよりゲームっぽく見えるようにしたいと思います。

- よりゲームっぽくするために細かいとこ修正していきます
- 特にコアなロジック部分はこの章ではやらないです
- 本章の内容は大きく3ステップです
  - 1. 歩かせてみるよの巻
  - 2. ジャンプもさせるよの巻
  - 3. ジャンプは１回だけだよの巻
- ソースを保存しているgithubのリポジトリも記載しています<br/>
リンクにアクセスして実際のソースをダウンロードすることができます<br/>
**ぜひダウンロードして動かしながら試してみてください！**


## その１ 〜歩かせてみるよの巻〜
### ゴール
- 右に移動する際に主人公が動いているようにします

### 前提
- 複数の画像を一定間隔ごとに表示して動いているように見せます
- ソース側でハンドリングできるように、１ファイルのgifでなく複数の画像ファイルを用います

### やること
- 動いているように見せる複数の画像を作成する ([[参考]ドッド絵を作成する](http://neutralx0.net/tool/dot2/))
- 右ボタンが押されている場合には、カウントを取り、カウントが一定数超えるごとに次の画像を表示するようにする

### ソース


```javascript:index.js

... (省略)

// ゲームオーバーか否かのフラグ値
var isGameOver = false;

// 移動中の場合にカウントする
var walkingCount = 0;
// カウントに対して画像を切り替える単位
const walkRange = 5;

... (省略)

// 画面を更新する関数を定義 (繰り返しここの処理が実行される)
function update() {
  
  ... (省略)

  if (isGameOver) {

    ... (省略)

  } else {
    // 入力値の確認と反映
    if (input_key_buffer[37] || input_key_buffer[39]) {
      walkingCount = (walkingCount + 1) % (walkRange * 10);
    } else {
      walkingCount = 0;
    }

    ... (省略)

  }

  x = updatedX;
  y = updatedY;

  // 主人公の画像を表示
  var image = new Image();
  if (isGameOver) {
    // ゲームオーバーの場合にはゲームオーバーの画像が表示する
    image.src = '../images/character-01/game-over.png';
  } else if (Math.floor(walkingCount / walkRange) === 0) {
    image.src = '../images/character-01/walk-right-01.png';
  } else if (Math.floor(walkingCount / walkRange) === 1) {
    image.src = '../images/character-01/walk-right-02.png';
  } else if (Math.floor(walkingCount / walkRange) === 2) {
    image.src = '../images/character-01/walk-right-03.png';
  } else if (Math.floor(walkingCount / walkRange) === 3) {
    image.src = '../images/character-01/walk-right-04.png';
  } else if (Math.floor(walkingCount / walkRange) === 4) {
    image.src = '../images/character-01/walk-right-05.png';
  } else if (Math.floor(walkingCount / walkRange) === 5) {
    image.src = '../images/character-01/walk-right-06.png';
  } else if (Math.floor(walkingCount / walkRange) === 6) {
    image.src = '../images/character-01/walk-right-07.png';
  } else if (Math.floor(walkingCount / walkRange) === 7) {
    image.src = '../images/character-01/walk-right-08.png';
  } else if (Math.floor(walkingCount / walkRange) === 8) {
    image.src = '../images/character-01/walk-right-09.png';
  } else if (Math.floor(walkingCount / walkRange) === 9) {
    image.src = '../images/character-01/walk-right-10.png';
  }
  ctx.drawImage(image, x, y, 32, 32);

  ... (省略)
}

... (省略)

```

### 説明
- 右ボタンが押されている間は `walkingCount` を増やしていきます
- `walkingCount` が5増えるごとに画像を変えていきます ( `walkRange` で指定)
- 画像は10枚でループさせるので、 `walkCount` は500以下とするようにします (厳密には0〜499)
- 左向きに進む場合の対応はその２でやります


## その２ 〜ジャンプもさせるよの巻〜
### ゴール
- 左向きに移動した場合やジャンプした場合にもそれっぽく見えるようにします

### やること
- ジャンプ用の画像を作成します
- 左向き用の画像は、右向き用の画像を水平方向に反転して作成します
- 最後に右左どちらのボタンが押されたかを保持しておきどっち向きの画像を表示するべきかを判断します
- ジャンプフラグが立っている場合にはジャンプの画像を表示します

### ソース

```javascript:index.js

... (省略)

// 移動中の場合にカウントする
var walkingCount = 0;
// カウントに対して画像を切り替える単位
const walkRange = 5;
// 右向きか否か
var toRight = true;

... (省略)

// 画面を更新する関数を定義 (繰り返しここの処理が実行される)
function update() {

  ... (省略)

  if (isGameOver) {

    ... (省略)

  } else {
    // 入力値の確認と反映
    if (input_key_buffer[37] || input_key_buffer[39]) {
      walkingCount = (walkingCount + 1) % (walkRange * 10);
    } else {
      walkingCount = 0;
    }

    if (input_key_buffer[37]) {
      toRight = false;
      updatedX = x - 2;
    }
    if (input_key_buffer[38]) {
      vy = -7;
      isJump = true;
    }
    if (input_key_buffer[39]) {
      toRight = true;
      updatedX = x + 2;
    }

    ... (省略)

  }

  x = updatedX;
  y = updatedY;

  // 主人公の画像を表示
  var image = new Image();
  if (isGameOver) {
    // ゲームオーバーの場合にはゲームオーバーの画像が表示する
    image.src = '../images/character-01/game-over.png';
  } else if (isJump) {
    image.src = `../images/character-01/jump-${
      toRight ? 'right' : 'left'
    }-000.png`;
  } else {
    image.src = `../images/character-01/walk-${
      toRight ? 'right' : 'left'
    }-${'00' + Math.floor(walkingCount / walkRange)}.png`;
  }
  ctx.drawImage(image, x, y, 32, 32);

  ... (省略)

}

... (省略)

```

### 説明
- 画像の命名規則を以下のように決めてしまい、画像ごとに分岐を記載しなくとも、画像のファイル名を動的に作成するようにしています
  - `jump-right-000.png`
  - `jump-left-000.png`
  - `walk-right-001.png`
  - `walk-right-002.png`
  - `walk-left-001.png`
  - `walk-left-002.png`
- これでさらにゲームっぽくなったのではないでしょうか？

## その３ 〜ジャンプは１回だけだよの巻〜
### ゴール
- 1回しかジャンプできないようにします(空中でジャンプできないようにします)

### やること
- 空中でジャンプできないようにします

### ソース
これはかんたんですね！
キーボードの入力に応じてジャンプを制御している部分に、ジャンプ中でない場合のみジャンプするようにすればよいだけです！
(`!isJump`の部分)

```javascript:index.js
  ... (省略)

    if (input_key_buffer[37]) {
      toRight = false;
      updatedX = x - 2;
    }
    if (input_key_buffer[38] && !isJump) {
      vy = -10;
      isJump = true;
    }
    if (input_key_buffer[39]) {
      toRight = true;
      updatedX = x + 2;
    }
  ... (省略)
```

※ 実際のソースコードは [こちら](https://github.com/taku7777777/mario-game-tutorial-01-05-03) からダウンロードできます

▼ CodePenのサンプル

<p class="codepen" data-height="487" data-theme-id="dark" data-default-tab="js,result" data-user="taku7777777" data-slug-hash="LYRQgYz" style="height: 487px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="mario-game-tutorial-01-05-03">
  <span>See the Pen <a href="https://codepen.io/taku7777777/pen/LYRQgYz">
  mario-game-tutorial-01-05-03</a> by taku7777777 (<a href="https://codepen.io/taku7777777">@taku7777777</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>


## 終わりに
お疲れさまです！

次はクリボーを出現させましょう！！