サーバー構築不要!スマートフォンアプリ向けの新クラウド

トップ >ドキュメント >チュートリアル(JavaScript):Monacaアプリのゲームにランキング機能をつける

チュートリアル(JavaScript)

Monacaアプリのゲームにランキング機能をつける

概要

このチュートリアルでは、Monacaでサンプルとして選択できる「ブロック崩しゲーム」に、オンラインランキング機能を実装します。従来はサーバー構築・開発などが必要だったオンライン機能ですが、ニフクラ mobile backendを利用することで、サーバー側の開発をすることなく、簡単に実装することができます。

ランキング画面

このチュートリアルで作るもの

このチュートリアルでは、以下の機能を順に実装します。

  1. ゲームのスコアをクラウド(mBaaS)に保存する機能
    ゲームが終了したタイミングで、スコアがmBaaSに送信されるようにします。
  2. スコア保存時に名前を入力する(ログイン)機能
    会員管理・認証機能を使用し、会員登録とプレイヤー名の保存を行います。まず会員登録機能を実装し、その後プレイヤー名を入力、データを更新する機能を実装します。
  3. 保存したスコアとユーザーの紐付け
    各スコアを出したのがどのプレイヤーなのか、紐付けを行います。
  4. スコアランキングを表示する機能
    保存したスコアとプレイヤー名を使い、スコアの上位ランキングを作成します。

完成したプロジェクトは、Githubにて公開していますので、参考にしてください。

mBaaSの機能としては、データストア(データベース)機能、会員管理・認証機能を使用します。

ブロック崩しサンプルについて

本チュートリアルは、ゲーム部分のみが実装されたサンプルに、オンライン機能部分を実装していくことで進めます。そのゲーム部分として、Monacaの「ブロック崩し」サンプルを使用します。
このサンプルは2Dで画面描画を行うためのライブラリ「Pixi.js」を用いて作られており、JavaScriptで本格的なゲームを作ることが可能となっています。

ゲーム画面
サンプルについての詳しい説明は、Monacaドキュメント ブロック崩しゲームをご覧ください。

事前準備

この章では、チュートリアルを進めるための事前準備を行います。

Monacaで新規プロジェクトを作成する

Monacaの無料会員登録を行い、新規プロジェクトを作成します。

テンプレート選択
テンプレートの中から、「ブロック崩し」を選択します。

今後処理を記述するJavaScriptファイルを作成する

ゲームに関する処理は、すべてmain.jsに書かれており、Pixiでの描画設定等を行っています。

今回の処理をmain.jsに追記すると見通しが悪くなるため、別のJavaScriptファイルを用意して、今後はそちらに主な処理を書き込みます。

JavaScriptファイル(ncmbController.js)を追加した後の、
wwwフォルダ内の主なファイル構成は以下の通りです。

  • index.html
  • js/
    • main.js
    • ncmbController.js
  • css/
    • style.css
  • /assets/images/tutorial/monaca_breakout/
  • res/

JavaScriptファイルの追加手順は以下の通りです。

jsフォルダを右クリックし、「新規ファイル」を選択し、ncmbController.jsというファイルを作成します。

新規ファイル作成

ファイル形式にはJavaScriptを選択してください。

新規ファイル作成
処理を定義するオブジェクトを作成します。
今作成したncmbController.jsに、以下のように定義してください。

// ncmbController.js

var ncmbController = {
}

index.htmlで、このJavaScriptファイルを読み込むように設定しておいてください。

<script src="js/ncmbController.js"></script>

ニフクラ mobile backendのアカウントを作成する

ニフクラ mobile backendの登録を行います。
会員登録ページにて無料登録を行ってください。

登録を行うと、アプリ名を入力する画面が表示されます(既に登録済みの方は、ヘッダーメニュー「+新しいアプリ」を選択すると表示されます)。
アプリ名は自分のわかりやすい名前をつけてください。

新規アプリ作成
アプリを作成すると、アプリケーションキーとクライアントキーが表示されます。
この後使いますので控えておきましょう。このキーはアプリ設定画面でも確認できます。

各種キー

ニフクラ mobile backendの導入と初期化

作成するアプリで「ニフクラ mobile backend」の各機能を使うための準備を行います。

