赤緑青の色ブロックをクリックする

赤緑青の色ブロックをクリックする

赤緑青の3つの正方形の色ブロックを「_stage」変数の数ずつ出現させます。いずれかの色ブロックがクリックされたら、徐々に透明になりながら拡大して消える、という動作をします。

赤緑青の色ブロックをクリック判定する

「js/color.js」ファイルを新規作成します。imgタグをjQueryで作成してランダムに配置し、それらがクリックされたら消します。まだXY移動量のデルタ(dx、dy、増分)はセットだけして使っていません。デルタは最後に使います。

・サンプルコード「js」→「color.js」ファイル
class Color {
  constructor(i) {
    this.dx = (Math.random()*2+2)*(Math.random()<0.5)?1:-1;
    this.dy = (Math.random()*2+2)*(Math.random()<0.5)?1:-1;
    var img = $('<img class="color" src="images/'+(i%3)+'.png" alt="'+(i%3)+'" />');
    img.css('left',Math.random()*($('body').width()-100));
    img.css('top',Math.random()*($('body').height()-100));
    $('#main').prepend(img);
  }
}

【サンプルコードの解説】
「Color」クラスで色ブロック1個ずつを表示します。
Colorクラスのコンストラクタで「dx」「dy」プロパティに各色ブロックのXY移動量をランダムに代入します。「.color」セレクタで0~2.png画像をalt属性に同じ番号で「img」タグをjQueryで作り「img」変数に代入します。imgのjQueryのスタイルシート(CSS)でx('left')とy('top')座標をランダムに配置します。Webアプリなのでimg変数をjQueryでプリロードします。

・サンプルコード「js」→「main.js」ファイル
$(function() {
  var _stage = 2;
  var _mainLoopID = null;
  var _colors = [];
  var _audio = $("audio").get();
  for ( i = 0; i < _audio.length; i++ ) _audio[i].load();

  function init() {
    var rgb = [0,0,0];
    $('#main').empty();
    _colors = [];
    for ( var i = 0 ; i < _stage*3; i++ ) {
      _colors.push(new Color(i));
    }
    while ( rgb[0] == rgb[1] ) {
      rgb = [~~(Math.random()*_stage),~~(Math.random()*_stage),~~(Math.random()*_stage)];
    }
    setBgColor(rgb);

    $('.color').on('click',function() {
      playAudio(3);
      rgb[$(this).attr('alt')]++;
      $(this).off().animate({'left':0,'top':0,'width':$('body').width(),'height':$('body').height(),'opacity':0},500,function() {
        isGameOver($(this));
      });
      setBgColor(rgb);
    });
    _mainLoopID = setInterval(mainLoop,50);
  }

  function setBgColor(rgb) {
(中略)
  }

  function mainLoop() {
  }

  function isGameOver(selector) {
    selector.remove();
  }

  function start() {
    clearInterval(_mainLoopID);
    $('body').css('background-color','rgb(255,255,255)');
    $('h1').off().on('click',function() {
      playAudio(0);
      $(this).empty();
      init();
    });
  }

  function playAudio(mp3) {
(中略)
  }

  start();
});

【サンプルコードの解説】
「_mainLoopID」変数には「setInterval」関数で50ミリ秒ごとに呼ばれるメインループのタイマーIDを代入します。
まず空で宣言した「_colors」配列に、forループで生成したColorクラスのインスタンスを追加します。
.colorセレクタが'click'されたら混色サウンドを再生し、alt属性から0~2の色の番号を取得してその番号のrgb配列の要素をインクリメントし、アニメーションしてから消し、ゲームクリア判定します。
「mainLoop」関数はまだ何もしませんが、定義だけします。
「isGameOver(selector)」はjQueryで引数の色ブロックセレクタを消します。
「start」関数で最初に_mainLoopIDのタイマーを消します。

index.htmlファイルに画像のプリロードをコーディングする

次のサンプルコードをコーディングし、index.htmlファイルをブラウザで開いてColorゲームをプレイします。js/color.jsをスクリプトとして読み込みます。

imgタグで画像ファイルを読み込みます。こうしてプリロードすることでjQueryで画像を扱う場合に画像の読み込み処理をしなくて済みます。「.images」セレクタは「pc.css」ファイルで非表示にしています。

・サンプルコード「index.html」ファイル
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <TITLE>カラーゲーム「Color」</TITLE>
    <link href="css/pc.css" rel="stylesheet" /> 
    <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
    <script src="./js/color.js"></script>
    <script src="./js/main.js"></script>
  </head>
  <body>
    <div id="main"></div>
    <h1><img src="images/Title.png" /></h1>

    <audio id="audioGameStart">
      <source src="sounds/GameStart.mp3" />
      <source src="sounds/GameStart.ogg" />
    </audio>
    <audio id="audioGameOver">
      <source src="sounds/GameOver.mp3" />
      <source src="sounds/GameOver.ogg" />
    </audio>
    <audio id="audioStageClear">
      <source src="sounds/StageClear.mp3" />
      <source src="sounds/StageClear.ogg" />
    </audio>
    <audio id="audioMix">
      <source src="sounds/Mix.mp3" />
      <source src="sounds/Mix.ogg" />
    </audio>

    <img class="images" src="images/Title.png" />
    <img class="images" src="images/GameOver.png" />
    <img class="images" src="images/StageClear.png" />
    <img class="images" src="images/0.png" />
    <img class="images" src="images/1.png" />
    <img class="images" src="images/2.png" />
  </body>
