このセクションではブロックのアニメーションを行います。一定速度で左に移動して、キャンバス外に出たブロックを再びキャンバスに描画するように設定します。

ブロックの更新

まず、ブロックののX軸方向の速度を表す変数bvxを設定します。また、変数が増えてきたのでコメントを追加します。

main.js
// ブロック変数
// 基準点座標
let bx_list = [0, 200, 400, 600];
let by_list = [100, 125, 150, 200];
// 速度
let bvx = -2;
// 幅
let bw = 50;
// 上下のブロックのスペース
let bs = 140;
// 左右のブロックの距離
let bd = 200;
JavaScript
main.js
// ブロック変数
// 基準点座標
let bx_list = [0, 200, 400, 600];
let by_list = [100, 125, 150, 200];
// 速度
let bvx = -2;
// 幅
let bw = 50;
// 上下のブロックのスペース
let bs = 140;
// 左右のブロックの距離
let bd = 200;
JavaScript

次に、ブロックの状態を更新するupdate_blocks関数を作成します。

main.js
// ブロックの更新
function update_blocks() {
  // 速度をもとに座標を変更
  for (let i = 0; i < bx_list.length; i++) {
    bx_list[i] += bvx;
  }
}

// 背景の描画
function draw_background() {
  ctx.fillStyle = BACKGROUND_COLOR;
  ctx.fillRect(0, 0, cvs.width, cvs.height);
}
JavaScript
main.js
// ブロックの更新
function update_blocks() {
  // 速度をもとに座標を変更
  for (let i = 0; i < bx_list.length; i++) {
    bx_list[i] += bvx;
  }
}

// 背景の描画
function draw_background() {
  ctx.fillStyle = BACKGROUND_COLOR;
  ctx.fillRect(0, 0, cvs.width, cvs.height);
}
JavaScript

update_blocks関数では各ブロック対に対して、bvy分座標を移動しています。

最後にupdate_blocks関数をmain関数のupdate_player関数の前で実行します。

main.js
function main() {
  update_blocks();
  update_player();
  draw_background();
  draw_blocks();
  draw_player();

  setTimeout(main, FRAME_ELEMENT);
}
JavaScript
main.js
function main() {
  update_blocks();
  update_player();
  draw_background();
  draw_blocks();
  draw_player();

  setTimeout(main, FRAME_ELEMENT);
}
JavaScript

ブロックの再利用

Chromeに移動してindex.htmlを更新します。実行結果は以下の画像のようにブロックが移動します。

ただ、一度ブロックがキャンバスの外に出たら描画されなくなるので、上の画像のように4つ目のブロックの後ろに5つ目のブロックは現れません。5つ目以降のブロックを描画する方法はいくつか考えられますが、今回はキャンバスの外に出たブロックを、再びキャンバスに描画するように修正します。以下の画像を参照してください。

一番左のブロックをご覧ください。今回はブロックの基準点のX座標が-bd以下になったときにX座標にbd *4を足して一番右の白いブロックの位置に移動します。このようにしてブロックの間隔を一定に保ったまま5つ目以降のブロックを描画します。

上の考えをもとにupdate_blocks関数を更新します。

main.js
// ブロックの更新
function update_blocks() {
  // 速度をもとに座標を変更
  for (let i = 0; i < bx_list.length; i++) {
    bx_list[i] += bvx;

    // x座標が-bd以下であればbd * 4を足す
    if (bx_list[i] <= -bd) {
      bx_list[i] += bd * 4;
    }
  }
}
JavaScript
main.js
// ブロックの更新
function update_blocks() {
  // 速度をもとに座標を変更
  for (let i = 0; i < bx_list.length; i++) {
    bx_list[i] += bvx;

    // x座標が-bd以下であればbd * 4を足す
    if (bx_list[i] <= -bd) {
      bx_list[i] += bd * 4;
    }
  }
}
JavaScript

Y座標のランダム化

現在のブロックの基準点のY座標は固定でゲームが単調なので、Y座標をランダム化します。

まず、生成されるY座標の最小値と最大値をmin_bymax_byで設定します。

main.jsx
// ブロック変数
// 基準点座標
let bx_list = [0, 200, 400, 600];
let by_list = [100, 125, 150, 200];
// y座標の最小値、最大値
let min_by = 100;
let max_by = 200;
// 速度
let bvx = -2;
// 幅
let bw = 50;
// 上下のブロックのスペース
let bs = 140;
// 左右のブロックの距離
let bd = 200;
JavaScript
main.jsx
// ブロック変数
// 基準点座標
let bx_list = [0, 200, 400, 600];
let by_list = [100, 125, 150, 200];
// y座標の最小値、最大値
let min_by = 100;
let max_by = 200;
// 速度
let bvx = -2;
// 幅
let bw = 50;
// 上下のブロックのスペース
let bs = 140;
// 左右のブロックの距離
let bd = 200;
JavaScript

次に、update_blocks関数のif文の中にY座標を変更する処理を追加します。