JavaScript SDKのインストール

Monaca上で開発を行い、mobile backendと連携する場合、SDKは「外部サービス連携機能」を使うことで自動で導入することができます。

「設定」メニューから「外部サービス連携」を選択します。

外部サービス連携
ニフクラ mobile backendの「詳細」を選択し、「セットアップ」を行います。

外部サービス連携
外部サービス連携
必要なファイルが追加されます。

最後に、ローダー設定を行います。
「JS/CSSコンポーネントの追加と削除」から、ncmbの「設定」を選択、
components/ncmb/ncmb.min.js にチェックを入れてOKを選択してください。

外部サービス連携
外部サービス連携
この設定により、アプリ起動時にSDKが自動で読み込まれるようになります。

ncmbControllerの初期化(各種キーの読み込み)

アプリが起動したときに呼び出されるinit(main.js)にncmbControllerの初期化処理を追加します。

// main.js -> init()

ncmbController.init(BB.screenSize);

実際の初期化処理

// ncmbController.js

var ncmbController = {
    APPLICATION_KEY: "YOUR_APPLICATION_KEY",
    CLIENT_KEY: "YOUR_CLIENT_KEY",

    ncmb: null,
    currentUser: null,  // ログインしたユーザーのオブジェクトを格納
    screenSize: null,    // 画面サイズを格納

    // 初期化
    init: function(screenSize) {
        var self = this;
        self.ncmb = new NCMB(self.APPLICATION_KEY, self.CLIENT_KEY);    // mobile backendの初期化
        self.screenSize = screenSize;
    }
}

YOUR_APPLICATION_KEY、YOUR_CLIENT_KEY に、それぞれ先ほど控えたアプリケーションキーとクライアントキーを記載します。

スコアを保存する

この章では、スコアの保存処理を実装していきます。
この章を終えると、クラウド上にプレイした結果が保存でき、管理者がmobile backendのダッシュボードから確認できるようになります。

スコア確認
スコアの保存には、データストア機能を使います。
データベースのようにmobile backend上に各種データを保存することができる機能です。

スコア保存(送信)処理を実装する

スコアを送信する、sendScore関数を作成していきましょう。
クラス生成→インスタンス生成→送信処理、という順に処理を行います。

// ncmbController.js -> ncmbController

// スコア送信
sendScore: function(score) {
    var self = this;

    // [1]Score(クラス)を生成
    var Score = self.ncmb.DataStore("ScoreClass");

    // [2]インスタンス生成、スコア数値をフィールド名"score"にセット
    var scoreData = new Score({score: score});

    // [3]送信処理
    scoreData.save()
        .then(function (saved) {
            alert("スコア送信完了!");
        })
       .catch(function(err){
            console.log(err);
        });
},

ゲームクリア時とゲームオーバー時に、sendScoreを呼び出すように変更します。

// main.js -> BB

// Game Over
endGame: function() {
    BB.gameState = GAMESTATE_STOP;
    vibrate();
    ncmbController.sendScore(BB.score);
},

// Game Clear
clearGame: function() {
    // デフォルトで表示される「ゲームクリア」ダイアログは出さない
    // if(typeof navigator.notification !== 'undefined') navigator.notification.alert("Cleared!", function(){}, "Congraturations");
    // else alert("Cleared!");

    BB.gameState = GAMESTATE_STOP;
    ncmbController.sendScore(BB.score);
}

スコア送信
玉が落ちるかブロックがなくなると、スコアが送信されます。
送信されると、以下のようにダッシュボードから確認ができます。

スコア確認

順位を表示する

スコアの送信が完了した際、順位を表示するようにしていきます。

データストア内のデータを検索したり取得する場合は、クエリを使用します。
検索条件をメソッドチェーンで記述し、fetchやfetchAllなどのメソッドを実行して結果を取得します。

今回、スコアの順位は「今回のスコアより大きい値の記録の数(行数)+1」で求めます。
データの件数は検索条件にcountメソッドを追加することで取得できます。

では実際に順位を取得し、アラートで表示してみましょう。
「スコア送信完了!」のアラートを削除し、以下のように記述します。

// ncmbController.js -> ncmbController -> sendScore()

