JavaScriptでシューティングゲームをゼロから作ろう!

JavaScriptでシューティングゲームをゼロから作ろう!

HTML・CSS・JavaScriptだけで、ブラウザで動く本格シューティングゲームを完成させるチュートリアルです。
ボス戦・パワーアップ・コンボシステムまで実装して、アーケードゲーム級の作品に仕上げよう。

⏱ 読了:約30分 🎯 対象:プログラミング初心者〜

📋 もくじ

  1. 完成するとどうなる?
  2. 準備するもの
  3. ファイル構成を作ろう
  4. HTMLを書こう
  5. CSSでデザインしよう
  6. JavaScriptの基本構造を書こう
  7. ゲームループを作ろう
  8. 自機を動かそう
  9. 弾を撃とう(オブジェクトプール)
  10. 敵を出現させよう
  11. 当たり判定を作ろう
  12. ボス戦を実装しよう
  13. エフェクトを追加しよう
  14. サウンドをコードだけで作ろう
  15. レベル&コンボシステムを作ろう
  16. 完成コード全文
  17. 動かしてみよう
  18. 次のステップ

完成するとどうなる?

この記事を最後まで読むと、ブラウザ上で動く本格シューティングゲームが完成します。ただのシューティングじゃなくて、こんな機能がついています:

  • 自機が上下左右に動いて自動連射する
  • ザコ敵・中型敵・高速突進敵の3種類の敵が出現
  • スコアが3000点たまるたびにボス戦が始まる(WARNING!演出つき)
  • ボスには全方位弾幕・レーザー照射・ザコ召喚の3つの攻撃パターン
  • 敵を連続で倒すとコンボがつながってスコアがどんどん増える
  • 3WAY弾・スピードアップ・ボムのパワーアップアイテム
  • 爆発パーティクル・画面シェイク・ヒットストップのジューシーな演出
  • 音声ファイルなし!Web Audio APIでコードだけで効果音を生成

使うのは HTML・CSS・JavaScript の3つだけ。特別なライブラリやフレームワークは使いません。約2,900行でアーケードゲーム級のゲームが作れます!

準備するもの

以下の2つだけ用意してください。

  • テキストエディタWeb版のVS Codeだとインストール不要!)
  • Webブラウザ(Chrome、Edge、Safariなど何でもOK)

ファイル構成を作ろう

パソコンのどこかにフォルダを1つ作ります。名前は shooting にしましょう。その中に3つのファイルを作ります。

shooting/
    index.html ─ 画面の構造
    style.css  ─ 見た目のデザイン
    script.js  ─ ゲームの動き(約2,900行)

Webページは基本的にこの3つの役割分担でできています。HTMLが骨組み、CSSが見た目、JavaScriptが動き。テトリスの記事でもやった構成と同じです。

HTMLを書こう

index.html を開いて、以下のコードを書いてください。

<!doctype html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>シューティングゲーム</title>
    <link rel="stylesheet" href="style.css" />
  </head>

  <body>
    <canvas id="gameCanvas"></canvas>
    <script src="script.js"></script>
  </body>
</html>

HTMLのポイント解説

テトリスの時と比べてかなりシンプルです。<canvas> タグが1つあるだけ。スコア表示もHP表示も、すべてJavaScriptのCanvas描画で行うので、HTML側には余計な要素を置きません。

<canvas> は「自由に絵が描ける画用紙」みたいなもの。ここにJavaScriptから宇宙船や敵やレーザーを描いていきます。

CSSでデザインしよう

style.css にゲームの見た目を書きます。

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  background-color: #000;
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
}

canvas {
  display: block;
  box-shadow: 0 0 40px rgba(0, 200, 255, 0.12),
              0 0 80px rgba(0, 100, 200, 0.06);
  border: 1px solid rgba(0, 200, 255, 0.08);
}

CSSのポイント解説

背景を真っ黒にして、Canvasを画面のど真ん中に配置しています。box-shadow でCanvasの周りにシアン色のうっすら光るエフェクトをつけて、ネオン風の雰囲気を出しています。

ゲームの描画はすべてJavaScript側で行うので、CSSは最小限。これがCanvas系ゲームの特徴です。

JavaScriptの基本構造を書こう

ここからがメイン! script.js に書いていくコードを、セクションごとに解説していきます。

Canvasの初期化

const CANVAS_WIDTH = 400;
const CANVAS_HEIGHT = 700;

const canvas = document.getElementById("gameCanvas");
const ctx = canvas.getContext("2d");
canvas.width = CANVAS_WIDTH;
canvas.height = CANVAS_HEIGHT;

