Javascript(43)ChatGPTとCanvasアニメーションで遊ぼう

カラフルなJavascriptの画像 javascript

前回はChatGPTでハノイの塔の解き方について紹介しました。

Javascript(42)ChatGPTでハノイの塔の解き方
今回は、javascriptとChatGPTを使用してハノイの塔を解き方を紹介していこうと思います。

今回はChatGPTとCanvasアニメーションで遊ぼうについて紹介していきます。

【もっと詳しく知りたい人は是非これを読んでください!!】

1冊ですべて身につくJavaScript入門講座 [ Mana ]

価格:2794円
(2025/1/12 23:09時点)
感想(2件)

 

JavaScriptで花火シミュレーター!ChatGPTとCanvasアニメーションで遊ぼう

ブラウザ上に色とりどりの花火を打ち上げてみませんか?本記事では、JavaScriptとHTML5 Canvasを使って、インタラクティブな花火シミュレーターを初心者向けに実装していきます。

JavaScriptの基本文法を理解している方であれば大丈夫!プログラミング初心者でも楽しみながら学べるように、ChatGPTが解説サポート役として登場し、Canvasを使ったアニメーションの基礎から花火の爆発演出まで丁寧に説明します。

以下のステップで段階的に花火アニメーションを作成していきましょう。

  • Canvasの準備と小さな円の描画
  • 円に色をつける
  • 複数の花火をランダムな位置に打ち上げる
  • アニメーションループで花火を動かす(setIntervalrequestAnimationFrameの使い方)
  • 爆発時の粒子(パーティクル)による演出

それでは早速、夜空に花火を咲かせるプログラミングの旅に出発しましょう!

Canvasとは?(ChatGPT解説)

まずは「Canvasって何?」という疑問について、ChatGPTに聞いてみましょう。

ChatGPT: 「Canvas(キャンバス)」は、HTML5で導入された描画用のHTML要素です。キャンバスはまさに名前の通り絵を描くキャンバスのようなもので、<canvas>タグでページ上に作られます。ただし、キャンバス単体には絵や図形の描画機能はありません。JavaScriptを使ってキャンバスにアクセスし、図形や画像を描画するための専用のオブジェクト(描画コンテキスト)を取得する必要があります。

例えば、2Dグラフィックスを描く場合、JavaScriptでdocument.getElementByIdなどを使ってCanvas要素を取得し、getContext('2d')メソッドでCanvasの2D描画コンテキストCanvasRenderingContext2Dオブジェクト)を手に入れます。ここでは線や円を描いたり色を塗ったりといった命令を実行でき、(0,0)はキャンバスの左上を指します。

要するに、Canvasはブラウザ上に用意された「お絵かき用の画用紙」であり、JavaScriptのコードで好きなタイミングに好きな図形を描くことができます。ゲーム開発やアニメーション作成にもよく使われる技術ですね。今回の花火シミュレーターでも、このCanvas上に丸い花火の玉や爆発の光の粒を描画して、アニメーションさせていきます。

花火の基本:円を描いてみよう

それでは実際にCanvasを使った描画を始めましょう。まずは花火の「玉」に相当する小さな円を描いてみます。下記のHTMLコードを用意してください(canvas要素と簡単なスクリプトを含みます)。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>花火シミュレーター (テスト)</title>
</head>
<body>
  <canvas id="fireworksCanvas" width="600" height="400"></canvas>
  <script>
    const canvas = document.getElementById('fireworksCanvas');
    const ctx = canvas.getContext('2d');
    // 小さな円を描画する
    ctx.beginPath();
    ctx.arc(300, 350, 5, 0, Math.PI * 2);
    ctx.fill();  // 塗りつぶし (デフォルトの黒色)
  </script>
</body>
</html>

上記では、幅600×高さ400ピクセルの<canvas>要素を作成し、そのキャンバスに対してJavaScriptで黒い円を描画しています。ctx.beginPath()で新しいパスを開始し、ctx.arc(300, 350, 5, 0, 2 * Math.PI)で中心座標(300,350)、半径5pxの円を設定しています。fill()によって円を塗りつぶし描画します。この段階では円の色はデフォルト(黒)です。