// 順位を求める
// ”score” フィールドの値が score より大きいものを取得
Score.greaterThan("score", score)
    .count()    // 件数を結果に含める
    .fetchAll()
    .then(function(scores){
        // countの結果は、取得データscoresのcountプロパティに含まれる

        // 0件のとき正しく動作するように条件分岐
        var rank = (scores.count !== undefined) ? parseInt(scores.count) + 1 : 1;

        // ダイアログの表示
        if(typeof navigator.notification !== 'undefined'){
            navigator.notification.alert(
                "今回の順位は #" + rank + " でした!",
                function(){},
                "スコア送信完了!"
                );
        } else {
            alert("スコア送信完了!\n今回の順位は #" + rank + " でした!");
        }
    })

順位確認
コードを追加して動作を確認すると、スコア送信後に順位を知らせるダイアログが表示されるようになります。
これで、各プレイのスコアの順位を表示することができました。

プレイヤーを登録する

順位の表示はできましたが、ランキングの1位を誰が出したのかなど、ほかのプレイヤーの情報についてはまだわかりません。
そこで、プレイヤーが名前を登録できるようにしてみましょう。

ゲームをプレイした後でプレイヤー名を入力してもらうため、アプリ起動時にユーザー登録(またはログイン)を裏で行い、ゲーム終了後に表示名のみを更新するという流れで実装します。

この章では前段階として、プレイヤーをmobile backendに登録する処理を実装します。

会員登録機能

この章では、会員管理・認証機能を使用します。
ただし、今回はユーザー(プレイヤー)の負担を少なくするため、ユーザーには表示する名前のみ入力してもらうようにし、IDとパスワードについてはランダムな文字列を設定して登録するようにします。

ユーザー登録処理をつくる

ユーザーを登録する処理を実装します。
今回、IDとパスワードは同じランダム文字列を使用しますが、その文字列をlocalStorageに保存することで、プレイヤーがランダム文字列を意識せずにログインできるようにします。

// ncmbController.js -> ncmbController

// ユーザー登録
createUser: function() {
    var self = this;

    //適当なUUIDを作成
    var uuid = self.uuid();

    //ユーザークラスのインスタンスを作成
    //userNameとパスワードにはuuidを設定
    var user = new self.ncmb.User({userName:uuid, password:uuid});

    //会員登録を行うメソッドを実行
    user.signUpByAccount()
        .then(function(user){
            // 登録完了後ログイン
            localStorage.setItem("userName", uuid);
            alert("ユーザー登録に成功しました!");
        })
        .catch(function(err){
            // userName が被った場合はエラーが返る
            alert("ユーザー登録に失敗しました");
        });
},

ランダムな文字列を生成する関数uuidについては、こちらなどを参考に実装してみてください。

動作を確認する

init()メソッドの最後(ncmbControllerの初期化後)にcreateUserを呼び出す処理を追加し、一度動作を確認してみましょう。

// main.js -> init()

ncmbController.createUser();

アプリを起動すると、自動でユーザーが作成されます。
「ユーザー登録が完了しました!」というダイアログが表示され、mobile backendのダッシュボードでも確認することができます。

ユーザー作成確認

プレイヤーのログイン機能を実装する

前の章でプレイヤーの登録機能を作りましたが、このままではゲームを起動するたびにユーザーが作られてしまいます。
既にユーザーが作成されている場合・新しくユーザーを作成した直後の場合に、ログイン処理を行うように変更しましょう。

ユーザーIDがlocalStorageに保存されている場合や、以前ログインした際のデータが残っている場合はログインを、そうでない場合は会員登録を行うメソッドloginWithUUIDを作成します。

また、ログインした後のユーザー情報は、ncmbControllerのcurrentUserプロパティに格納します。

// ncmbController.js -> ncmbController