getContext("2d") で、2Dの絵を描く「ペン」を手に入れます。テトリスでは context.scale(20, 20) で座標を拡大しましたが、今回はピクセル単位でそのまま描画します。

ゲーム状態の管理(ステートマシン)

const STATE = {
  TITLE: "title",
  PLAYING: "playing",
  GAMEOVER: "gameover",
};

let gameState = STATE.TITLE;

ゲームには「タイトル画面」「プレイ中」「ゲームオーバー」の3つの状態があります。gameState 変数を切り替えることで、同じ画面でまったく違う動きを実現しています。これをステートマシン(状態機械)と呼びます。ゲーム開発ではど定番のパターンです。

ゲームループを作ろう

ゲームの心臓部、ゲームループを作ります。

let lastTime = 0;

function gameLoop(timestamp) {
  // 前フレームからの経過時間を秒に変換
  const rawDelta = lastTime === 0 ? 0 : (timestamp - lastTime) / 1000;
  lastTime = timestamp;

  const deltaTime = rawDelta;

  // --- 更新 ---
  switch (gameState) {
    case STATE.TITLE:
      updateTitle(deltaTime);
      break;
    case STATE.PLAYING:
      updatePlaying(deltaTime);
      break;
    case STATE.GAMEOVER:
      updateGameOver(deltaTime);
      break;
  }

  // --- 描画 ---
  drawBackground(deltaTime);

  switch (gameState) {
    case STATE.TITLE:
      drawTitle();
      break;
    case STATE.PLAYING:
      drawPlaying();
      break;
    case STATE.GAMEOVER:
      drawGameOver();
      break;
  }

  // 次のフレームを予約
  requestAnimationFrame(gameLoop);
}

// ゲーム開始!
requestAnimationFrame(gameLoop);

ここで何をしてる?

requestAnimationFrame は「次の画面更新のタイミングで関数を呼んでね」とブラウザにお願いする関数です。これを繰り返すことで、毎秒約60回画面が更新されるループが完成します。

deltaTime(デルタタイム)は「前のフレームから何秒経ったか」を表す数値です。60FPSなら約 0.016秒。なぜこれが必要か? パソコンの性能によってFPSが変わっても、同じ速度でゲームが動くようにするためです。移動量を 速度 × deltaTime で計算すれば、高性能PC(120FPS)でも低性能PC(30FPS)でも同じ体験になります。

switch 文でゲーム状態ごとに違う処理を呼び分けているのもポイント。タイトル画面ではタイトルを描画し、プレイ中ではゲームロジックを走らせ、ゲームオーバーではスコアを表示……と、状態ごとに完全に分離できます。

自機を動かそう

キー入力の管理

const keys = {
  ArrowLeft: false,
  ArrowRight: false,
  ArrowUp: false,
  ArrowDown: false,
};

document.addEventListener("keydown", (e) => {
  if (e.key in keys) {
    keys[e.key] = true;
    e.preventDefault(); // 矢印キーでページがスクロールしないように
  }
});

document.addEventListener("keyup", (e) => {
  if (e.key in keys) keys[e.key] = false;
});

keydown でキーの状態を true に、keyupfalse に戻します。こうすると「キーが押されているかどうか」を毎フレーム確認できるので、押しっぱなしでスムーズに移動できます。

自機の移動

const PLAYER_SPEED = 300; // px/秒

const player = {
  x: CANVAS_WIDTH / 2,
  y: CANVAS_HEIGHT - 80,
  width: 32,
  height: 36,
  hp: 5,
  tilt: 0, // 左右移動時の傾き
};

function updatePlayer(deltaTime) {
  let dx = 0;
  let dy = 0;
  if (keys.ArrowLeft) dx -= 1;
  if (keys.ArrowRight) dx += 1;
  if (keys.ArrowUp) dy -= 1;
  if (keys.ArrowDown) dy += 1;

  player.x += dx * PLAYER_SPEED * deltaTime;
  player.y += dy * PLAYER_SPEED * deltaTime;

  // 画面外に出ないよう制限
  const hw = player.width / 2;
  player.x = Math.max(hw, Math.min(CANVAS_WIDTH - hw, player.x));
  player.y = Math.max(minY, Math.min(CANVAS_HEIGHT - player.height / 2, player.y));

  // 傾き演出:左右移動で機体が傾く
  const targetTilt = dx * (8 * Math.PI / 180);
  player.tilt += (targetTilt - player.tilt) * Math.min(1, 10 * deltaTime);
}

