練習問題 9-1:ボールの移動とブロック崩し

■ ボールの移動

  • ボールの座標は x, y で管理する。
  • 移動は x += dx, y += dy のように行う。
  • 左右の壁に当たったら dx = -dx として向きを反転する。
  • 上の壁に当たったら dy = -dy として向きを反転する。

■ ラケットでボールを打ち返す

  • ラケットの幅は 80
  • mouseX をラケットの左端とし、当たり判定は以下の条件で行う。
mouseX - 10 < x && x < mouseX + 90

■ 例題 9-1-1:ボールの移動と跳ね返り

  • ボールを上下左右に移動させ、壁やラケットで跳ね返す処理を作成する。
let x = 100, y = 20;
let dx = 4, dy = 4;

function ballMove() {
  x += dx; y += dy;
  ellipse(x, y, 20, 20);
  if (x < 10 || width - 10 < x) dx = -dx;
  if (y < 10) dy = -dy;
}

function checkRacket() {
  if (mouseX - 10 < x && x < mouseX + 90 && y == 344)
    dy = -dy;
}

function setup() {
  createCanvas(300, 400);
  noStroke();
  fill(0);
}

function draw() {
  background(220);
  rect(mouseX, 354, 80, 20);
  ballMove();
  checkRacket();
}

■ 練習問題 9-1-1:ボールの複数管理と得点表示

次の機能を追加せよ。

  • ボールの数を ballN で管理し、最大3個まで使用可能とする。
  • ボールがラケットに当たるたびに得点を +10 する。
  • ボールが落下した場合、1個減らし、位置を初期化する。
let x = 100, y = 124;
let dx = 4, dy = 4;
let ballN = 3;
let score = 0;

function draw() {
  background(220);
  text("Score: " + score, 10, 20);
  text("Ball: " + ballN, 240, 20);
  rect(mouseX, 354, 80, 20);
  
  if (ballN > 0) {
    ballMove();
    checkRacket();
    if (y > 390) {
      ballN--;
      x = 100;
      y = 124;
    }
  }
}

■ 練習問題 9-1-2:出現位置のランダム化と待機処理

次の機能を追加せよ。

  • ボールの出現位置をランダムに設定する。
  • ボールが落下してから次のボールが出るまで、一定時間待機する。
function rnd(m, n) {
  return Math.floor(Math.random() * (n - m + 1)) + m;
}

function sleep(ms) {
  const start = new Date().getTime();
  while (new Date().getTime() - start < ms) {}
}

// 使い方例:
x = rnd(20, 280);
sleep(500);  // 0.5秒待機

■ 練習問題 9-1-3:ブロック表示と当たり判定

次の機能を追加せよ。

  • ブロックの有無を示す配列 m[][] を作成する。値が 1 のときブロックが存在する。
  • ブロックは 6列 × 3行 に配置し、サイズは 横50×縦20、隙間は横2ピクセル、縦10ピクセルとする。
  • block() 関数でブロックを表示する。
  • blockCheck() 関数で、ボールがブロックに当たったかを判定する。ヒットした場合、ブロックを消し、得点を +10 する。

📦 ステップ①:ブロック配列の作成

  • ブロックがある:1
  • ブロックがない:0

として、次のような配列 m を作る。

const m = [
  [1, 1, 1, 1, 1, 1],  // 1行目
  [1, 1, 1, 1, 1, 1],  // 2行目
  [1, 1, 1, 1, 1, 1]   // 3行目
];

📐 ステップ②:ブロックの表示(block()関数)

  • ブロックは 横50×縦20 ピクセル。
  • 横方向の間隔は 2ピクセル、縦方向の間隔は 10ピクセル
  • 配列 m[i][j] が「1」のときだけブロックを表示する。
function block() {
  for (let i = 0; i < 3; i++) {
    for (let j = 0; j < 6; j++) {
      if (m[i][j] === 1) {
        rect(j * 50 + 2, i * 20 + 50, 46, 10);
      }
    }
  }
}

📎 図解イメージ
(マス目+インデックス番号がある画像と一緒に使う)

   j →     0     1     2     3     4     5
i ↓  +---------------------------------------
   0 | [1] [1] [1] [1] [1] [1]
   1 | [1] [1] [1] [1] [1] [1]
   2 | [1] [1] [1] [1] [1] [1]

🎯 ステップ③:ボールがブロックに当たったか判定(blockCheck()関数)

🧮 判定の考え方

ボールの中心座標 (x, y) が、どのブロックのマスにいるかを 計算で求める:

let i = Math.floor((y - 50) / 20);
let j = Math.floor(x / 50);
  • i:縦のインデックス(行番号)
  • j:横のインデックス(列番号)

🧠 補足:

  • ブロックの上端は y = 50 ピクセルからスタート
  • Math.floor() を使って整数に切り下げ

✅ ステップ④:当たり判定の実装

function blockCheck() {
  if (0 < x && x < 300 && 50 < y && y < 110) {
    let i = Math.floor((y - 50) / 20);
    let j = Math.floor(x / 50);

    if (m[i][j] === 1) {
      dy = -dy;
      m[i][j] = 0;     // ブロックを消す
      score += 10;     // 得点を加算
    }
  }
}

💡 ポイントまとめ

内容説明
ブロック配列1:あり、0:なし
配置横6列×縦3行、1つのサイズは50×20ピクセル
表示条件m[i][j] === 1のとき表示する
判定式i = Math.floor((y - 50)/20)
j = Math.floor(x / 50)
当たったらブロック削除+スコア加算+向きを反転

📸 画像例:(ball = 3、score = 80)


■ 練習問題 9-1-4:自由課題

  • 任意の機能を追加し、ゲームを発展させよ。
    • 例:ボール速度の変化、ブロックの色変更、ゲームクリア、ゲームオーバーなど。

コメントする