前田稔のスマホ・ゲームの作り方

スマホでゲームをプレイするときは スマホ・ゲーム を参照して下さい。

スマホ・ゲームの基本

HTML と JavaScript を使ってスマホ・ゲームの作り方を説明します。
  1. スマホでホームページが閲覧出来るようなので、HTPP(HyperText Transfer Protocol)を使ったスマホ対応ゲームに挑戦します。
    HTPP を使ったゲームプログラムは、専用ソフトが必要なく HTML の知識と Text Editor があれば誰でも開発することが出来ます。
    掲載しているゲームは HTML と JavaScript や PHP で作成した簡単なゲームです。
    ゲームを作成するための基本的な説明が主体で、本格的なゲームの作成は読者に任せます。
    このコーナーのソースファイルの文字コードは utf-8 に統一しています。
    実行を確認した環境は ZenfoneGo の Android です。
  2. スマホ・ゲームのページは画面が小さいこともあり、十分な説明が出来ません。
    ゲームの作成方法や解説は次のページを参照して下さい。
    ゲームの説明  前田稔の JavaScript のページ
  3. スマホでゲームを作成するときの要点です。
    1. 画面が小さいので操作が容易なようにレイアウトします。
      文章は簡潔に最低限必要なものに留めて下さい。
    2. 画面が縮小されて操作が難しいので、スマホ専用の sumaho.css を組み込んで "viewport" を設定して下さい。
      これで文章が短いときには、スマホの文字が大きくなります。
      <!DOCTYPE html> 
      <html>
      <head>
      <meta http-equiv="content-type" content="text/html; charset=utf-8">
      <meta name="viewport" content="width=device-width,initial-scale=1.0" />
      <link rel="stylesheet" href="sumaho.css" type="text/css">
      </head>
      
    3. 【NOTE】
      必ずしも sumaho.css を組み込む必要はありません。
      最初に sumaho.css を組み込まずに試してみて下さい。
      <html>
      <head>
      <meta http-equiv="content-type" content="text/html; charset=utf-8">
      <meta name="viewport" content="width=device-width,initial-scale=1.0" />
      </head>
      
    4. スマホでは全角でタイプする場合も多く、全角⇒半角変換を行います。
      直接タイプ入力するよりも、選択(タップ)する方が操作性が増します。
      // 全角⇒半角変換
      function toChar_8(s)
      {   return s.replace(/[A-Za-z0-9]/g, function(s)
          {   return String.fromCharCode(s.charCodeAt(0) - 0xFEE0);
          });
      }
      
    5. パソコンの [戻るアイコン←] はスマホの [戻るボタン] に対応しているのですが、機能に多少の違いがあるようです。
    6. 一般の画像ファイルも使えますが、Animation GIF を使うとアニメーションしながら動きまわります。
      style で画像を描画(移動)するときは <!DOCTYPE html> を指定すると動かなくなるようです。
    7. 三山くずしゲームにサウンドを組み込んだのですが Android では通信料金が発生するのかサウンドの自動再生はされないようです。
      touchstart 等のユーザによる操作のイベントの中で再生処理をする必要があります。
      具体例はページ後部の Sound Test を参照して下さい。
      【NOTE】
      最近(2019/10)ではサウンドも普通に再生されるようになったようです。
      hoge.addEventListener('touchstart', function()
      { var audio = new Audio ('osrstart.mp3');
        audio.play();
      });      
      
    8. HTML に組み込む sumaho.css のソースコードです。
      詳細は CSSの基本 を参照して下さい。
      @charset "utf-8";
      
      /* 全般的なスタイル */
      *  {
          margin:0; padding:0;    /*マージン・パディングをリセット*/
          color:#333333;          /*文字色*/
         } 
      body {
          background-color:#faf8e0;   /*ページ全体の背景色*/
          margin:0px 10px 10px 10px;
          -webkit-text-size-adjust: 100%!important ;
         }
      h1 {
          margin: 10px 0 10px 0;  /* 上右下左 */
          font-size: 20p;         /* 文字サイズ */
          color: #333333;         /* 文字色を#333333 */
          padding: 5px 0px;       /* 上下5ピクセル、左右0px */
         }
      h2 {
          margin: 8px 0 8px 0;    /* 上右下左 */
          font-size: 18p;         /* 文字サイズ */
          color: #333333;         /* 文字色を#333333 */
          padding: 5px 0px;       /* 上下5ピクセル、左右0px */
         }
      h3 {
          margin: 6px 0 6px 0;    /* 上右下左 */
          font-size: 16p;         /* 文字サイズ */
          color: #333333;         /* 文字色を#333333 */
          padding: 5px 0px;       /* 上下5ピクセル、左右0px */
         }
      ul { margin:0px 10px 0px 16px; }
      ol { margin:0px 10px 0px 16px; }
      li { margin:20px 10px 20px 10px; }
      p  { margin:40px 0px 40px 0px; }
      hr { height:1px; border:solid 1px #cccccc;
           margin:10px 1px 10px 0px;
         }
      /* 範囲設定 */
      div.ff
      {   text-align:left;
          background-color:#ffffff;   /*内容全体の背景色*/
      }
      div.e0
      {   text-align:left;
          background-color:#e0e0e0;
      }
      span.red
      { color:#e02020; }
      span.s1
      { font-size:20pt; }
      span.s2
      { font-size:18pt; }
      span.s3
      { font-size:16pt; }
      img.s1
      {   max-width:100%;
          height:auto;
      }
      img.s2
      {   max-width:75%;
          height:auto;
      }
      img.s3
      {   max-width:50%;
          height:auto;
      }
      a:link {/*未訪問のリンク*/
          color:0000e0;
          font-style:normal;
          text-decoration:underline;
      }
      a:visited {/*訪問後のリンク*/
          color:#934C7B;
          text-decoration:underline;
      }
      a:hover {/*マウスをのせたとき*/
          color:#f000a0;
          font-style:normal;
          text-decoration:underline;
      }
      a:active {/*クリック中*/
          text-decoration:none;
      }
      

ゲームで使えるショート・プログラム

ゲームのソースコードは、パソコンで起動して右クリックから[ソースの表示]で確認することができます。
または「F12 からデバッグタブ」を選択すると、より詳しい情報が表示されます。
  1. 平方根の計算 の全ソースコードを掲載します。
    <html>
    <center>
    <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0" />
    
    <script type="text/javascript">
    function keisan(form)
    { if (form.num.value == "")
      { window.alert("データを入力して下さい♪");
        return;
      }
      var text = form.num.value;
      var str = toChar_8(text);
      if (isNaN(str) == true)
      { window.alert("数値を入力して下さい♪ [" + str + "]");
        return;
      }
      form.root.value = Math.sqrt(str);
    }
    // 全角⇒半角変換
    function toChar_8(s)
    {   return s.replace(/[A-Za-z0-9]/g, function(s)
        {   return String.fromCharCode(s.charCodeAt(0) - 0xFEE0);
        });
    }
    </script>
    
    </head>
    <body bgcolor="faf8e0">
    <h2>平方根の計算</h2>
    
    <form>
    元の数値
    <input type="text" name="num" value="" size=20><br><br>
    <input type="button" nama="ans" value="計算" onClick="keisan(this.form)"><br><br>
    平方根
    <input type="text" name="root" value="" size=30>
    </form>
    
    </body>
    </center>
    </html>
    
  2. スマホ・ゲーム説明画面
    ゲームの開始時に説明画面を表示します。
    1. document.write() でメッセージを表示します。
              document.write("・あなたと私がじゃんけんをします<br>");
                ・
                ・
                ・
      
    2. form に[開始]ボタンを設定して "guid_1.html"(自分自身)を呼び出します。
      このとき mode パラメータを渡します。(name="mode" value=0)
              document.write('<form action="guid_1.html" method="get">');
              document.write('<input type="hidden" name="mode" value=0>');
              document.write('<input type="submit" value="開始">');
              document.write('</form>');
      
    3. window.location.search.length はパラメータの長さで、3以下のときはパラメータが渡されなかったときです。
      mode に value=0 が渡された時、説明画面を表示します。
          if (window.location.search.length<3)
      
  3. パラメータ
    form にパラメータを設定して、渡す方法と受け取る方法です。
    1. フォームからパラメータを入力して "guid_2.html"(自分自身)を呼び出します。
      そのとき "para_1", "para_2", "para_3" を渡します。"para_3" は隠しパラメータです。
              document.write('<form action="guid_2.html" method="get">');
              document.write('<input type="text" name="para_1" value=12>');
              document.write('<input type="text" name="para_2" value=abc>');
              document.write('<input type="hidden" name="para_3" value=XYZ>');
              document.write('<input type="submit" value="CALL">');
              document.write('</form>');
      
    2. 渡されたパラメータ("para_1", "para_2", "para_3")を受け取ります。
      受け取ったパラメータを window.alert() で確認しています。
              param = new Array();
              var query = window.location.search.substring(1);
              var parameters = query.split('&');
              for(i=0; i<parameters.length; i++)
              {   var element = parameters[i].split('=');
                  var paramName = decodeURIComponent(element[0]);
                  var paramValue = decodeURIComponent(element[1]);
                  param[paramName] = paramValue;
              }
      
              p1 = param["para_1"];
              p2 = param["para_2"];
              p3 = param["para_3"];
              var str = "para_1:" + p1 + "  para_2:" + p2 + "  para_3:" + p3;
              window.alert(str);
      
    3. window.location.search.length はパラメータの長さで、3以下のときはパラメータが渡されなかったときです。
      適当な数字(文字)をタイプして[CALL]をクリックしてください。
      スマホでは全角でタイプする場合も多く、全角⇒半角変換を行った方が良いかも知れません。
      詳細は 全角 ⇔ 半角 を参照して下さい。
  4. 乱数でボタンを並べる
    ボタンの数を乱数で決めて form に並べます。
    実行する度にボタンの数が変わります。
    1. ボタンを選択して "guid_3.html"(自分自身)を呼び出します。
              num = Math.floor(Math.random()*5)+3;
              document.write('<form action="guid_3.html" method="get">');
              for(i=1; i<num; i++)
              {   document.write('<input type=radio name="val" value=',i,'>',i,' 個取る<br>');  }
              document.write('<input type="submit" value="CALL">');
              document.write('</form>');
      
    2. 選択されたボタンを window.alert() で確認します。
              param = new Array();
              var query = window.location.search.substring(1);
              var parameters = query.split('&');
              for(i=0; i<parameters.length; i++)
              {   var element = parameters[i].split('=');
                  var paramName = decodeURIComponent(element[0]);
                  var paramValue = decodeURIComponent(element[1]);
                  param[paramName] = paramValue;
              }
      
              p1 = param["val"];
              var str = "クリックされたボタン : " + p1;
              window.alert(str);
      
    3. window.location.search.length はパラメータの長さで、3以下のときはパラメータが渡されなかったときです。
  5. 画像を並べる
    石の画像を並べて、マウスのクリックで石を取り除きます。
    1. 石の画像を num 個並べる関数を head の中で定義します。
      最初に呼ばれたときは num には 10 が設定されています。
      石をクリックすると MouseClick() 関数がクリックされた番号で呼び出されます。
      クリックで呼び出されたときは、"石を取り除きました" を表示して残りの石を並べます。
        MouseClick(10);
          ・・・
      function MouseClick(num)
      {   if (num<10) document.write("<h2>石を取り除きました</h2>");
          for(i=0; i<num; i++)
              document.write("<img src='img/jewel.gif'","onClick=MouseClick(",i,")>");
      }
      
    2. 今回は連続して取り除くことは出来ません。
      連続して取り除くプログラムは head や MouseClick() 関数も含めた HTML 自体を再帰的に呼び出します。
  6. クリックのテスト
    クリック(タップ)された座標をオセロ盤の座標に変換して確認します。
    1. onmousedown でクリック(タップ)を検出して、座標を表示します。
        document.onmousedown =
          function(e)
          { if (!e)  e= window.event;
            xp= Math.floor((e.clientX-20)/38);
            yp= Math.floor((e.clientY-10)/38);
            window.alert("XP:" + xp + "  YP:" + yp);
          }
      
    2. body では "ban.gif" を描画するだけです。
      <img src="ban.gif">
      
  7. タップ座標に画像を移動
    マウスがクリック(タップ)された座標に画像を移動します。
    1. img タグの style で座標を設定して anime1.gif を描画します。
      style で画像を描画(移動)するときは <!DOCTYPE html> を指定すると効かなくなるようです。
      また style で座標を設定すると、HTML のテキストと重なって描画されます。
      この画像には "Enemy" の名前を付けています。
        <img src="anime1.gif" name="Enemy"
          style="position:absolute;left:0px;top:70px;">
      
    2. マウスのクリック(タップ)を検出して、"Enemy" の座標を移動します。
        document.onmousedown =
          function(e)
          { if (!e)  e= window.event;
            xp= e.clientX;
            yp= e.clientY;
            document.Enemy.style.left= xp;
            document.Enemy.style.top= yp;
          }
      
  8. タップで画像を切り替える
    マウスのクリック(タップ)で画像を切り替えます。
    1. アニメーション画像を切り替える手法は [歩く/走る/ジャンプ] や [イベント] が発生した場合などに使います。
      最初は "anime1.gif" を描画します。
      この画像には "anime" の名前を付けています。
      <img src="anime1.gif" name="anime"><br>
      
    2. window.onmousedown = mousedown; で、マウスがクリックされたとき mousedown() 関数を呼び出します。
      num は現在描画中の画像番号で、クリックする毎に 0 と 1 を切り替えます。
      document.anime.src= "anime" + (num+1) + ".gif"; で、"anime" の画像を切り替えます。
        num = 0;    //現在の画像
        window.onmousedown = mousedown;
        function mousedown()
        {   num = (num+1)%2;
            document.anime.src= "anime" + (num+1) + ".gif";
        }
      
  9. 画像の往復運動
    アニメーションしながら、画像が往復運動します。
    1. body の onLoad で setInterval を設定して 25 ミリ秒ごとに moveImage() を呼び出します。
      img タグの style で座標を設定して anime1.gif を描画します。
      この画像には "Enemy" の名前を付けています。
      <body onLoad="setInterval('moveImage()',25)">
      <h2>画像の往復運動</h2>
        <img src="anime1.gif" name="Enemy"
          style="position:absolute;left:0px;top:70px;">
      
    2. moveImage() 関数です。
      document.Enemy は name="Enemy" が設定されたリソースを指します。
      x は画像を描画するX座標で、Enemy.style.left= x; で座標を変えながら移動します。
      v は移動速度で0~120の間を往復運動します。
        x=0;
        v=2;
        function moveImage()
        {
          x+=v;
          if((x>120)||(x<0))  v= -v; 
          document.Enemy.style.left= x;
        }
      
  10. Start/Stop ボタン
    dog0.gif ~ dog4.gif の5枚の画像を切り替えてアニメーションをします。
    アニメーションの Start/Stop ボタンを設定します。
    1. starts() 関数から setInterval を設定して upDate() を呼び出します。
      123 は upDate() を呼びだす時間間隔(ミリ秒)です。
      id = 0;      //Interval のID
      ic = 0;      //ic= 表示する画像番号
      
      //Start ボタンがクリックされたとき
      function starts()
      {   clearInterval(id);
          id=window.setInterval("upDate()",123);
      }
      
    2. Stop ボタンで、Interval をクリアしてアニメーションを停止します。
      //Stop ボタンがクリックされたとき
      function stop()
      {   clearInterval(id); 
          Disp();
      }
      
    3. upDate() 関数で dog0.gif ~ dog4.gif の画像を切り替えます。
      Disp() 関数を呼び出して ic 番目の画像を描画します。
      //ic= 表示する画像番号
      function upDate()
      {   ic = ic+1;
          if (ic > 4) ic=0;
          Disp();
      }
      
    4. ic 番目の画像を描画します。
      このページで使う画像は1枚だけなので、images[0].src(添え字がゼロ番目の画像)は犬の画像です。
      //ic 番目の画像を描画
      function Disp()
      {   document.images[0].src="img/dog"+ic+".gif";  }
      </script>
      
    5. Start/Stop ボタンを設定して、クリックを検出します。
      今回は画像に名前を設定しないで、images[0]. で参照してみました。
      <table border="0">
          <tr><td><img src="img/dog0.gif"></td></tr>
      </table>
      <form name="Ctrl">
          <input type="button" value="START" onClick="starts()">
          <input type="button" value="STOP" onClick="stop()">
      </form>
      
  11. 弾丸を発射
    プログラムを起動すると弾丸が左端から右側に向けて発射されます。
    1. body から setInterval() で 25 ミリ秒ごとに move() 関数を呼び出します。
      img タグで "tama.gif" を style を設定して描画します。
      画像には "tama" の名前を付けています。
      <body onLoad="setInterval('move()',25)">
      <img src="tama.gif" name="tama" style="position:absolute;left:0px;top:50px;">
      
    2. move() 関数で弾丸を移動します。
      X座標を 4 アップして tama.style.left に設定します。
      X座標が 600 を超えると弾丸は止まります。
        x= 0;
        function move()
        { x+= 4;
          if (x<600)  document.tama.style.left= x;
        }
      
  12. 弾丸を広がりながら発射
    shat.js を組み込んで、3発の弾丸を広がりながら発射します。
    1. 弾丸を発射するソースコードを定義した shat.js を head 内に組み込みます。
      func() は3発の弾丸を移動する関数です。
      <head>
      <meta http-equiv="content-type" content="text/html; charset=utf-8">
      <meta name="viewport" content="width=device-width,initial-scale=1.0" />
      <link rel="stylesheet" href="sumaho.css" type="text/css">
      <script src="shot.js" type="text/javascript"></script>
      <script type="text/javascript">
        function func()
        { cls0.move();
          cls1.move();
          cls2.move();
        }
      </script>
      </head>
      
    2. shat.js のソースコードです。
      id は弾丸の id で、x, y が発射する座標で、xd, yd が移動量です。
      this.move で宣言されている関数は shot クラスの内部関数です。
      座標がウインドウの外に出たら描画を停止します。
      600, 400 は画面サイズに合わせて調整して下さい。
        function shot(id, x, y, xd, yd)
        { this.id = id;
          this.x = x;
          this.y = y;
          this.xd = xd;
          this.yd = yd;
          this.flg = true;
      
          this.move = function()
          { if (this.flg)
            { this.x += this.xd;
              this.y += this.yd;
              if (this.x<0 || this.x>600 || this.y<0 || this.y>400)   this.flg = false;
            }
            if (this.flg)
            { document.getElementById(this.id).style.visibility= "visible";
              document.getElementById(this.id).style.left= this.x;
              document.getElementById(this.id).style.top= this.y;
            }
            else  document.getElementById(this.id).style.visibility= "hidden";
          }  
        } 
      
    3. body から setInterval() で 25 ミリ秒ごとに func() 関数を呼び出します。
      cls0, cls1, cls2 の弾丸を生成します。
      <body onLoad="setInterval('func()',25)">
      <script type="text/javascript">
        var cls0 = new shot("tama0", 600, 70, -4, 0);
        var cls1 = new shot("tama1", 600, 70, -4, 1);
        var cls2 = new shot("tama2", 600, 70, -4, 2);
      </script>
      
    4. 3発の弾丸の画像を名前(id)を設定して描画します。
      <img src="tama.gif" id="tama0" style="position:absolute;left:600px;top:70px;">
      <img src="tama.gif" id="tama1" style="position:absolute;left:600px;top:70px;">
      <img src="tama.gif" id="tama2" style="position:absolute;left:600px;top:70px;">
      
  13. 円状に発射
    プログラムを起動すると10発の弾丸が同心円状に発射されます。
    1. shat.js は便利なクラスで、発射座標と方向を指定すれば簡単に弾丸を発射することが出来ます。
      今回は10発の弾丸を同心円状に発射します。
      弾丸を広がりながら発射 を参照して shat.js を head 内に組み込んで下さい。
      func() 関数で弾丸を移動します。
      <script src="shot.js" type="text/javascript"></script>
      <script type="text/javascript">
        function func()
        { for(i=0; i<10; i++) cls[i].move();
        }
      </script>
      </head>
      
    2. body から setInterval() で 25 ミリ秒ごとに func() 関数を呼び出します。
      <body onLoad="setInterval('func()',25)">
      
    3. 画面の中央から、10発の弾丸の移動方向を設定して登録します。
        var cls = new Array();
        for(i=0; i<10; i++)
        { var w = "tama" + i;
          var x = 3 * Math.cos((i*36)/180*Math.PI);
          var y = 3 * Math.sin((i*36)/180*Math.PI);
          cls[i] = new shot(w, 300, 200, x, y);
        }
      
    4. 最初に10発の弾丸に名前(id)を設定して描画します。
      画像の名前(id)は "tama0" ~ "tama9" になります。
        for(i=0; i<10; i++)
        { var w = "tama" + i;
          document.write('<img src="tama.gif" id="', w, '" style="position:absolute;left:300px;top:200px;">');
        }
      
  14. Saund Test
    サウンド(mp3)のテストです。
    1. サウンドを演奏する saisei() 関数です。
      <script type="text/javascript">
      function saisei(file)
      { var audio = new Audio(file);
        audio.play();
      }; 
      </script>
      
    2. ボタンのクリックで saisei() 関数を呼び出します。
      <input type="button" value="開始" onClick="saisei('start.mp3')"><br><br>
      <input type="button" value="勝ち" onClick="saisei('win.mp3')"><br><br>
      <input type="button" value="負け" onClick="saisei('lose.mp3')"><br><br>
      

ゲームのプレイは スマホ・ゲーム を参照して下さい。
スマホ・ゲームの作り方
ゲームの説明
前田稔(Maeda Minoru)の超初心者のプログラム入門