移動量は 方向 × 速度 × deltaTime で計算しています。Math.max / Math.min で画面端からはみ出さないようにクランプ(制限)しているのもポイント。

自機の描画

function drawPlayer() {
  const { x, y, width, height, tilt } = player;

  ctx.save();
  ctx.translate(x, y);
  ctx.rotate(tilt);

  // グロウエフェクト
  ctx.shadowColor = "#00ffff";
  ctx.shadowBlur = 18;

  // 三角形の宇宙船
  ctx.beginPath();
  ctx.moveTo(0, -height / 2);        // 機首(上)
  ctx.lineTo(-width / 2, height / 2); // 左翼端
  ctx.lineTo(0, height / 2 - 8);     // くびれ
  ctx.lineTo(width / 2, height / 2);  // 右翼端
  ctx.closePath();

  ctx.fillStyle = "rgba(0, 200, 220, 0.15)";
  ctx.fill();
  ctx.strokeStyle = "#00ffff";
  ctx.lineWidth = 2;
  ctx.stroke();

  ctx.restore();
}

ctx.translate()ctx.rotate() で座標系を自機の位置に移動してから描画しています。こうすると、自機の位置が変わっても描画コードは常に「原点を基準」に書けるので楽になります。

shadowColorshadowBlur でネオンのような発光エフェクトをつけています。影の色をシアンにして、ぼかしを強くすると光って見えるんです!

弾を撃とう(オブジェクトプール)

🔑 このゲーム最大の設計ポイント:オブジェクトプール

シューティングゲームでは弾が大量に飛び交います。弾を撃つたびに new Object() で作って、画面外に出たら捨てる……とやると、JavaScriptの**ガベージコレクション(GC)**が頻繁に動いてカクつきます。

そこで使うのがオブジェクトプールパターン。最初にまとめて作っておいて、active フラグで使い回します。

const BULLET_POOL_SIZE = 80;
const BULLET_SPEED = 600;
const SHOT_INTERVAL = 0.12; // 自動連射の間隔(秒)

// 80個分の弾を事前に確保
const bulletPool = Array.from({ length: BULLET_POOL_SIZE }, () => ({
  active: false,
  x: 0,
  y: 0,
  vx: 0,
  vy: 0,
}));

// 空いている弾を1つ探す
function acquireFromPool(pool) {
  for (const item of pool) {
    if (!item.active) return item;
  }
  return null; // 全部使用中ならスキップ
}

// 弾を発射
function fireBullet(x, y, vx = 0, vy = -BULLET_SPEED) {
  const b = acquireFromPool(bulletPool);
  if (!b) return;
  b.active = true;
  b.x = x;
  b.y = y;
  b.vx = vx;
  b.vy = vy;
}

プールなし vs プールあり

プールなし

プールあり

弾を撃つとき

new Object() で新規作成

active = true に変更

弾が消えるとき

ゴミ箱(GC)が回収

active = false に変更

パフォーマンス

GCでカクつく

GCが起きない!

このパターンは弾だけでなく、敵・パーティクル・敵弾にも使っています。ゲーム開発の鉄則です。

自動連射の仕組み

let shotTimer = 0;

function updateBullets(deltaTime) {
  shotTimer += deltaTime;
  while (shotTimer >= SHOT_INTERVAL) {
    shotTimer -= SHOT_INTERVAL;
    fireBullet(player.x, player.y - player.height / 2);
    playShootSound();
  }

  // 弾の移動&画面外判定
  for (const b of bulletPool) {
    if (!b.active) continue;
    b.x += b.vx * deltaTime;
    b.y += b.vy * deltaTime;
    if (b.y < -15 || b.x < -50 || b.x > CANVAS_WIDTH + 50) {
      b.active = false;
    }
  }
}

shotTimer で時間を計って、0.12秒ごとに弾を発射しています。プレイヤーが何もしなくても自動で撃ち続けるので、操作は移動に集中できます。

敵を出現させよう

このゲームには3種類の敵がいます。

ザコ敵(ひし形・赤)

const ENEMY_POOL_SIZE = 30;
const ENEMY_SPEED_Y = 150;
const ENEMY_SINE_AMPLITUDE = 30; // 左右揺れの幅

const enemyPool = Array.from({ length: ENEMY_POOL_SIZE }, () => ({
  active: false,
  x: 0, y: 0, baseX: 0,
  time: 0, phase: 0,
  hp: 1,
  radius: 10,
}));