花火に色をつける

花火と言えばカラフルな光です。先ほど描いた円に色を付けてみましょう。Canvasでは、fillStyleプロパティに色を指定してからfill()を呼ぶことで、図形を好きな色で塗りつぶせます。たとえば赤色にしてみます。

    // ... (canvas取得とコンテキスト取得は上と同じ)
    ctx.beginPath();
    ctx.arc(300, 350, 5, 0, 2 * Math.PI);
    ctx.fillStyle = 'red';  // 塗りつぶす色を指定
    ctx.fill();             // 赤い円を描画
  

このようにctx.fillStyleにCSSカラーを指定できます。実行すると円が鮮やかな赤色に変わるはずです。他にも'blue''green'など好みの色名を指定して楽しめます。

ランダムな場所に複数打ち上げる

1発だけでなく、複数の花火を同時に打ち上げてみましょう。JavaScriptのループと乱数を使い、複数の円をランダムな位置に描画します。なお、見やすいよう背景を黒に設定すると、花火の色が夜空に映えて綺麗です。

    // 背景を黒に(CSSでキャンバスを指定)
    // canvas { background-color: black; }

    // 複数の花火を描画
    const colors = ['red', 'yellow', 'blue', 'lime', 'magenta', 'cyan'];
    for (let i = 0; i < 5; i++) {
      const x = Math.random() * canvas.width;
      const y = canvas.height - 5;
      const color = colors[Math.floor(Math.random() * colors.length)];
      ctx.beginPath();
      ctx.arc(x, y, 5, 0, Math.PI * 2);
      ctx.fillStyle = color;
      ctx.fill();
    }
  

Math.random()は0以上1未満の乱数を返す関数です。canvas.widthと掛け合わせることで0〜600pxの範囲の座標を得ています。リロードするたびに配置が変わるため、何度でも楽しめます。

アニメーションさせよう(ループ処理)

静止した花火の玉を動かしてみましょう。花火を打ち上げるには、円を下から上へアニメーションさせる必要があります。Canvas上の図形を動かすためには、絵を描いては消し、位置を変えてまた描くという動作を一定間隔で繰り返します。JavaScriptではsetIntervalrequestAnimationFrameでループ処理を実現できますが、アニメーション用途にはrequestAnimationFrameを使うのが一般的です。

requestAnimationFrameは、ブラウザの描画タイミングに合わせて関数を呼び出してくれるため、コマ落ちが少なくスムーズなアニメーションが期待できます。一方setIntervalは指定時間ごとに関数を呼ぶだけなので、ディスプレイのリフレッシュレートとは同期しません。モダンなWebアニメーションではrequestAnimationFrameを使うのがおすすめです。

それでは、requestAnimationFrameを使って花火が上昇するアニメーションを作ってみましょう。clearRectで前フレームの描画を消去し、新しい座標で再描画を行います。

  <script>
    const rockets = [];
    const numRockets = 5;
    const colors = ['red', 'yellow', 'blue', 'lime', 'magenta', 'cyan'];

    // 初期の花火を用意
    for (let i = 0; i < numRockets; i++) {
      const x = Math.random() * canvas.width;
      const y = canvas.height - 5;
      const color = colors[Math.floor(Math.random() * colors.length)];
      const vy = 2 + Math.random() * 3;  // 上昇速度(2〜5)
      rockets.push({ x, y, color, vy });
    }

    function animate() {
      // キャンバスをクリア
      ctx.clearRect(0, 0, canvas.width, canvas.height);

      // 花火玉を更新・描画
      for (let rocket of rockets) {
        rocket.y -= rocket.vy;  // 上方向に移動
        ctx.beginPath();
        ctx.arc(rocket.x, rocket.y, 5, 0, Math.PI * 2);
        ctx.fillStyle = rocket.color;
        ctx.fill();
      }

      requestAnimationFrame(animate);
    }
    animate();
  </script>
  

これで、5つの花火玉が画面下から上へと滑らかに上昇していきます。requestAnimationFrameによってanimate()が毎フレーム呼び出されるため、画面の描画がスムーズです。