// UUIDが存在すればログイン、しなければ新規作成
loginWithUUID: function() {
    var self = this;
    var userName = localStorage.getItem("userName");

    if(!userName){
        // ユーザーを作成したことがない
        self.createUser();
    } else if(!self.currentUser) {
        // ログアウト状態:userNameとパスワードでログイン
        // 今回はパスワード(第2引数)もuserNameを使用
        self.ncmb.User.login(userName, userName)
            .then(function(user){
                // ログイン後:ユーザーデータの更新
                self.currentUser = user;
                self.refreshCurrentUser();
            })
            .catch(function(err){
                // 失敗した場合:ユーザー作成
                console.log(err);
                self.createUser();
            });
    } else {
        // ログアウトしていない(前のログインデータが残っている)
        self.currentUser = self.ncmb.User.getCurrentUser();

        // userオブジェクトを使用してログイン
        self.ncmb.User.login(self.currentUser)
            .then(function(user){
                // ログイン後:ユーザーデータの更新
                self.currentUser = user;
                self.refreshCurrentUser();
            })
            .catch(function(err){
                // セッション切れの場合はログアウトして再ログイン
                console.log(err);

                self.ncmb.User.logout();  // ログアウト
                self.currentUser = null;
                self.loginWithUUID();       // 再ログイン
            });
    }
},

以前のユーザーデータが残ったまま一定時間が経過すると、セッション切れが発生します。セッション切れが発生した場合は、一度ログアウト処理を実行し、再度ログインする必要がありますので注意してください。

currentUserプロパティの更新

ncmbControllerのcurrentUserプロパティには常に最新のuserオブジェクトを格納しておくようにするため、
ログインやプレイヤー名を変更するタイミングで必ず情報を更新するようにします。
情報を更新するためのrefreshCurrentUserメソッドを実装します。

// ncmbController.js -> ncmbController

// currentUserプロパティを更新
refreshCurrentUser: function() {
    var self = this;
    if(!self.currentUser) return;

    // オブジェクトIDを用いてユーザーを検索(fetchById)
    self.ncmb.User.fetchById(self.currentUser.get("objectId"))
             .then(function(user){
                 self.currentUser = user;
              })
             .catch(function(err){
                console.log(err);
                self.currentUser = null;
              });
},

既存の処理の修正

loginWithUUIDは、まずログインできるかどうかを確認し、ログインできなかった場合には会員登録処理を行う流れとなっています。
そのため、会員登録処理を呼び出していた箇所でloginWithUUIDを呼び出し、ログイン処理を行うように変更します。
具体的にはinit()メソッドの最後にあったncmb.createUser()の呼び出し部分を以下のように書き換えます。

// main.js -> init()

ncmbController.loginWithUUID();

また、会員登録処理が成功したらログインする必要があるので、「ユーザー登録に成功しました!」アラートの代わりに呼び出し処理を追加します。

// ncmbController.js -> ncmbController -> createUser()

//会員登録を行うメソッドを実行
user.signUpByAccount()
    .then(function(user){
        // 登録完了後ログイン
        localStorage.setItem("userName", uuid);
        self.loginWithUUID();
    })

これで、ログイン処理を実装することができました。

ユーザー名を登録する処理を実装する

ゲームプレイ後、ユーザーに名前を入力してもらう処理を実装します。会員登録はアプリ起動時に行っていますので、ここではユーザー名の更新のみ行います。

Onsen UIを導入する

UIの見た目を整えるため、UI系のライブラリである「Onsen UI」を使用します。Onsen UIを使用しない場合はこの手順をスキップし、「jQueryを導入する」へ進んでください。

Onsen UIは、JS/CSSコンポーネント読み込みで追加できます。
途中でCSSを読み込む設定が出てきますので、onsen-css-components-dark-theme.cssにチェックを入れてください。

OnsenUI導入
初期化のためのコードを記述します。
main.jsのinit()メソッドの最後に、以下のコードを追加してください。

// main.js -> init()

 ons.bootstrap();

jQueryを導入する

表示系の処理を簡単に記述するため、JavaScriptのライブラリであるjQuery(Monaca Version)を使用します。
「設定」メニューの「JS/CSSコンポーネント読み込み」から、OnsenUIと同様に追加を行ってください。ローダーの設定を行った後、コードに記述を追加する必要はありません。

登録画面をつくる

登録するための入力フォームをHTMLに追加します。
</body>の直前に以下の内容を追記してください。

<div id="mask" class="mask"></div>
<div id="userEditWrapper" class="userEditWrapper">
  <form id="userEdit">
  <label for="name">プレイヤー名</label><br />
  <input type="text" id="name" value="" class="text-input" /><br />
  <input type="button" id="submit" class="button" value="送信" />
  </form>
