ブラウザゲームをつくって公開!アクセスもまあまああるのですが、なんか物足りない。ゲームにはハイスコアが表示されているものがあります。そのときに自分の名前も登録できるようになっていて、これをみると「なんとしても抜きたい」という気持ちになってしまいます。そこでゲームのハイスコアを表示させる機能について考えます。
やり方ですが、ゲームが終了したときにサーバーにリクエストをおくってそのときの点数が上位10以内にはいっていたら記憶させ、次回以降に表示させます。
ハイスコア表示のサンプルページ
今回は実験で以下のようなものをつくります。
アクセスすると乱数が生成されます。名前の欄にハンドルネームを入力してボタンを押すと、生成された乱数が上位10位以内であれば[トップ10を見る]のリンク先のページに表示されるというものです。
最初にHTMLファイルの内容を示します。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>ハイスコア サンプル</title> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <body> <label>ハンドルネーム</label> <input type="text" id="name" maxlength='16' /> <button type="button" onclick="SendData()">登録</button> <p><a href="./high-score.html" target="_blank" rel="noopener">トップ10を見る</a></p> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> <script type="text/javascript"> window.addEventListener('load', Load); let score = 0; function Load() {     // 乱数でスコアをつくる     score = Math.random() * 10000;     score = Math.round(score); } // 登録ボタンがおされたら上位10位以内であれば登録する function SendData() {     const textbox1 = document.getElementById("name");     let phpurl = "https://lets-csharp.com/sample/high-score/save-data.php";     // ハンドルネームの欄になにも入力されていなければ「名無しさん」とする     let name = textbox1.value;     if(name == "")         name = "名無しさん";     $.post(phpurl, {         name:name,         score:score,     }); } </script> </body> </html> | 
次にsave-data.phpの内容を示します。HTMLと同じディレクトリにhighscore.csvというファイルがあるのですが、このファイルを読み込んで配列の配列をつくります。そこに送られてきたデータを追加したあとscoreが大きい順にソートします。終わったらこれを文字列に変換してファイルとして保存します。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | <?php // 上位10位まで保存 $MaxCount = 10; mainFunc(); function GetFileName(){     $filename = "./" . "highscore.csv";     return $filename; } function sortByKey($key_name, $sort_order, $array) {     foreach ($array as $key => $value) {         $standard_key_array[$key] = $value[$key_name];     }     array_multisort($standard_key_array, $sort_order, $array);     return $array; } function mainFunc(){     // https://lets-csharp.com/* 以外からのリクエストは拒否する     $referer = $_SERVER['HTTP_REFERER'];     if(strpos($referer,'https://lets-csharp.com/')  === false)         return;     $stack = array();     // csvファイルが存在するならデータを配列に変換     if(file_exists(GetFileName())){         $allData = file_get_contents(GetFileName());         $lines = explode("\n", $allData);         foreach ( $lines as $line ) {             $words = explode(",", $line);             if($words[0] == "")                 continue;             $newArray = array(                 'name'=> $words[0],                 'score'=> $words[1],                 'now'=> $words[2],             );             $stack[] = $newArray;         }     }     // 配列に送られてきたデータを追加     $name = "";     $score = 0;     $name = $_POST["name"];     $score = $_POST["score"];     $now = date("Y-m-d H:i:s");     // 不適切なデータは処理しない     // nameがない、長すぎるなど     if(mb_strlen($name) > 16)         return;     if(mb_strlen($score) > 16)         return;     if($name == "")         return;     $newArray = array(         'name'=> $name,         'score'=> $score,         'now'=> $now,     );     $stack[] = $newArray;     // socreが大きい順に配列をソート     $sorted_array = sortByKey('score', SORT_DESC, $stack);     // 上位からMaxCountだけデータを取得してcsvファイルとして保存する     global $MaxCount;     $dataCount = count($sorted_array);     $str = "";     for($i = 0; $i < $dataCount; $i++){         if($i >= $MaxCount)             break;         $str .= join(",", $sorted_array[$i]);         $str .= "\n";     }     file_put_contents( GetFileName(), $str, LOCK_EX ); } | 
次に上位10位を表示させる方法を考えます。リンクをクリックして表示される別のページに上位10位を表示させます。
ここではXMLHttpRequestをつかってサーバー上のcsvファイルの内容を取得してtableタグを生成して上位10位を表示させています。
high-score.html
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>ハイスコア サンプル</title> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> td {     padding:3px 10px 3px 10px; } </style> </head> <body> <div id = "result" border="1"></div> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> <script type="text/javascript"> let urldata = "https://lets-csharp.com/sample/high-score/get-data.php"; let request = createXMLHttpRequest(); request.open("GET", urldata, true); request.send(""); request.onreadystatechange = function() {     if (request.readyState == 4 && request.status == 200) {         //受信完了時の処理         var result = document.getElementById("result");         var text = document.createTextNode(decodeURI(request.responseText));         let str = text.textContent;         const lines = str.split("\n");         $(result).append("<table border=\"1\" id=\"table\">\n</table>");         var table = document.getElementById("table");         let len = lines.length;         let num = 0;         for(let i=0; i<len; i++) {             if(lines[i] == "")                 break;             let trid = "tr-id" + i.toString();             $(table).append("<tr id = " + trid + "></tr>\n");             const words = lines[i].split(",");             let len2 = words.length;             var tr = document.getElementById(trid);             $(tr).append("<td>" + (i + 1).toString() + " 位</td>");             for(let j=0; j<len2; j++) {                 $(tr).append("<td>" + words[j] + "</td>");             }             $(table).append("</tr>");         }         $(result).append("");     } } function createXMLHttpRequest() {     if (window.XMLHttpRequest) {         return new XMLHttpRequest();     } else if (window.ActiveXObject) {         try {             return new ActiveXObject("Msxml2.XMLHTTP");         }         catch (e) {             try {                 return new ActiveXObject("Microsoft.XMLHTTP");             }             catch (e2) {                 return null;             }         }     } else {         return null;     } } </script> </body> </html> | 
get-data.php
| 1 2 3 4 5 6 7 8 | <?php function GetFileName(){     $filename = "./" . "highscore.csv";     return $filename; } $allData = file_get_contents(GetFileName()); echo $allData; | 
3Dカーレースゲームにハイスコア表示機能を追加する
TypeScript/JavaScriptでつくる3Dカーレースゲームをつくりましたが、これもハイスコアを保存できるようにしてみました。index.htmlを一部修正して、high-score.html、save-data.php、get-data.phpをゲームをアップロードしているディレクトリと同じディレクトリにアップロードしておきます。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | <!DOCTYPE html> <html> <head> <title>TypeScript/JavaScriptでもつくる3Dカーレースゲーム</title> <meta charset="UTF-8" /> <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> </head> <body> <canvas id="can"></canvas> <div id="info1" style="position: absolute; top: 0; left: 0; background: white"></div> <div id="info2" style="position: absolute; top: 0; left: 0; background: white"></div> <div id="info3" style="position: absolute; top: 0; left: 0; background: white"></div> <div id="info4" style="position: absolute; top: 0; left: 0; background: white"></div> <input type="checkbox" value="音を出す" id="SoundCheckbox">音を出す <!-- ここから3行追加 --> <label>ハンドルネーム</label> <input type="text" id="name" maxlength='16' /> <p><a href="./high-score.html" target="_blank" rel="noopener">トップ10を見る</a></p> <!-- ここまで追加 --> <script src="base-classes.js"></script> <script src="get-course-border.js"></script> <script src="is-cource-inside.js"></script> <script src="get-course-inside.js"></script> <script src="rival-car.js"></script> <script src="create-car-functions.js"></script> <script src="functions.js"></script> <script src="app.js"></script> </body> </html> | 
functions.jsのGameOver関数を以下のように修正します。mileageを小数のまま送るとうまくいかないので四捨五入して整数にしています。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | function GameOver() {     if(isGameOver)         return;     isGameOver = true;     car1.position.x = 0;     car1.position.z = 0;     StopBgm();     // これを追加     SaveData(); } function SaveData(){     const textbox1 = document.getElementById("name");     let phpurl = "save-data.php";     let url = location.href;     let name = textbox1.value;     if(name == "")         name = "名無しさん";     $.post(phpurl, {         url:url,         name:name,         score:Math.round(mileage),     }); } | 
上位10位を見るにはハイスコア TypeScript/JavaScriptでもつくる3Dカーレースゲームにアクセスしてください。
high-score.htmlとget-data.phpの内容はほとんど同じです。