ザコ敵はサイン波で左右に揺れながら降りてきます。Math.sin() を使って波状の動きを作るのは、ゲームプログラミングの定番テクニックです。

// サイン波で左右に揺れる
e.x = e.baseX + Math.sin(e.time / 2 * Math.PI * 2 + e.phase) * 30;

編隊出現もあります。5〜8体を横一列に並べて、少しずつ位相をずらすことでウェーブ状の動きになります。

中型敵(八角形・オレンジ)

HP4で、降下→停止→プレイヤーに向けて扇状に3発発射→再降下という行動パターン。撃破するとパワーアップアイテムをドロップすることがあります。

突進敵(三角形・緑)

画面横から高速で斜めに突っ込んでくるタイプ。残像エフェクトつき。残像はリングバッファ(固定サイズの配列を循環して使う)で実装しています。

当たり判定を作ろう

📐 数学の出番!円形の当たり判定

見た目は三角形やひし形でも、当たり判定はで行います。2つの円の中心同士の距離が、半径の合計より小さければ「当たり」。

const BULLET_RADIUS = 1.5; // 弾の半径

function checkCollisions() {
  for (const b of bulletPool) {
    if (!b.active) continue;

    for (const e of enemyPool) {
      if (!e.active) continue;

      const dx = b.x - e.x;
      const dy = b.y - e.y;

      // 2点間の距離 < 半径の合計 → ヒット!
      if (Math.hypot(dx, dy) < BULLET_RADIUS + e.radius) {
        b.active = false;
        e.hp -= 1;
        if (e.hp <= 0) {
          e.active = false;
          spawnExplosion(e.x, e.y); // 爆発エフェクト
          score += onKill(100);     // コンボ付きスコア
          playDestroySound();
        }
      }
    }
  }
}

💡 Math.hypot() = 三平方の定理

Math.hypot(dx, dy)√(dx² + dy²) を計算する関数で、**三平方の定理(ピタゴラスの定理)**そのものです。中学数学で習う公式がゲーム開発にそのまま使われています。三角関数(Math.sin, Math.cos, Math.atan2)も敵弾の角度計算やレーザーの方向決定で大活躍します。

ボス戦を実装しよう

スコアが3000点に達するたびにボスが出現します。

ボス出現の演出

function checkBossSpawn() {
  if (score >= nextBossScore) {
    bossIntro.phase = "warning"; // WARNING!表示開始
  }
}

演出は3段階で進みます。

  1. WARNING! が赤く点滅(2秒間)
  2. 画面が暗転(0.3秒)
  3. ボスが上から降りてくる

出現時には低音BGM(60Hz × 8パルス)が鳴って、緊張感を演出します。

3つの攻撃パターン

ボスは3秒ごとにパターンをローテーションします。

パターンA:全方位弾幕

function fireBossOmni() {
  for (let i = 0; i < 16; i++) {
    const angle = (i / 16) * Math.PI * 2;
    const b = acquireFromPool(enemyBulletPool);
    if (!b) continue;
    b.active = true;
    b.x = boss.x;
    b.y = boss.y;
    b.vx = Math.cos(angle) * bulletSpeed;
    b.vy = Math.sin(angle) * bulletSpeed;
  }
}

パターンB:レーザー照射

プレイヤーの方向を1秒間追尾する予告線を表示してから、太いレーザーを0.5秒間照射します。当たるとダメージ!

パターンC:ザコ召喚

ボスの周りにザコ敵3体を呼び出します。ボスを攻撃しつつザコも処理しなければなりません。

ヒットストップ演出

ボスを倒した瞬間、ゲーム全体が0.3秒間スローモーションになります。

// ヒットストップ中はゲーム時間を1/10に
if (hitStopTimer > 0) hitStopTimer = Math.max(0, hitStopTimer - rawDelta);
const deltaTime = hitStopTimer > 0 ? rawDelta * 0.1 : rawDelta;

たった2行のコードで「倒した瞬間の重み」を表現できます。格闘ゲームやアクションゲームでもよく使われるテクニックです。

エフェクトを追加しよう

このゲームの「すごいところ」は演出です。6つのエフェクトでゲームをリッチにしています。

背景の星(パララックス)

// 遠い星(50個)と近い星(30個)を2層で配置
const starsFar = Array.from({ length: 50 }, () => createStar("far"));
const starsNear = Array.from({ length: 30 }, () => createStar("near"));

遠い星は小さくゆっくり流れ、近い星は大きく速く流れます。2つの層を重ねることで**奥行き感(パララックス効果)**が生まれます。

