Google Game Services 実績とリーダーボードの実装


前々回の記事で動かしたサンプルを参考に、実績とリーダーボードが実装されていない別のサンプルにこの二つを組み込んでみましょう。
今回はゲーム要素のある「ButtonClicker」を使用します。

実績とリーダーボードの閲覧
まずはactivity_main.xmlに実績閲覧用とリーダーボード閲覧用の二つのボタンを実装します。

<Button android:id="@+id/showAchievements"
       style="@style/MainScreenButton"
       android:text="実績を見る"/>
<Button android:id="@+id/showLeaderboards"
       style="@style/MainScreenButton"
       android:text="ランキングを見る"/>

次に、MainActivity.javaで追加したボタンを有効化します。
以下のように上記で記述したボタンを追加しましょう。

final static int[] CLICKABLES = {
            R.id.button_accept_popup_invitation, R.id.button_invite_players,
            R.id.button_quick_game, R.id.button_see_invitations, R.id.button_sign_in,
            R.id.button_sign_out, R.id.button_click_me, R.id.button_single_player,
            R.id.button_single_player_2,R.id.showAchirvment,R.id.showLeaderboards
    };

これを追加しないとsetOnClickListenerが生成されず、ボタンを押しても反応しなくなります。
もちろんボタン毎にsetOnClickListenerを記述しても良いのですが、コードが増えるので上記の方がわかりやすいかと思います。

ボタンの準備が終わったら、実績とリーダーボード、それぞれを閲覧するためのメソッドを実装します。

final int RC_RESOLVE = 5000, RC_UNUSED = 5001;
public void onShowAchievementsRequested() {
        if (isSignedIn()) {
            startActivityForResult(getGamesClient().getAchievementsIntent(), RC_UNUSED);
        } else {
            showAlert("サインインしてください。");
        }
    }

    public void onShowLeaderboardsRequested() {
        if (isSignedIn()) {
            startActivityForResult(getGamesClient().getAllLeaderboardsIntent(), RC_UNUSED);
        } else {
            showAlert("サインインしてください。");
        }
    }

最後にonClickに上記を呼び出す記述をして完了です。

@Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.showAchirvment:
                resetGameVars();
                onShowAchievementsRequested();
            break;
            case R.id.showLeaderboards:
                resetGameVars();
                onShowLeaderboardsRequested();
            break;
        }
     }

これで、追加されたボタンを押すと実績とリーダーボードを閲覧できるようになります。

実績の解除とリーダーボードへの記録の送信
まずは前々回の記事と同様にアプリのリンク、実績、リーダーボードの登録を行い、ids.xmlに「TypeANumber」の同ファイルを参考にして、実績とリーダーボードのIDを記述します。
実績とリーダーボードの準備が終わったら、MainActivity.javaに以下のクラスを記述します。

class AccomplishmentsOutbox {
        int rankingScore = -1;

        boolean isEmpty() {
            return rankingScore < 0;
        }

        public void saveLocal(Context ctx) {
            /* TODO: This is left as an exercise. To make it more difficult to cheat,
             * this data should be stored in an encrypted file! And remember not to
             * expose your encryption key (obfuscate it by building it from bits and
             * pieces and/or XORing with another string, for instance). */

        }

        public void loadLocal(Context ctx) {
            /* TODO: This is left as an exercise. Write code here that loads data
             * from the file you wrote in saveLocal(). */

        }
    }

上記クラスの変数を宣言し、onCreateでloadLocalを実行します。

AccomplishmentsOutbox mOutbox = new AccomplishmentsOutbox();
@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mOutbox.loadLocal(this);
    }

saveLocalを行うメソッドと、リーダーボードの更新を行うメソッドを追加します。(今回はリーダーボードの名前を「ranking」としています)

void pushAccomplishments() {
        if (!isSignedIn()) {
            // can't push to the cloud, so save locally
            mOutbox.saveLocal(this);
            return;
        }
        if(mOutbox.rankingScore >= 0){
            getGamesClient().submitScore(getString(R.string.ranking),
                    mOutbox.rankingScore);
            mOutbox.rankingScore = -1;
        }
        mOutbox.saveLocal(this);
    }
void updateLeaderboards(int finalScore) {
        if(mOutbox.rankingScore < finalScore){
            mOutbox.rankingScore = finalScore;
        }
    }

まずはクリックした回数をリーダーボードに記録するために、制限時間終了後にリーダーボードへの記録の送信を行います。
gameTick()で制限時間の管理をしているので、そこに追記します。

// Game tick -- update countdown, check if game ended.
    void gameTick() {
        if (mSecondsLeft > 0)
            --mSecondsLeft;

        // update countdown
        ((TextView) findViewById(R.id.countdown)).setText("0:" +
                (mSecondsLeft < 10 ? "0" : "") + String.valueOf(mSecondsLeft));

        if (mSecondsLeft <= 0) {
            // finish game
            findViewById(R.id.button_click_me).setVisibility(View.GONE);
            broadcastScore(true);
            updateLeaderboards(mScore);
            pushAccomplishments();
        }
    }

これで制限時間終了後、リーダーボードに記録がされるようになりました。
続けて、条件を満たした時に実績を解除する記述です。今回はボタンのクリックを1回目と10回目に実績を解除するように設定しています。
scoreOnePoint()でクリックした回数を管理しているので、そこに追記します。

// indicates the player scored one point
    void scoreOnePoint() {
        if (mSecondsLeft <= 0)
            return; // too late!
        ++mScore;
        updateScoreDisplay();
        updatePeerScoresDisplay();
        if(mScore == 1){
            if (getGamesClient().isConnected()) {
                // unlock the "Trivial Victory" achievement.
                getGamesClient().unlockAchievement(
                        getString(R.string.bc_achievement_1));
            }
        }
        if(mScore == 10){
            if (getGamesClient().isConnected()) {
                // unlock the "Trivial Victory" achievement.
                getGamesClient().unlockAchievement(
                        getString(R.string.bc_achievement_2));
            }
        }

        // broadcast our new score to our peers
        broadcastScore(false);
    }

これでボタンクリック1回目と10回目に対応した実績が解除されるようになりました。
元のサンプルでは実績解除時にToastが表示されるようになっていますが、デフォルトで画面上部に通知が出るので今回は特に通知は行っていません。

Comments

comments

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です