ソースコード解説・目次

CHAPTER 11 · 全23項目

スコア・コンボ・残機

撃破時の加点、2.2秒のコンボ猶予、残機の増加とハイスコア保存を追います。

主な参照先:killAlien / COMBO_STEPS / bumpCombo / addScore / saveHi

撃破の処理は1か所に集める

killAlien() は生存フラグを確認してから敵を消し、生存数を減らします。その後、ゲージ充電、コンボ更新、加点、粒子やリング、カプセル抽選、ヒットストップ、効果音をまとめて処理します。複数の弾が同じ敵を調べても、二重に得点しないための入口にもなっています。

上の段ほど多くつなぐ

game.html · L804–806ソースを見る ↗
const COMBO_WINDOW = 2.2;
// ×2〜×8 に上がるのに必要な連続撃破数。上の段ほど多くつなぐ必要があり、×8 は 1 ウェーブをほぼ途切れずに撃ち続けた証になる。
const COMBO_STEPS = [3, 7, 12, 18, 25, 33, 42];
game.html · L999–1009ソースを見る ↗
function bumpCombo() {
  combo.n++; combo.t = COMBO_WINDOW;
  let m = 1;
  while (m <= COMBO_STEPS.length && combo.n >= COMBO_STEPS[m - 1]) m++;
  if (m > combo.mult) {
    combo.mult = m;
    maxMult = Math.max(maxMult, m);
    popup(player.x, PLAYER_Y - 34, `COMBO ×${m}`, MULT_COLORS[m - 1], 13);
    sfx.tier(m);
  }
}

撃破するたびに残り時間を COMBO_WINDOW、つまり2.2秒へ戻します。COMBO_STEPS は×2〜×8に上がるのに必要な連続撃破数で、3体で×2、7体で×3、12体で×4…42体で最大の×8になります。段が上がるほど必要な数が増えるので、×8は1ウェーブ(50体)をほとんど途切れずに撃ち続けたときだけ届きます。

while ループは、combo.n が届いている段の数だけ m を進めます。通常の敵の素点は上段30点、中段20点、下段10点。倍率を更新してから加点するので、3体目から新しい倍率が適用されます。コンボは被弾したとき、2.2秒の時間切れ、そして次のウェーブの開始時(makeWave() の resetCombo())に×1へ戻ります。

10000点で1機、以降20000点ごとに残機を増やす

game.html · L803–803ソースを見る ↗
const FIRST_LIFE = 10000, LIFE_STEP = 20000; // 1UP は 10000 点で 1 回、以降 20000 点ごと

残機が増える点数は定数で決めています。最初は FIRST_LIFE の10000点、それ以降は LIFE_STEP の20000点ごとなので、10000点、30000点、50000点…で残機が1つ増えます。

game.html · L972–984ソースを見る ↗
function addScore(n) {
  score += n;
  if (score > hi) { hi = score; newRecord = true; }
  while (score >= nextLife) {
    nextLife += LIFE_STEP;
    if (lives < 5) {
      lives++;
      // 画面中央の WAVE 表示・WAVE CLEAR!・PERFECT!・次のウェーブの予告 (y=244〜380) と重ならない高さに出す。
      popup(W / 2, 430, "1UP!", "#ffe066", 20);
      sfx.oneUp();
    }
  }
}

次の残機獲得ラインを nextLife で管理します。ゲーム開始時に FIRST_LIFE を入れておき、ラインを越えるたびに LIFE_STEP を足します。大きな加点で複数のラインをまたいでも処理できるよう while を使います。残機は最大5ですが、満タンでもライン自体は先へ進みます。

「1UP!」の表示は画面中央ではなく y=430 に出します。中央付近 (y=244〜380) にはウェーブ開始の表示や「WAVE CLEAR!」「PERFECT!」、次のウェーブで始まる攻撃の予告が出るため、文字が重ならない高さにずらしています。

保存する値と表示する値

game.html · L970–970ソースを見る ↗
function saveHi() { try { localStorage.setItem(HI_KEY, String(hi)); } catch (e) {} }

ハイスコアはゲームオーバー時に localStorage へ文字列として保存します。読み書きに失敗してもゲームを続けられるよう try / catch で囲っています。画面用の scoreShown は実際の score に少しずつ近づけ、数字が滑らかに増える演出に使います。