爆発パーティクル

function spawnExplosion(x, y, count = 20, baseHue = 0) {
  for (let i = 0; i < count; i++) {
    const angle = Math.random() * Math.PI * 2;
    const speed = 60 + Math.random() * 200;
    const p = acquireFromPool(explosionPool);
    p.active = true;
    p.x = x;
    p.y = y;
    p.vx = Math.cos(angle) * speed;
    p.vy = Math.sin(angle) * speed;
    p.hue = baseHue + Math.random() * 30;
    // ...
  }
}

撃破時に20〜30個のパーティクルが放射状に飛び散ります。HSLカラーで色相(hue)を変えることで、ザコは赤、中型はオレンジ、突進は緑……と敵ごとに爆発の色を変えています。

画面シェイク

if (screenShake.timer > 0) {
  const intensity = screenShake.intensity * (screenShake.timer / screenShake.duration);
  ctx.translate(
    (Math.random() * 2 - 1) * intensity,
    (Math.random() * 2 - 1) * intensity
  );
}

被弾やボス撃破の瞬間に ctx.translate() でキャンバス全体をランダムにずらして揺れを表現しています。intensity を時間とともに減衰させることで、揺れが徐々に収まります。

その他のエフェクト

  • 流れ星:3〜5秒ごとにランダムに出現。グラデーショントレイルで尾を引く
  • ネオングリッド:画面左右にレトロ風のグリッドライン。奥ほど細く暗くなる(パースペクティブ)
  • スクリーンフラッシュ:被弾時に画面全体が一瞬赤く光る
  • コンボ表示:コンボ5以上で画面端がレインボーに、10以上でテキストもレインボーに

サウンドをコードだけで作ろう

このゲームの特徴の1つが、音声ファイルを一切使わないこと。すべての効果音をWeb Audio APIでリアルタイム生成しています。

let audioCtx = null;

// ユーザーが最初にキーを押した瞬間に初期化
function initAudio() {
  if (audioCtx) return;
  audioCtx = new (window.AudioContext || window.webkitAudioContext)();
}

// 発射音:800Hz のサイン波、50ms
function playShootSound() {
  if (!audioCtx) return;
  const osc = audioCtx.createOscillator();
  const gain = audioCtx.createGain();
  osc.type = "sine";
  osc.frequency.setValueAtTime(800, audioCtx.currentTime);
  gain.gain.setValueAtTime(0.1, audioCtx.currentTime);
  gain.gain.exponentialRampToValueAtTime(0.001, audioCtx.currentTime + 0.05);
  osc.connect(gain);
  gain.connect(audioCtx.destination);
  osc.start();
  osc.stop(audioCtx.currentTime + 0.05);
}

音の作り方

効果音

波形

周波数

長さ

発射音

サイン波

800Hz

50ms

撃破音

サイン波 + ノイズ

200Hz

150ms

被弾音

のこぎり波 800→100Hz

スイープ

100ms

アイテム取得

C→E→G→C アルペジオ

261〜523Hz

200ms

ボス登場

サイン波パルス

60Hz × 8回

1秒

レベルUP

C+E 和音

261+329Hz

200ms

createOscillator() で波形を作り、createGain() で音量を制御、exponentialRampToValueAtTime() で減衰させる。たったこれだけで様々な効果音が作れます!

ブラウザの制限に注意

ブラウザのセキュリティ上、ユーザーが操作する前に音を鳴らすことはできません。だから initAudio() はSPACEキーが押されたタイミングで呼んでいます。

レベル&コンボシステムを作ろう

レベルシステム

const LEVEL_UP_INTERVAL = 30; // 30秒ごと
const MAX_LEVEL = 10;

// Lv.1〜10 の間を線形補間
function levelLerp(minVal, maxVal) {
  const t = (gameLevel - 1) / (MAX_LEVEL - 1);
  return minVal + (maxVal - minVal) * t;
}

function getEnemySpawnInterval() {
  return levelLerp(1.5, 0.4); // Lv.1: 1.5秒 → Lv.10: 0.4秒
}

30秒ごとにレベルアップし、敵の出現間隔・編隊確率・敵弾速度がすべて levelLerp() で滑らかに上昇します。線形補間(lerp)は、ゲームの難易度バランスを取るときの必須テクニックです。

コンボシステム

const COMBO_TIMEOUT = 1.0; // 1秒以内に次を倒せばコンボ継続

