ボールゲーム

  1. ボールゲーム


    1. ゲームのルール

       壁で跳ねながら落ちてくるボールをマウスを使ってパッドを移動し跳ね返します。パッドで跳ね返すと得点が増えます。3回成功するごとに、ボールの数が増えます。
       5回失敗までの得点を競います。

    2. 複数のボール

      一度に複数のボールが落ちてきます。ボールの位置や速度を配列に保存します。

  2. 手法

    1. イベント

      タイマーイベントでボールを移動し、マウスイベントでラケットを移動します。

    2. 経過表示

       得点やミスした数、ゲームオーバーなどのメッセージを表示します。以下は得点表示用の div タグです。
      <div id='tn_score' style='position:absolute;left:27;font-size:11px;color:rgb(255,255,255);'>SC:0</div>
      表示内容を変更するには、ID を指定し、innerHTML 属性(文字列)を変更します。tn_sc は得点記録用の変数です。
      document.getElementById("tn_score").innerHTML="SC:"+tn_sc;

    3. パッドの移動

       マウスイベントを処理する関数は、document の属性として設定します。
      document.onmousemove=tn_mouseMove;
      マウスのx位置は IE5以後のブラウザ(bw==1)では、e.pageX で取得できます。tn_rx はパッドの中心座標で8はパッドの半幅です。tn_gx はゲーム画面の左の枠の座標です(ここでは0)。マウス座標がゲーム画面よりはみ出た場合、画面ないに戻します(scrnWはゲーム画面の幅)。
      function tn_mouseMove(e)// ラケットの移動
      {
         if(tn_gameover==true){return;}
         if(bw==1){tn_rx=e.pageX-tn_gx-8;}
         else{tn_rx=document.body.scrollLeft+event.clientX-tn_gx-8;}
         if(tn_rx>(scrnW-16)){tn_rx=(scrnW-16);}
         if(tn_rx<1){tn_rx=1;}
      }

    4. 跳ね返り、ゲームオーバー

       ボールが左右および上の枠に達した場合、速度の符号を反転して移動方向を逆にします。また、パッドの上端の位置で、左右方向がパッドの範囲の場合も反転させます。
       ボールがゲームの枠の高さ(scrnH)に達した場合打ち損ねたことになり、tn_misssyori(n) で ミスの処理をします。ミスした数が tn_miss_max になると、ゲームオーバーになります。

    5. ソース

      以下にプログラム例を示します。元のプログラムは http://plusone.jpn.org/javascript/ ですが、必須でない処理を削って簡単にしました。
      //ボールをマウスで打ち返すゲーム
      //http://plusone.jpn.org/javascript/より
      
      tn_gx=0;// ゲーム画面の表示位置
      tn_gy=20;
      tn_sc=0;// スコア
      tn_miss=0;// ミス
      tn_miss_max=5;
      tn_rx=50;// ラケットの座標
      tn_ry=132;
      tn_MaxBalls=5;// 最大のボール数
      scrnW=123;
      scrnH=158;
      
      tn_balls=new Array(tn_MaxBalls);// ボールを表示制御フラグ
      tn_bx=new Array(tn_MaxBalls);// ボールの座標
      tn_by=new Array(tn_MaxBalls);
      tn_bv=new Array(tn_MaxBalls);//ボールの速度
      tn_bw=new Array(tn_MaxBalls);
      
      tn_gameover=true;//ゲームオーバーのフラグ
      tn_interval=10;// 表示間隔
      
      // ブラウザチェック
        bw=0;
        if(document.getElementById){bw=1;}// ネスケ6〜 IE5〜なら真
        if((document.all)&&(bw==1)){bw=2;}// IE4〜なら真
      
      //背景画像設定 tn_start() 
        document.write("<img src='black.gif' width=123 height=158 style='position:absolute;left:0px;' name='tn_screen' onClick='tn_start()'>");
      //ボール画像
      for(var i=0;i<tn_MaxBalls;i++){
         document.write("<img src='white.gif' width=2 height=2 style='position:absolute;left:-100px;' name='tn_ball"+i+"'>");
      }
      //ラケット画像
        document.write("<img src='white.gif' width=16 height=2 style='position:absolute;left:-100px;' name='tn_bar'>");
      //ゲーム得点など
        document.write("<div id='tn_over' style='position:absolute;left:36;text-align: center;font-size:11px;color:rgb(255,255,255);'>GAME OVER</div>");
        document.write("<div id='tn_score' style='position:absolute;left:27;font-size:11px;color:rgb(255,255,255);'>SC:0</div>");
        document.write("<div id='tn_miss' style='position:absolute;left:70;font-size:11px;color:rgb(255,255,255);'>Miss:5</div>");
        tn_init();//ゲーム初期設定
      
      //------------------
      
      function tn_init()
      {
         if(bw==0)
         {
            alert("ブラウザが対応していません\n");
            return;
         }
      
         tn_demoinit();// 待ち受け用に各変数の初期設定
         tn_gxset();//画面設定
         document.onmousemove=tn_mouseMove;// マウスイベントの設定
      
         tn_main();// ゲーム実行
      }
      
      function tn_demoinit()// 各変数の初期設定
      {
         tn_miss=0;// ミスのリセット
         tn_interval=11;// ゲームの早さ初期設定
         tn_sc=0;// スコアリセット
         tn_rx=50;// ラケットの座標
         
         for(var i=0;i<tn_MaxBalls;i++)// ボールの各変数の初期設定
         {
            tn_balls[i]=true;// ボールの状態を設定
            document.images["tn_ball"+i].style.left=-tn_gx-100;// ボールを画面外に表示(消す)
            tn_bx[i]=Math.floor(Math.random()*100)+10;// ボールの座標の初期設定
            tn_by[i]=Math.floor(Math.random()*64);
            tn_bv[i]=1;// ボールのx速度の初期設定
           if(Math.random()<0.5){tn_bv[i]=-tn_bv[i]}
            tn_bw[i]=1;//y方向速度
         }
      }
      
      function tn_gxset()
      {
         document.tn_screen.style.top=tn_gy;
         document.tn_bar.style.left=tn_gx+tn_rx;// ラケット表示位置
         document.tn_bar.style.top=tn_gy+tn_ry;
         //表示y位置を設定
         document.getElementById("tn_over").style.top=tn_gy+42;
         document.getElementById("tn_score").style.top=tn_gy+144;
         document.getElementById("tn_miss").style.top=tn_gy+144;
      }
      
      function tn_start()// ゲームスタートの設定
      {
         if(tn_gameover==false){return;}//
         tn_demoinit();// デモ用の各変数の初期設定
         tn_interval=18;
         for(var i=1;i<tn_MaxBalls;i++) {
            tn_balls[i]=false;
         }
         tn_by[0]=0;
         document.getElementById("tn_over").style.visibility="hidden";// ゲームオーバー表示を消す
         document.getElementById("tn_miss").innerHTML="Miss:"+tn_miss;// ミス表示リセット
         document.getElementById("tn_score").innerHTML="SC:"+tn_sc;// スコア表示リセット
         tn_gameover=false;//ゲームオーバーのフラグを戻す
      }
      
      //メインルーチン
      function tn_main()
      {
         var tn_touch;// ボールが壁に接触しているかどうかのフラグ
         for(var i=0;i<tn_MaxBalls;i++)// ボールの移動
         {
            if(tn_balls[i]==false){continue;}// ボールが無い状態なら移動処理しない
            tn_bx[i]+=tn_bv[i];// ボールの座標に速度を加算
            tn_by[i]+=tn_bw[i];
            
            if((tn_bx[i]<1)||(tn_bx[i]>120)){// ボールと壁の接触判定 
               tn_bv[i]=-tn_bv[i];// X軸の速度を反転させる
            }
            
            if(tn_by[i]<1){tn_bw[i]=-tn_bw[i];}// ボールが一番上にきたらY軸の加速度を反転させる
            if(tn_by[i]>scrnH-3){tn_misssyori(i);}// ボールが下にすり抜ければミスの処理
            
            if((tn_by[i]==tn_ry-2)&&(Math.abs(tn_bx[i]-tn_rx-8)<10))// ボールとラケットの接触判定
            {
               tn_bw[i]=-tn_bw[i];// Y軸方向の速度を反転
               if(tn_gameover==false)// ゲームオーバー時でなければスコアを加算
               {
                  tn_sc++;// スコアを加算
                  document.getElementById("tn_score").innerHTML="SC:"+tn_sc;// 得点表示
                  
                  if(tn_sc%3==0){tn_addBall();}// 3点ごとにボールを増やす
               }
            }
            document.images["tn_ball"+i].style.left=tn_gx+tn_bx[i];// ボールの位置変更
            document.images["tn_ball"+i].style.top=tn_gy+tn_by[i];
         }
         document.tn_bar.style.left=tn_gx+tn_rx;//ラケットの位置
         
         setTimeout("tn_main()",tn_interval);// タイマー処理
      }
      
      function tn_mouseMove(e)// ラケットの移動
      {
         if(tn_gameover==true){return;}
         if(bw==1){tn_rx=e.pageX-tn_gx-8;}
         else{tn_rx=document.body.scrollLeft+event.clientX-tn_gx-8;}
         
         if(tn_rx>(scrnW-16)){tn_rx=(scrnW-16);}
         if(tn_rx<1){tn_rx=1;}
      }
      
      function tn_addBall()// ボール追加処理
      {
         for(var j=0;j<tn_MaxBalls;j++){
            if(tn_balls[j]==false){// 非表示状態のボールが見つかれば再設定
               tn_bx[j]=Math.floor(Math.random()*100)+5;
               tn_by[j]=Math.floor(Math.random()*64)+2;
               tn_bv[j]=1;
               tn_bw[j]=1;
               if(Math.random()<0.5){tn_bv[j]=-tn_bv[j];}
               tn_balls[j]=true;
               break;// 繰り返し処理を抜ける
            }
         }
      }
      
      function tn_misssyori(n)// ミスした時の処理
      {
         tn_bx[n]=-tn_gx-100;// 座標を画面の外に設定して消す
         document.images["tn_ball"+n].style.left=-100;
         if(tn_gameover==false){// デモ中はミスを加算しない
            tn_miss++;// ミスをカウントする
            document.getElementById("tn_miss").innerHTML="Miss:"+tn_miss;// ミス数の表示
         }
         tn_balls[n]=false;// ミスしたボールを非表示にする
         if(tn_miss==tn_miss_max){// ミスがある数を超えたらゲームオーバーの処理
            tn_over()
         }else{
            var m=0;
            for(var i=0;i<tn_MaxBalls;i++){// 現在非表示状態のボールの数をカウントする
               if(tn_balls[i]==false){m++;}
            }
            if((m==tn_MaxBalls)||(tn_gameover==true)){tn_addBall();}// ボールが0個の場合はボールを増やす
         }
      }
      
      function tn_over()// ゲームオーバーの処理
      {
         tn_gameover=true;// ゲームオーバーを示すフラグをたてる
         document.getElementById("tn_over").style.visibility="visible";// 「ゲームオーバー」の表示
      }

    6. デモ

      ここから実行できます。