main.js
// ブロックの更新
function update_blocks() {
  // 速度をもとに座標を変更
  for (let i = 0; i < bx_list.length; i++) {
    bx_list[i] += bvx;

    // x座標が-bd以下であればbd * 4を足し、y座標を変更する
    if (bx_list[i] <= -bd) {
      bx_list[i] += bd * 4;
      by_list[i] = Math.floor(Math.random() * (max_by - min_by + 1)) + min_by;
    }
  }
}
JavaScript
main.js
// ブロックの更新
function update_blocks() {
  // 速度をもとに座標を変更
  for (let i = 0; i < bx_list.length; i++) {
    bx_list[i] += bvx;

    // x座標が-bd以下であればbd * 4を足し、y座標を変更する
    if (bx_list[i] <= -bd) {
      bx_list[i] += bd * 4;
      by_list[i] = Math.floor(Math.random() * (max_by - min_by + 1)) + min_by;
    }
  }
}
JavaScript

追加した処理の確認をします。まずMath.random()0以上1未満の範囲で浮動小数点数の疑似乱数を生成します。それにmax_by - min_by + 1101をかけることで、0以上101未満の範囲で浮動小数点数の疑似乱数になります。次にMath.floor()は与えられた数値以下の最大の整数を返すので0以上100以下の範囲で整数の疑似乱数になります。最後にmin_byを足すことでmin_by100以上max_by200以下の疑似乱数をby_list[i]に代入しています。

以上でブロックのアニメーション設定が終わりました。最終的にmain.jsは以下のようになります。

main.js
// 描画コンテキストの取得
let cvs = document.querySelector("canvas");
let ctx = cvs.getContext("2d");

// 色
const BACKGROUND_COLOR = "hsl(200deg, 100%, 70%)";
const PLAYER_COLOR = "hsl(0deg, 100%, 60%)";
const PLAYER_STROKE_COLOR = "hsl(0deg, 0%, 100%)";
const BLOCK_COLOR = "hsl(230deg, 100%, 70%)";
const BLOCK_STROCK_COLOR = "hsl(0deg, 0%, 0%)";

// ゲーム変数
const FRAME_ELEMENT = 1000 / 30;

// キャンバス変数
let line_width = 2;

// プレイヤー変数
// 座標
let px = 70;
let py = 50;
// サイズ
let ps = 20;
// 速度
let pvy = 8;
// 基準速度
let standard_pvy = 8;
// ジャンプした場合の速度
let jump_pvy = -15;
// ジャンプできる最低速度
let min_jump_pvy = 6;
// 基準速度未満の場合の追加速度
let add_pvy = 1.5;
// ジャンプ判定
let jump_flag = false;

// ブロック変数
// 基準点座標
let bx_list = [0, 200, 400, 600];
let by_list = [100, 125, 150, 200];
// y座標の最小値、最大値
let min_by = 100;
let max_by = 200;
// 速度
let bvx = -2;
// 幅
let bw = 50;
// 上下のブロックのスペース
let bs = 140;
// 左右のブロックの距離
let bd = 200;

// キーイベント
document.addEventListener("keydown", event => {
  if (event.key === " ") {
    if (pvy >= min_jump_pvy) {
      jump_flag = true;
    }
  }
});

// 初期化処理
function init() {
  ctx.lineWidth = line_width;
}

// プレイヤーの更新
function update_player() {
  // ジャンプ時の処理
  if (jump_flag) {
    jump_flag = false;
    pvy = jump_pvy;
  }

  // 基準速度未満であれば追加速度を与える
  if (pvy < standard_pvy) {
    pvy += add_pvy;
  }

  // 基準速度を超えていれば基準速度にする
  if (pvy > standard_pvy) {
    pvy = standard_pvy;
  }

  // 速度をもとに座標を変更
  py += pvy;
}

// ブロックの更新
function update_blocks() {
  // 速度をもとに座標を変更
  for (let i = 0; i < bx_list.length; i++) {
    bx_list[i] += bvx;

    // x座標が-bd以下であればbd * 4を足し、y座標を変更する
    if (bx_list[i] <= -bd) {
      bx_list[i] += bd * 4;
      by_list[i] = Math.floor(Math.random() * (max_by - min_by + 1)) + min_by;
    }
  }
}

// 背景の描画
function draw_background() {
  ctx.fillStyle = BACKGROUND_COLOR;
  ctx.fillRect(0, 0, cvs.width, cvs.height);
}

// プレイヤーの描画
function draw_player() {
  ctx.strokeStyle = PLAYER_STROKE_COLOR;
  ctx.fillStyle = PLAYER_COLOR;

  ctx.strokeRect(px - ps / 2, py - ps / 2, ps, ps);
  ctx.fillRect(px - ps / 2, py - ps / 2, ps, ps);
}

// ブロックの描画
function draw_blocks() {
  ctx.strokeStyle = BLOCK_STROCK_COLOR;
  ctx.fillStyle = BLOCK_COLOR;

  for (let i = 0; i < bx_list.length; i++) {
    // 上ブロック
    ctx.strokeRect(bx_list[i] - bw / 2, 0, bw, by_list[i] - bs / 2);
    ctx.fillRect(bx_list[i] - bw / 2, 0, bw, by_list[i] - bs / 2);
    // 下ブロック
    ctx.strokeRect(bx_list[i] - bw / 2, by_list[i] + bs / 2, bw, cvs.height - (by_list[i] + bs / 2));
    ctx.fillRect(bx_list[i] - bw / 2, by_list[i] + bs / 2, bw, cvs.height - (by_list[i] + bs / 2));
  }
}