</div>

CSSについても、以下のコードを追加します(css/style.css)。
div.maskは、入力画面が表示されている間背景を暗くし、ボタン操作ができないようにするために使用します。

.mask{
  display: none;
  position: absolute;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, .5);
  z-index: 1;
}

.userEditWrapper{
  display: none;
  position: absolute;
  width: 80%;
  padding: 10px;
  line-height: 1.5em;
  color: #fff;
  background: #000;
  border: solid 1px #b22222;
  text-align: center;
  z-index: 2;
}

.text-input{
  margin: 10px 0;
}

.button{
  background: #b22222;
}

入力欄の表示と登録処理を実装する

プレイヤー名の入力欄の表示と登録処理の実装を行います。
会員情報に新たにdisplayNameというフィールドを作成し、そこに名前を格納します。

なお、ncmbControllerの初期化で定義したscreenSizeはここで使用します。

// ncmbController.js -> ncmbController

// ユーザー名登録フォームの表示
showDisplayNameDialog: function() {
    var self = this;

    $("#mask").show();
    // ダイアログを左右中央に表示する
    $("#userEditWrapper").css("top", self.screenSize.height / 2 - 100);
    $("#userEditWrapper").css("left", self.screenSize.width * 0.1);
    $("#userEditWrapper").show();
},

// ユーザー名登録
updateDisplayName: function(){
    $("#userEditWrapper").hide();
    $("#mask").hide();

    // 入力した名前をカレントユーザーにセット
    var name = $("#name").val();
    this.currentUser.set("displayName", name);

    // 会員情報の更新
    return this.currentUser.update();
},

updateDisplayNameは、成功・失敗をPromise形式で返すようにしています。
したがって、呼び出し元ではメソッドチェーンでつなぐことができます。

プレイヤー名の登録画面を呼び出す

スコア送信時にプレイヤー名が登録されていなければ、先ほどのメソッドを呼び出すように修正します。
合わせて、スコア送信時にログインされていない場合、ログインするように処理を変更します。

条件が複雑なので、スコア送信のメソッドとは分けて定義するようにします。
ゲーム終了後に呼び出し、条件分岐のみを行う関数finishGame(score)を追加します。

// ncmbController.js -> ncmbController

finishGame: function(score){
    var self = this;

    if(!self.currentUser){
        self.loginWithUUID();
    } else if(!self.currentUser.displayName){
        // まだユーザー名を登録していない場合
        self.showDisplayNameDialog();

        $("#submit").on("click", function(){
            self.updateDisplayName()
                .then(function() {
                    self.sendScore(score);
                })
                .catch(function(err) {
                    console.log(err);
                    alert("ユーザー名の登録に失敗しました");
                });
        });
    } else {
        // ユーザー名登録済:スコア送信
        self.sendScore(score);
    }
},

合わせて、main.jsの呼び出し元も変更します。

// main.js -> BB

// Game Over
endGame: function() {
    BB.gameState = GAMESTATE_STOP;
    vibrate();
    ncmbController.finishGame(BB.score);
},

// Game Clear
clearGame: function() {
    BB.gameState = GAMESTATE_STOP;
    ncmbController.finishGame(BB.score);
}

動作を確認する

ここまでで、プレイヤー名の登録処理を実装することができました。
この実装により、初回プレイ時にプレイヤー名の登録画面が表示され、2回目のプレイ以降は表示されなくなります。

プレイヤー名登録
登録したプレイヤー名は、mobile backendのダッシュボードでも確認できます。

プレイヤー名確認

スコアとプレイヤーを紐付ける

プレイヤーの情報は保存できましたが、このままではスコアが誰によって保存されたものなのかわかりません。
ここでは、スコアとプレイヤーの紐付け処理について実装します。

スコア保存時にプレイヤーを保存する

スコアを保存する際、userフィールドにcurrentUserを格納して保存するようにします。

// ncmbController.js -> ncmbController -> sendScore

// [1]Score(クラス)を生成
var Score = self.ncmb.DataStore("ScoreClass");

// [2]インスタンス生成、スコア数値とログインしているユーザー(ポインタ)をセット
var scoreData = new Score({score: score, user: self.currentUser});

