LoginSignup
4
1

More than 3 years have passed since last update.

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

Last updated at Posted at 2020-12-30

本連載について

本章の概要

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

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

その1 〜歩かせてみるよの巻〜

ゴール

  • 右に移動する際に主人公が動いているようにします

前提

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

やること

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

ソース

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)
  • 左向きに進む場合の対応はその2でやります

その2 〜ジャンプもさせるよの巻〜

ゴール

  • 左向きに移動した場合やジャンプした場合にもそれっぽく見えるようにします

やること

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

ソース

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
  • これでさらにゲームっぽくなったのではないでしょうか?

その3 〜ジャンプは1回だけだよの巻〜

ゴール

  • 1回しかジャンプできないようにします(空中でジャンプできないようにします)

やること

  • 空中でジャンプできないようにします

ソース

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

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;
    }
  ... (省略)

※ 実際のソースコードは こちら からダウンロードできます

▼ CodePenのサンプル

See the Pen mario-game-tutorial-01-05-03 by taku7777777 (@taku7777777) on CodePen.

終わりに

お疲れさまです!

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

4
1
0

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
4
1