Chapter 55

弾幕

miku
miku
2021.11.16に更新
このチャプターの目次

この章ではシューティングゲームの表現である弾の表現や弾幕について扱う。実際にシューティングゲームを作る場合や、パーティクルのようなデザインの表現でも利用できる。

自機狙い弾

名前の通り、発射した弾が自機に向かって真っ直ぐと向かってくる。発射した時点で角度が決まるので、途中で曲がることはない。

let bullets;

function setup() {
  createCanvas(windowWidth, windowHeight);

  bullets = [];
}

function draw() {
  clear();

  if (frameCount % 10 === 0) {
    const angle = atan2(mouseY, mouseX - width / 2);
    const bullet = Bullet.create(width / 2, 0, angle, 10);
    bullets.push(bullet);
  }

  for (let i = 0; i < bullets.length; i++) {
    const bullet = bullets[i];
    Bullet.update(bullet);
    Bullet.draw(bullet);
  }

  bullets = bullets.filter((bullet) => {
    return bullet.x >= 0 && bullet.x < width && bullet.y >= 0 && bullet.y < height;
  });
}

const Bullet = {
  create: function (x, y, angle, speed) {
    return { x, y, angle, speed };
  },

  update: function (bullet) {
    bullet.x += cos(bullet.angle) * bullet.speed;
    bullet.y += sin(bullet.angle) * bullet.speed;
  },

  draw: function (bullet) {
    circle(bullet.x, bullet.y, 10);
  },
};

atan2() で弾の発射座標からマウス座標までの角度を取得して、cos(), sin() で軸ごとの成分を取得する。その成分に speed を掛けたものを速度とする。

全方位弾

特定の角度おきに360度弾を散らばす。見た目のインパクトがある上、敵の後ろに回られて攻撃を避けられるなどを防ぐ実用性もある。

let bullets;

function setup() {
  createCanvas(windowWidth, windowHeight);

  bullets = [];
}

function draw() {
  clear();

  if (frameCount % 10 === 0) {
    for (let angle = 0; angle < TWO_PI; angle += 0.2) {
      const bullet = Bullet.create(width / 2, height / 10, angle, 10);
      bullets.push(bullet);
    }
  }

  for (let i = 0; i < bullets.length; i++) {
    const bullet = bullets[i];
    Bullet.update(bullet);
    Bullet.draw(bullet);
  }

  bullets = bullets.filter((bullet) => {
    return bullet.x >= 0 && bullet.x < width && bullet.y >= 0 && bullet.y < height;
  });
}

const Bullet = {
  create: function (x, y, angle, speed) {
    return { x, y, angle, speed };
  },

  update: function (bullet) {
    bullet.x += cos(bullet.angle) * bullet.speed;
    bullet.y += sin(bullet.angle) * bullet.speed;
  },

  draw: function (bullet) {
    circle(bullet.x, bullet.y, 10);
  },
};

n-way弾

n-wayの n のところには数字が入り、たとえば4-wayだと4つ弾が並んだ弾が打ち出される。特に方向の一つが自機狙いになると、自機狙い弾に飾りを付けたような形になる。n が奇数だと真ん中の弾が自機狙いで、n が偶数だと自機を外れる形で撃ち出される事が多い。

let bullets;

function setup() {
  createCanvas(windowWidth, windowHeight);

  bullets = [];
}

function draw() {
  clear();

  if (frameCount % 60 === 0) {
    const baseAngle = atan2(mouseY, mouseX - width / 2);
    const dir = [-1, 1];
    for (let i = 0; i < 3; i++) {
      const n = i === 0 ? 1 : 2;
      for (let j = 0; j < n; j++) {
        const angle = baseAngle + 0.1 * i * dir[j];
        const bullet = Bullet.create(width / 2, 0, angle, 10);
        bullets.push(bullet);
      }
    }
  }

  for (let i = 0; i < bullets.length; i++) {
    const bullet = bullets[i];
    Bullet.update(bullet);
    Bullet.draw(bullet);
  }

  bullets = bullets.filter((bullet) => {
    return bullet.x >= 0 && bullet.x < width && bullet.y >= 0 && bullet.y < height;
  });
}

const Bullet = {
  create: function (x, y, angle, speed) {
    return { x, y, angle, speed };
  },

  update: function (bullet) {
    bullet.x += cos(bullet.angle) * bullet.speed;
    bullet.y += sin(bullet.angle) * bullet.speed;
  },

  draw: function (bullet) {
    circle(bullet.x, bullet.y, 10);
  },
};