// [3]送信処理
scoreData.save()
    .then(function (saved) {
// 以下、既に実装したコードから変更なし

動作を確認する

ユーザースコア保存
スコアを保存してmobile backendのダッシュボードで確認すると、userフィールドにポインタが格納されていることがわかります。
クラス名とオブジェクトIDが格納されているため、ユーザーを一意に特定することができます。

スコアランキングを表示する

ここまでで、スコアの保存と、スコアを獲得したユーザーとの紐付けを行うことが出来ました。
最後に、このデータを使ってスコアランキング機能を実装しましょう。

ランキングを取得する

mobile backendのデータストアから、上位のスコアを取得する処理showRankingを実装します。

スコアの取得は、順位のときと同様クエリを使います。
「スコアの高い順」など、データの並び替えを行うときはorder('field', isDescended)メソッドを使用します。
上位10件を取得し、まずはコンソールに出力してみましょう。

// ncmbController.js -> ncmbController

showRanking: function() {
    var self = this;

    //スコア情報を取得するため、クラスを作成
    var Score = self.ncmb.DataStore("ScoreClass");

    //スコアを降順に10件取得
    Score.order("score", true)
        .limit(10)
        .fetchAll()
        .then(function(results){

            // 取得した内容をコンソールに表示
            if(results.length > 0){
                for(i=0; i<results.length; i++){
                    var score = results[i],
                        rank = i + 1,
                        value = parseInt(score.score);

                    console.log(rank + ": " + value);
                }
            } else {
                console.log("スコアデータがありません");
            }

        })
        .catch(function(err){
          console.log(err);
        });
},

ランキング取得処理を呼び出すためのボタンを画面に設置します。
今回はRESETボタンの隣に「RANKING」というボタンを表示するようにします。
画面上の各ボタンの描画はmain.jsのBB.reset()で行っていますので、そこに追記します。

// main.js -> BB

// Reset current game and start new one
reset: function() {
    //Reset (remove all children in the stage if exists)

    ...

    var resetLabel = new PIXI.Text("RESET", {font: "24px/1.2 vt", fill: "red"});
    resetLabel.position.x = 18;
    resetLabel.position.y = BB.renderer.height - 52;
    BB.stage.addChild(resetLabel);
    resetLabel.buttonMode = true;
    resetLabel.interactive = true;
    resetLabel.click = resetLabel.tap = function(data) {
        BB.reset();
    };
    setTimeout(function() {
        resetLabel.setText("RESET"); //for Android
    }, 1000, resetLabel);

    // ここから追加(ランキングボタン)
    var rankingLabel = new PIXI.Text("RANKING", {font: "24px/1.2 vt", fill: "red"});
    rankingLabel.position.x = 80;
    rankingLabel.position.y = BB.renderer.height - 52;
    BB.stage.addChild(rankingLabel);
    rankingLabel.buttonMode = true;
    rankingLabel.interactive = true;
    rankingLabel.click = rankingLabel.tap = function(data) {
        ncmbController.showRanking();
    };
    setTimeout(function() {
        rankingLabel.setText("RANKING"); //for Android
    }, 1000, rankingLabel);
    // ここまで追加

    ...

    BB.gameState = GAMESTATE_PLAY;
},

ラベルの表示位置や文字の指定のほか、
タップしたときに先ほど作成したncmbController.showRanking()を呼び出すように設定しています。

コンソールに表示
RANKINGボタンをタップすると、コンソールに上位10件のスコアが表示されました。

スコアと一緒にユーザー名を取得する

誰が達成したスコアなのか、プレイヤー名を一緒に取得するように変更します。

今回、スコアデータの中にはユーザー情報をポインタとして格納しています。
スコアデータと一緒に取得するためには、include('field')メソッドを使用します。

// ncmbController.js -> ncmbController -> showRanking

//スコアを降順に10件取得、ユーザー情報を含める形で
Score.order("score", true)
    .include("user")
    .limit(10)
    .fetchAll()
    .then(function(results){

        // 取得した内容をコンソールに表示
        if(results.length > 0){
            for(i=0; i<results.length; i++){
                var score = results[i],
                    rank = i + 1,
                    value = parseInt(score.score),
                    displayName = "NO NAME";

                // ユーザーが正しく取得できていれば、ユーザー名を変数に格納
                if(score.user !== undefined){
                    displayName = score.user.displayName;
                }

                console.log(rank + ": " + displayName + "(" + value + ")");
            }
        } else {
            console.log("スコアデータがありません");
        }

    })
    .catch(function(err){
      console.log(err);
    });

これで、ランキング画面に必要な情報を取得することができました。

ランキング画面をつくる

取得したデータを、ランキング画面として綺麗に表示しましょう。

まずは、ランキングを表示する画面をHTMLで作ります。
</body>の直前に、以下のように追加します。

<div id="ranking" class="ranking">
    <h2>ランキング</h2>
    <ul id="rankingTable" class="list list--inset rankingTable">
    </ul>
    <ons-button class="login-button" id="closeRanking">閉じる</ons-button>
</div>

合わせて、CSSにもスタイルを追加します。

.ranking{
    display: none;
    position: absolute;
    width: 100%;
    min-height: 100%;
    color: #fff;
    background: #000;
    text-align: center;
    z-index: 3;
}

.rankingTable{
    margin: 10px 0;
}

先ほどランキングデータを取得していたshowRankingで、HTMLを作成するように変更します。
合わせて、ランキング画面の表示処理も実装します。

// ncmbController.js -> ncmbController -> showRanking

//スコアを降順に10件取得、ユーザー情報を含める形で
Score.order("score", true)
    .include("user")
    .limit(10)
    .fetchAll()
    .then(function(results){

        //ランキング表のHTML生成
        var tableSource = "";
        if(results.length > 0){
            for(i=0; i<results.length; i++){
                var score = results[i],
                    rank = i + 1,
                    value = parseInt(score.score),
                    displayName = "NO NAME";

                // ユーザーが正しく取得できていれば、ユーザー名を変数に格納
                if(score.user !== undefined){
                    displayName = score.user.displayName;
                }

                tableSource += "<li class=\"list__item list__item--inset\">"
                    + rank + ":"
                    + displayName
                    + " (" + value + ")</li>";
            }
        } else {
            tableSource += "<li class=\"list__item list__item--inset\">ランキングはありません</li>";
        }

        $("#rankingTable").html(tableSource);

        //ランキング画面を表示する
        $("#ranking").show();
    })
    .catch(function(err){
      console.log(err);
    });

最後に、ランキング画面を閉じる処理を実装します。

// ncmbController.js -> ncmbController

//ランキング画面を閉じる
closeRanking:function() {
    $("#ranking").hide();
}

ncmbControllerのinit()の中で、ボタンを押したときに動作するように設定しておきましょう。

// ncmbController.js -> ncmbController -> init()

//閉じるボタンの動作を規定
$("body").on("click", "#closeRanking", function(){
    self.closeRanking();
});

ランキング完成
以上で、上位のスコアとプレイヤー名をランキング画面に表示できるようになりました。

動作を確認する

最後に、出来上がったアプリの動作を確認してみましょう。

ランキング画面
なおMonacaデバッガーを使用する場合、[設定]→[localStorageの削除]を行うと端末からユーザー情報が削除されるため、初回起動時の状態を再現することができます。

まとめ

このチュートリアルでは、ブロック崩しゲームのサンプルに、以下の機能を実装しました。

  • ゲームのスコアをクラウド(mBaaS)に保存する機能
  • スコア保存時に名前を入力する(会員登録・ログイン)機能
  • スコアランキングを表示する機能

本来はサーバー側に、スコアの受け入れやログイン用プログラム、スコアとユーザーのデータベースを作成する必要がありますが、
mBaaSを利用すると、このようにクライアントアプリ(ゲーム)側の実装だけでオンライン機能を実現することができます。

バックエンドの知識がないために諦めていた機能も、mBaaSなら実現できるかもしれません。
ぜひ、mBaaSを使って魅力的なアプリをつくってください!

お探しの内容が見つからなかった場合はユーザーコミュニティ もご活用ください。(回答保証はいたしかねます)
なお、 Expertプラン以上のお客様はテクニカルサポートにてご質問を承らせて頂きます。

推奨画面サイズ1024×768px以上

ページの先頭へ