function main() {
  update_blocks();
  update_player();
  draw_background();
  draw_blocks();
  draw_player();

  setTimeout(main, FRAME_ELEMENT);
}

init();
main();
JavaScript
main.js
// 描画コンテキストの取得
let cvs = document.querySelector("canvas");
let ctx = cvs.getContext("2d");

// 色
const BACKGROUND_COLOR = "hsl(200deg, 100%, 70%)";
const PLAYER_COLOR = "hsl(0deg, 100%, 60%)";
const PLAYER_STROKE_COLOR = "hsl(0deg, 0%, 100%)";
const BLOCK_COLOR = "hsl(230deg, 100%, 70%)";
const BLOCK_STROCK_COLOR = "hsl(0deg, 0%, 0%)";

// ゲーム変数
const FRAME_ELEMENT = 1000 / 30;

// キャンバス変数
let line_width = 2;

// プレイヤー変数
// 座標
let px = 70;
let py = 50;
// サイズ
let ps = 20;
// 速度
let pvy = 8;
// 基準速度
let standard_pvy = 8;
// ジャンプした場合の速度
let jump_pvy = -15;
// ジャンプできる最低速度
let min_jump_pvy = 6;
// 基準速度未満の場合の追加速度
let add_pvy = 1.5;
// ジャンプ判定
let jump_flag = false;

// ブロック変数
// 基準点座標
let bx_list = [0, 200, 400, 600];
let by_list = [100, 125, 150, 200];
// y座標の最小値、最大値
let min_by = 100;
let max_by = 200;
// 速度
let bvx = -2;
// 幅
let bw = 50;
// 上下のブロックのスペース
let bs = 140;
// 左右のブロックの距離
let bd = 200;

// キーイベント
document.addEventListener("keydown", event => {
  if (event.key === " ") {
    if (pvy >= min_jump_pvy) {
      jump_flag = true;
    }
  }
});

// 初期化処理
function init() {
  ctx.lineWidth = line_width;
}

// プレイヤーの更新
function update_player() {
  // ジャンプ時の処理
  if (jump_flag) {
    jump_flag = false;
    pvy = jump_pvy;
  }

  // 基準速度未満であれば追加速度を与える
  if (pvy < standard_pvy) {
    pvy += add_pvy;
  }

  // 基準速度を超えていれば基準速度にする
  if (pvy > standard_pvy) {
    pvy = standard_pvy;
  }

  // 速度をもとに座標を変更
  py += pvy;
}

// ブロックの更新
function update_blocks() {
  // 速度をもとに座標を変更
  for (let i = 0; i < bx_list.length; i++) {
    bx_list[i] += bvx;

    // x座標が-bd以下であればbd * 4を足し、y座標を変更する
    if (bx_list[i] <= -bd) {
      bx_list[i] += bd * 4;
      by_list[i] = Math.floor(Math.random() * (max_by - min_by + 1)) + min_by;
    }
  }
}

// 背景の描画
function draw_background() {
  ctx.fillStyle = BACKGROUND_COLOR;
  ctx.fillRect(0, 0, cvs.width, cvs.height);
}

// プレイヤーの描画
function draw_player() {
  ctx.strokeStyle = PLAYER_STROKE_COLOR;
  ctx.fillStyle = PLAYER_COLOR;

  ctx.strokeRect(px - ps / 2, py - ps / 2, ps, ps);
  ctx.fillRect(px - ps / 2, py - ps / 2, ps, ps);
}

// ブロックの描画
function draw_blocks() {
  ctx.strokeStyle = BLOCK_STROCK_COLOR;
  ctx.fillStyle = BLOCK_COLOR;

  for (let i = 0; i < bx_list.length; i++) {
    // 上ブロック
    ctx.strokeRect(bx_list[i] - bw / 2, 0, bw, by_list[i] - bs / 2);
    ctx.fillRect(bx_list[i] - bw / 2, 0, bw, by_list[i] - bs / 2);
    // 下ブロック
    ctx.strokeRect(bx_list[i] - bw / 2, by_list[i] + bs / 2, bw, cvs.height - (by_list[i] + bs / 2));
    ctx.fillRect(bx_list[i] - bw / 2, by_list[i] + bs / 2, bw, cvs.height - (by_list[i] + bs / 2));
  }
}

function main() {
  update_blocks();
  update_player();
  draw_background();
  draw_blocks();
  draw_player();

  setTimeout(main, FRAME_ELEMENT);
}

init();
main();
JavaScript

実行結果

Chromeに移動してindex.htmlを更新します。実行結果は以下の画像のように5つ目以降のブロックが描画されそのブロックのY座標はランダムになります。

コメント

コメントはまだありません。

コメント