爆発・粒子の演出

花火のクライマックスである「爆発」を実装します。花火玉がある程度の高さに達したら、複数の小さな光の粒子を飛ばす演出を入れましょう。ロケット配列とは別に粒子配列を用意し、爆発の瞬間に粒子を生成し、元のロケットは削除します。

    const particles = [];

    function animate() {
      ctx.clearRect(0, 0, canvas.width, canvas.height);

      // 花火玉(ロケット)の更新・描画
      for (let i = rockets.length - 1; i >= 0; i--) {
        const rocket = rockets[i];
        rocket.y -= rocket.vy;

        // 一定の高さで爆発
        if (rocket.y < 50) {
          // 20個の粒子を生成
          for (let j = 0; j < 20; j++) { const angle = Math.random() * (Math.PI * 2); // 0〜360度 const speed = 2 + Math.random() * 3; // 粒子の速さ const vx = Math.cos(angle) * speed; const vy = Math.sin(angle) * speed; particles.push({ x: rocket.x, y: rocket.y, color: rocket.color, vx: vx, vy: vy, life: 60 }); } // 爆発後はロケットを配列から削除 rockets.splice(i, 1); } else { // 爆発していないロケットはそのまま描画 ctx.beginPath(); ctx.arc(rocket.x, rocket.y, 5, 0, Math.PI * 2); ctx.fillStyle = rocket.color; ctx.fill(); } } // 粒子の更新・描画 for (let k = particles.length - 1; k >= 0; k--) {
        const p = particles[k];
        p.x += p.vx;
        p.y += p.vy;
        p.life--;
        // 寿命が尽きたら削除
        if (p.life <= 0) {
          particles.splice(k, 1);
        } else {
          ctx.beginPath();
          ctx.arc(p.x, p.y, 2, 0, Math.PI * 2);
          ctx.fillStyle = p.color;
          ctx.fill();
        }
      }

      requestAnimationFrame(animate);
    }
  

rocket.y < 50になったら爆発を起こすようにしています(条件はお好みで調整可能)。爆発時にパーティクルを複数生成し、全方向へ飛ぶようMath.cosMath.sin速度を算出します。lifeが0になるまでは小さな円を描画し、それ以上になると削除する仕組みです。これで花火玉が頂点に達した瞬間にパッと色鮮やかな光の粒が広がり、儚く消えていくアニメーションが完成します。

ChatGPTからの補足解説とコーディングのコツ

  • パスの初期化: 複数の図形を連続で描画する際は、ctx.beginPath()を忘れずに。描画毎にパスをリセットしないと、前の図形と繋がって意図しない形になる場合があります。
  • アニメーションの軌跡: 今回はclearRectで過去フレームを消していますが、半透明の黒で塗りつぶすなど工夫すれば残像効果を出せます。花火の煙や軌跡をよりリアルに演出したいときに便利なテクニックです。
  • オブジェクト指向で整理: 花火玉や粒子をクラスで定義し、update()draw()メソッドを持たせると、大規模なコードでも可読性を保ちやすくなります。
  • パラメータ調整: 粒子の数や速度、寿命、爆発タイミングなどを色々変えるだけでも花火の印象が変わります。自分好みにカスタマイズしてみましょう。

まとめと応用

ここまで、JavaScriptとCanvasを使って花火シミュレーターを一から作成してきました。Canvasの基本操作から始まり、色付け、ランダム位置の設定、アニメーション、爆発の演出と、段階的に学ぶことで自然にCanvasアニメーションの仕組みを理解できたのではないでしょうか。

まだまだ発展の余地はたくさんあります。背景に星空や地上のシルエットを入れる、音を付けてより臨場感を出す、マウスクリックで好きなタイミングで花火を上げるなど、アイデアしだいでいくらでも遊べるのがCanvasとJavaScriptの面白さです。ぜひコードを改造して、自分だけのオリジナル花火を打ち上げてみてください。

&nbsp;

以上がChatGPTとCanvasアニメーションの使い方の紹介でした。
次回はChatGPTと挑戦するJavaScript宝探しゲーム について紹介します。