function onKill(baseScore) {
  comboCount++;
  comboTimer = COMBO_TIMEOUT;
  return Math.round(baseScore * (1 + comboCount * 0.1));
}

敵を1秒以内に連続撃破するとコンボが加算され、スコアにボーナス倍率がかかります。コンボ数に応じて演出も豪華になります。

コンボ数

演出

2〜4

コンボ数テキスト表示(白)

5〜9

画面端がレインボーに光る + テキスト黄色

10〜

テキストもレインボーに!

パワーアップアイテム

中型敵を倒すと30%の確率でパワーアップアイテムが落ちてきます。

  • W(黄色):3WAY弾 — 3方向に弾を撃つ(15秒間)
  • S(緑色):スピードUP — 移動速度1.5倍(15秒間)
  • B(赤色):ボム — 画面上の敵を全滅+敵弾消し

アイテムは六角形で描画され、虹色にキラキラ回転しながら降りてきます。

完成コード全文

以下が3ファイルの完成コードです。そのままコピペして使ってOK! HTMLとCSSは上で書いた通り。JavaScriptは約2,900行あるので、ファイルに直接コピーしてください。

script.js(完成版)

コード全文が非常に長い(約2,900行)ため、以下のリンクからダウンロードしてください。

👉 完成コードをダウンロードする

全コードをコピーして script.js という名前で保存すればOKです。

記事の中で解説した各セクションが、コメント付きで整理されています:

script.js の構成
├── 定数・設定(1-13行)
├── Canvas初期化(17-21行)
├── 背景演出:星・流れ星・グリッド(42-201行)
├── プレイヤー:移動・描画・パーティクル(204-431行)
├── サウンドシステム(434-488行)
├── 弾:プール・発射・描画(490-640行)
├── 敵:ザコ・中型・突進(642-1141行)
├── 爆発パーティクル(1152-1241行)
├── コンボ・スコアポップアップ(1244-1402行)
├── パワーアップ&ボム(1404-1614行)
├── ボス戦(1617-2068行)
├── 衝突判定(2071-2405行)
├── レベルシステム(2152-2267行)
└── UI表示・演出・メインループ(2270-2880行)

動かしてみよう

3つのファイルを保存したら、index.html をダブルクリックしてブラウザで開いてみましょう。「PRESS SPACE TO START」と表示されたらスペースキーを押してゲーム開始!

←→↑↓:自機の移動(弾は自動連射)

もし画面が真っ黒のままだったり、エラーが出る場合は以下をチェックしてみてください:

  • 3つのファイルが同じフォルダに入っているか?
  • ファイル名は index.htmlstyle.cssscript.js になっているか?
  • ブラウザの開発者ツール(F12キー)のConsoleタブにエラーが出ていないか?

次のステップ

シューティングゲームが動いたら、次はカスタマイズに挑戦してみましょう!自分でコードをいじって遊ぶのが、プログラミング上達の一番の近道です。

チャレンジアイデア

  • 弾の速度や色を変えるBULLET_SPEEDfillStyle を好きな値に変えてみる
  • 新しい敵の種類を追加する:既存の敵のコードを参考に、動きの違う敵を作ってみる
  • ハイスコアを保存するlocalStorage を使えばブラウザを閉じてもスコアが残る
  • 自機のデザインを変えてみるdrawPlayer() の描画コードを書き換えて自分だけの機体に
  • 新しいパワーアップを考えて実装:シールド?ホーミング弾?レーザー?
  • BGMを追加する:Web Audio APIのオシレーターを組み合わせてメロディーを作ってみる

わからないことがあったら「JavaScript Canvas ○○」で検索してみよう。Canvasの描画APIはWebのゲーム開発で超よく使うので、覚えておくと他のゲームも作れるようになるよ!

野澤嘉孝

この記事を書いた人

野澤 嘉孝

ソフトウェアエンジニア。同志社大学理工学部を経て、京都大学大学院で核融合発電の基礎研究(プラズマ物理)に従事。在学中は高校生向け数学塾の講師を、大学院では大学生に対して物理実験の授業を担当し、延べ500名以上の学生をサポート。現在は業界特化型SaaSの開発に携わりながら、中高生向けプログラミングスクール Sandbox(サンドボックス)の運営を行う。

"自分で作れた"が生まれるスクール、Sandbox

Sandboxについて詳しく見る > すぐに相談したい方は → 無料面談に申し込む まずは気軽に → Peatixで無料体験イベントを見る(オンライン・無料)

入会金無料・いつでも退会OK・退会後もいつでも再入会できます