</html>

メインループとゲームオーバーを処理する

次のサンプルコードをコーディングし、index.htmlファイルをブラウザで開いてColorゲームをプレイします。メインループで色ブロックの移動処理をし、isGameOver関数でゲームオーバーかゲームクリアか続行かを判定して処理します。これでゲームは完成です(図3)。冒頭で紹介したURLのブラウザゲームとは若干動作が異なるのは、解説しやすいようにシンプルにしたからです。

図3:Colorゲームのゲームオーバー画面
・サンプルコード「js」→「color.js」ファイル
class Color {
  constructor(i) {
(中略)
  }

  update($this) {
    var x = $this.offset().left+this.dx;
    var y = $this.offset().top+this.dy;
    $this.css('left',x);
    $this.css('top',y);
    if ( x < -100 || y < -100 || x > $('body').width() || y > $('body').height() ) {
      return true;
    }
    return false;
  }
}

【サンプルコードの解説】
Colorクラスの「update」メソッドで(x,y)を(dx,dy)だけ色ブロックを移動します。jQueryでCSSのx(つまり'left')とy(つまり'top')をセットします。if文で色ブロックが画面外に出たか調べます。

・サンプルコード「js」→「main.js」ファイル
$(function() {
(中略)

  function init() {
(中略)
  }

  function setBgColor(rgb) {
(中略)
  }

  function mainLoop() {
    $('.color').each(function(index) {
      if ( _colors[index].update($(this)) ) {
        isGameOver($(this));
      }
    });
  }

  function isGameOver(selector) {
    selector.remove();
    if ( $('.color').length <= 0 ) {
      playAudio(1);
      $('h1').html('<img src="images/GameOver.png" />');
      $('h1').off().on('click',function() {
        $(this).html('<img src="images/Title.png" />');
        start();
      });
    }
  }

  function start() {
(中略)
  }

  function playAudio(mp3) {
(中略)
  }

  start();
});

【サンプルコードの解説】
mainLoop関数で_colors配列のupdateメソッドを呼び出します。jQueryの「$(this)」を変数にしたものがupdateメソッドの「$this」引数です。色ブロックが画面外に出たらゲームオーバー判定します。
isGameOver関数で色ブロックが0個以下(全ての色ブロックが消えた場合)ならゲームオーバー処理します。ゲームオーバーならゲームオーバー画像を表示し、その画像のjQueryでクリック判定をイベントリスナーに登録します。クリックされたらタイトル画面に戻ります。

【コラム】モチベーション

アメリカでIQの高い学校へ飛び級した子が、頑張るのに疲れて普通の学校で平凡な学生生活を送ったと聞いたことがあります。やっぱりモチベーションがなければ何もできないから、モチベーションを高く保つことが大事なんでしょう。筆者も本を書いたり記事を書いたりするモチベーションぐらいならあるのですが、なかなか企画が通らないこともあり残念です。以前は新しいことにチャレンジするモチベーションがあったから色々な技術を身につけられたけど、やはり歳をとると新しいことにチャレンジするモチベーションは低下します…。

おわりに

今回は、JavaScriptのラッパーライブラリである「jQuery」を使って、「HTML5」+「CSS」+「JavaScript」によるWebページでColorゲームを作りました。jQueryはCDN(Contents Delivery Network)で取得しています。

人気記事トップ10

人気記事ランキングをもっと見る

企画広告も役立つ情報バッチリ! Sponsored

ClickHouse Cloudが実現した広告運用SaaS「ATOM」のデータ基盤革新、パフォーマンスを向上しながら、運用負荷とコストを削減 11月11日 6:20 AIで開発が加速する時代、品質保証はどう変わる? Tricentisが示すAIエージェント活用の実像 11月9日 6:45 悪用までの猶予が「1分」に迫るフロンティアAI時代に開発と本番を貫く脆弱性管理が必要 10月29日 8:30 欧州CRA対応とSBOM運用。AI生成コードのOSS混入問題の対策とは ――スニペット単位で検出する「FossID」「Insignary Clarity」によるSBOM運用 9月16日 6:40 PostgreSQLからTiDBへ、稼働中SaaSで進める段階的DB移行の実践と再設計への展望 9月7日 6:30 機能安全開発におけるGoogleTestの活用を支援!「Parasoft C/C++test CT」で実現する効率化&AI連携 4月14日 6:30 【CNDW2025】Grafanaが明かす「オブザーバビリティの哲学」ー最小限の労力で実用的なインサイトを得るには 1月23日 6:30 【CNDW2025】プロダクト急増に備える基盤刷新 ーウェルスナビがECSからEKSへの移行で得た知見とは 1月15日 6:30 【CNDW2025】250環境を5人で運用、構築時間は30分に ーKINTOテクノロジーズが語るインフラ基盤組織の作り方 2025年12月18日 6:30 新たな自動化で熱視線! AIエージェントの「推論能力」を支える2つのコンポーネントとは? 2025年11月28日 6:30