Pankia wiki ~Match~

Pankiaにはオフライン対戦とオンライン対戦があります。

//データの送信
+ (void)sendData:(NSData *)data toUser:(NSString *)user reliable:(BOOL)reliable;
+ (void)sendDataToAllUsers:(NSData *)data reliable:(BOOL)reliable;
//対戦開始からの経過時間
+ (double)timeElapsedOnCurrentMatch;
+ (double)timeElasped __deprecated;
//対戦終了 2種類の説明は後述
+ (void)finishMatchWithResult:(PNMatchResult *)result onSuccess:(void (^)(void))onSuccess onFailure:(void (^)(NSError *error))onFailure;
+ (void)endMatch;
//再戦
+ (void)waitForRematch:(int)timeout;
//対戦人数設定
+ (void)setInternetMatchMinRoomMember:(int)minMember;
+ (void)setInternetMatchMaxRoomMember:(int)maxMember;
+ (void)setLocalMatchMinRoomMember:(int)minMember;
+ (void)setLocalMatchMaxRoomMember:(int)maxMember;

対戦のときはさまざまな場合で呼ばれるメソッドが多くあります。

//対戦開始時
- (void)matchDidBegin:(PNMatchSession *)session;
//データ受信時
- (void)matchDidReceiveData:(NSData *)data fromUser:(NSString *)user;
//対戦相手の切断検知時
- (void)matchDidDisconnectWithUser:(NSString *)user;
//対戦終了時
- (void)matchDidFinish;
- (void)matchDidEnd;

データ送信時NSData *NSArray *型やNSString *型を変換して送信するのがよいかと思います。また, reliableをYESにするとデータの送信に失敗しても再送するため信頼度はあがります。リアルタイムを重視するならNOがいいと思います。

対戦終了はにfinish系とend系がありますが,finish系は対戦は終了し,結果も送信するが通信は終了されず,その後再戦もできる。end系は通信を終了するものなので普通に終了したい場合はfinishしたあとendする。

対戦開始時に受け取るPNMatchSession *から対戦情報を得る事が出来ます

@interface PNMatchSession : NSObject

@property (nonatomic, readonly) NSArray *members;
@property (nonatomic, readonly) int selfIndex;
@property (nonatomic, readonly) int lobbyId;
@property (nonatomic, readonly) BOOL isInternetMatch;

Pankia wiki ~Item~

アイテムによるメソッド

//アイテムの増加,減少,量
+ (int64_t)acquireItem:(int)itemId quantity:(int64_t)quantity error:(NSError **)error;
+ (int64_t)consumeItem:(int)itemId quantity:(int64_t)quantity error:(NSError **)error;
+ (int64_t)quantityOfItem:(int)itemId;
//購入
+ (void)purchaseProductWithProductIdentifier:(NSString *)productIdentifier onSuccess:(void (^)(NSData *receipt))onSuccess onFailure:(void (^)(NSError *error))onFailure;
+ (PNSKProduct *)productWithProductIdentifier:(NSString *)productIdentifier;
//アドオンを購入しているか
+ (BOOL)isAddOnPurchasedWithItemId:(int)itemId;
//オンライン時のみのアイテム増加,減少,量
+ (void)acquireItemSynchronously:(int)itemId quantity:(int64_t)quantity onSuccess:(void (^)(int64_t newQuantity))onSuccess onFailure:(void (^)(NSError *error))onFailure;
+ (void)consumeItemSynchronously:(int)itemId quantity:(int64_t)quantity onSuccess:(void (^)(int64_t newQuantity))onSuccess onFailure:(void (^)(NSError *error))onFailure;
+ (void)fetchItemOwnershipsWithOnSuccess:(void (^)(NSArray *ownerships))onSuccess onFailure:(void (^)(NSError *error))onFailure;
//オフライン時のアイテム管理の有効性
+ (void)setOfflineOwnershipManagamentEnabled:(BOOL)value;

このメソッドにでてくるものから,まずPNSKProduct *には以下のpropertyがあります

@interface PNSKProduct

@property (nonatomic, retain) NSString* productIdentifier;
@property (nonatomic, retain) NSString* localizedTitle;
@property (nonatomic, retain) NSString* localizedDescription;
@property (nonatomic, retain) NSDecimalNumber* price;
@property (nonatomic, retain) NSLocale* priceLocale;

そして

+ (int64_t)acquireOrConsumeItem:(int)itemId quantity:(int64_t)quantity error:(NSError **)error;

などにはPNItem*PNItemCategory*がありますが,PNItem*のpropertyは以下

@interface PNItem : PNModel

@property (nonatomic, assign) int id;
@property (nonatomic, retain) NSString *iconUrl;
@property (nonatomic, retain) NSString *categoryId;
@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSString *itemDescription;
@property (nonatomic, assign) int64_t quantity;
@property (nonatomic, assign) int64_t maxQuantity;
@property (nonatomic, retain) NSArray *screenshotUrls;
@property (nonatomic, readonly) NSArray *merchandises;
@property (nonatomic, readonly) PNItemCategory *category;
@property (nonatomic, readonly) NSString *stringId;
@property (nonatomic, readonly) BOOL isCoin;

PNItemCategory*についての使い方は

PNItem* item = [PNItem itemWithId:itemId];
PNItemCategory* category = [item category];

という風にカテゴリを出します。itemIdは必ず必要になってきますのでWEB上で設定したものを最初に定義しておきます

Pankia wiki ~LeaderBoard~

+ (NSArray *)leaderboards;
//ランクやスコアの取得(サーバー経由)
+ (void)fetchRankOnLeaderboard:(int)leaderboardId onSuccess:(void (^)(PNRank *rank))onSuccess onFailure:(void (^)(NSError *error))onFailure;
+ (void)fetchAllLeaderboardsRankWithOnSuccess:(void (^)(NSArray *ranks))onSuccess onFailure:(void (^)(NSError *error))onFailure;
+ (void)fetchLatestLeaderboardsScore:(NSArray *)leaderboardIds onSuccess:(void (^)(NSArray *scores))onSuccess onFailure:(void (^)(NSError *error))onFailure;
+ (void)scoresOnLeaderboard:(int)leaderboardId amongFriends:(BOOL)amongFriends offset:(int)offset limit:(int)limit onSuccess:(void (^)(NSArray *scores))onSuccess onFailure:(void (^)(NSError *error))onFailure;
//スコアの送信(使いたい型のものを利用)
+ (int64_t)postScore:(int64_t)score leaderboardId:(int)leaderboardId isIncremental:(BOOL)isIncremental;
+ (int64_t)postScore:(int64_t)score leaderboardId:(int)leaderboardId;
+ (float)postFloatScore:(float)score leaderboardId:(int)leaderboardId isIncremental:(BOOL)isIncremental;
   ...
//スコアの取得(ローカル経由)(使いたい型のものを利用)
+ (int64_t)latestScoreOnLeaderboard:(int)leaderboardId;
+ (float)latestFloatScoreOnLeaderboard:(int)leaderboardId;
...
//オンラインオフライン時の管理について
+ (void)postScoreSynchronously:(int64_t)score leaderboardId:(int)leaderboardId isIncremental:(BOOL)isIncremental onSuccess:(void (^)(PNRank *latestScore))onSuccess onFailure:(void (^)(NSError *error))onFailure;
+ (void)setOfflineScoreManagementEnabled:(BOOL)value;
+ (void)setScore:(int64_t)score onLeaderboard:(int)leaderboardId forNonPlayerCharacter:(NSString *)userId;
+ (int64_t)scoreOnLeaderboard:(int)leaderboardId forNonPlayerCharacter:(NSString *)userId;

リーダーボードにはこのようなメソッド達があります,

まずスコアの取得について サーバー経由とローカル経由がありますが,それぞれでの返り値の型が違う事に気づくと思います。
サーバー経由の方でPNRank *またはその配列NSArray *でスコアがかえされているのでそこからスコアを取得する必要があるが,整数(int64_t型)はrank.scoreにて取得できる。

PNRank *には以下のようなpropertyがあるので必要に応じて利用します

@interface PNRank : PNModel

@property (retain) PNUser *user;
@property (assign) int leaderboardId;
@property (assign) int rank;
@property (assign) long long score;
@property (assign) int userCount;
@property (assign) BOOL isRanked;

Pankia wiki ~Achievements~

アチーブメントには主に4つの使用できるメソッドがあります

//登録したアチーブメント達の配列値
+ (NSArray *)achievements;
//アンロックされているアチーブメント達
+ (NSArray *)unlockedAchievements;
//指定したIDのアチーブメントを解放
+ (void)unlockAchievement:(int)achievementId;
//指定したアチーブメントがロックされているかの真偽値
+ (BOOL)isAchievementUnlocked:(int)achievementId;

下の二つの使い方はコメントアウトの通りですが 上の二つを使ってアチーブメントの詳細情報を利用する事が出来ます。

@interface PNAchievement ...
//PNAchievementにproperty定義されているこれらが利用できる
@property (assign) int achievementId;
@property (retain) NSString *title;
@property (retain) NSString *description;
@property (assign) NSUInteger value;
@property (retain) NSString *iconUrl;
@property (assign) BOOL isSecret;
@property (assign) BOOL isUnlocked;
@property (assign) int orderNumber;

利用例としては

//アチーブメント全体から, もしシークレット設定してあったらそのアチーブメントを解放する
 for (PNAchievement *achievement in [Pankia achievements]) {
      if(achievement.isSecret)
           [Pankia unlockAchievement:achievement.achievementId];
     }

などと,アチーブメントの詳細情報も利用してさらに細かく管理できます。

Pankia wiki ~Dashboard~

Pankiaの公式解説サイト(Pankia Developer's WIKI)で全てが書かれているのかと思いきや,一部の説明しかなかったのでPankia.hからどんなものがあるか探って解説していこうと思います

ではPankia.hを見ていく


Pankia.hへのアクセスは画像からわかると思います

Pankia.hに基本的に私たちが使用できるメソッドが書かれているわけですが,中身がわからないと,利用もできないですよね

上からサーっと見てみると

@interface Pankia
 ...

@end

@interface Pankia(Dashboard)
 ...

@end

@interface Pankia(Achievements)
 ...

といった風にPankiaのコンテンツごとに分けてクラス宣言されている

利用したい項目のところに宣言されているメソッドにどのようなものがあるのか見ていく事が大事です


今回はDashboardの部分を見ましょう

見つけるのが面倒な人は黒い画面の上のバーのメソッド名などが書かれている部分を押すと

といった画面からメソッド一覧が見る事ができます


Pankia.h

@interface Pankia(Dashboard)

//Dashboardの向き(不要?)
+ (UIInterfaceOrientation)dashboardOrientation;

//Dashboardの開閉
+ (void)dismissDashboard;
+ (void)launchDashboard;

//Dashboardを介さないで直接With~の部分へのリンク
+ (void)launchDashboardWithLeaderboards;
+ (void)launchDashboardWithLeaderboard:(int)leaderboardId period:(PNLeaderboardPeriod)period;
+ (void)launchDashboardWithAchievements;
+ (void)launchDashboardWithItems;
+ (void)launchDashboardWithStore;
+ (void)launchDashboardWithMerchandiseDetail:(NSString *)productIdentifier;
+ (void)launchDashboardWithSettings;
+ (void)launchDashboardWithNetworkMatch;
+ (void)launchDashboardWithInternetMatchLobbies;
+ (void)launchDashboardWithLocalMatchLobbies;
+ (void)launchDashboardWithInternetMatchLobby:(int)lobbyId;
+ (void)launchDashboardWithLocalMatchLobby:(int)lobbyId;
+ (void)launchDashboardWithPrivacyPolicy;

//Dashboardの向きの設定(不要?)
+ (void)setDashboardOrientation:(UIInterfaceOrientation)orientation;

@end

 ...

@protocol PankiaDelegate<NSObject>
 ...

#pragma mark Dashboard Related Methods

//Dashboardの開閉時に呼ぶメソッド
- (void)dashboardWillAppear;
- (void)dashboardDidAppear;
- (void)dashboardWillDisappear;
- (void)dashboardDidDisappear;

 ...
@end

Dashboardに関するメソッドは以上かな?

とりあえず実際はこれらは簡単に組み込める機能であります,


次は,Achievements について見ていきます

Pankiaの使い方① 〜機能紹介とアプリ使用例〜

Pankiaの導入が出来たところでこれらをどのように利用していくのか説明します

Pankiaの機能の一覧としてはこのようなものがあります

ダッシュボード
 ├アチーブメント
 ├リーダーボード
 ├アイテム
 ├ストア(アイテム販売)
 └ネットワーク対戦
・アドオン
・アセット
iOS 外部サービス連携

これらの機能についての詳しい説明,使い方はこちらのPankia公式の説明サイトをご覧ください

Pankia Developer’s WIKI

ここでは簡単にどのようにこれらの機能を利用するかを考えてみています

Pankiaの導入されたアプリは多数ありますが,
全てのゲームでこれらの全ての機能を利用しているわけではありません

特にオンライン対戦機能はとても興味深く,是非実装してみたい機能ではありますが,
ゲームによってはそれはとても大変な作業になってしまうことがあります

ではどのようなゲームでどのような機能を利用するのがよいか考えます


ダッシュボード】 タイトル画面などにまずPankiaのメインメニューであるダッシュボードへのリンクを設置しましょう


【アチーブメント】 アチーブメントは割とどのようなゲームにも簡単に設置が出来ます

 これは「初めての ー」とか「100回目の ー」などの割とどうでもいい情報でも称号的にもらえることはユーザーにとってはうれしいものです

 そしてアチーブメントは獲得するとリアルタイムで上のバーに出てくるので,細かく称号が出していくことにも向いています

 これらの情報はもちろんアプリ内で管理することも可能ですがPankiaで利用する事により,簡単にオンライン管理できるので,アプリを再インストールしてアプリ内のセーブデータが消えてしまっていてもPankiaアカウントさえあればそれらのデータは保存されています


【リーダーボード】 これは単純にスコアか時間を競うゲームにはとても適しています

 オンラインランキングが簡単に作成できるので単純なゲームでもこれを組み込みこむことでやりがいのあるゲームになります


【アイテム】 これは想像しての通りのアイテムなのですが,アイテムの所有数などをオンライン/オフラインで管理しています

 課金でアイテムを売りたい場合などはこれを利用すると便利です
 
 仮に課金アイテムのシステムを利用し,このようにオンラインでアイテム管理をしていなかった場合, ものにもよりますが セーブデータを復元する事でユーザーが課金アイテムを失ったり,また使用しても購入直後のデータに復元した場合またアイテムが残っていたりといった不具合が生じます

 ここは自分の体制に合わせて利用してください


【ストア】 ストアという項目で先ほどのアイテムを販売することができます

 この際気をつけておかなければならないのは売り上げの7%がレベニューシェアされること,

 自分でアプリ課金を組み込む事も可能です

 しかし,その課金方法を調べてみるとわかりますが,組み込みデバグがかなり大変です

 なので,どれほどの規模のものを制作するかによりますが特に初心者で課金機能を利用したいのであればこれを利用するのがいいのかと思います

 
【ネットワーク対戦】 これはPankiaの中では目玉な機能ではないでしょうか!

 ネットワーク対戦にはインターネット対戦(オンライン)とローカル対戦(オフライン)の2種類が用意されています

 公式ページ(Pankia Developer’s WIKI)を見ればわかると思いますが,やや大変です(ものすごーーーーーく簡単にしてありますがw)

 ネットワーク対戦といっても様々なゲームに組み込めますが例えば簡単なものとして,「チェス」ゲームのネットワーク対戦
 もちろん時間制限などを付け加えると少し大変になりますが基本は相手がデータを送信し(コマを置い)たら相手のデータを受信する(相手がコマを置く)まで待機といった具合で組み込める

 次に例えば「クイズの早押しゲーム」など
 この場合先程の「チェス」とは違い,早押しという時間にシビアなゲームであり,双方間での時間差(ランダムな問題であればそれも),があってはゲームにならない。なので時間を共有するため常に時間がずれていないかなどを確認,修正する必要がある

 最後にオンラインゲームといったらFPS!とか思う人も多いのかもしれませんがそれに限らずアクションゲームは時間,ランダム,そして自分,相手,敵,の情報の共有を常にしないといけないのでかなり大変かつ重くなる可能性があるという事をちゅういしていかなければならない

 ちなみにPankiaの開発元の制作アプリであるLightBike2はPankiaの機能でかなりリアルタイムのオンライン対戦が実装されています

 しかし初心者なので最初はボードゲームのようなものから実装を試していこうと思います



以上のメニューが【ダッシュボード】のメニュー内にある項目らです。



【アドオン】 先ほどのアイテム課金の非消費版のようなものです

 例)無料ではコース2まで。85円でコース10まで解放。

 といったもの。これもオンラインで管理しているのでアカウントさえあればデータは消えません

 ただ今はまだβ版のようなのでもう少し様子をみてから使うといいのかも(汗;

【アセット】 アプリをダウンロードして初回の起動時に”ファイルのダウンロード中..”といったようなメッセージが出た経験がありますか?

 その時はアプリに足りないリソースファイルなどを追加ダウンロードしています

 iPhoneアプリには3G回線のときダウンロード容量の制限が50MB(前までは20MB?)があるのでそれを少し超えてしまうなんて時に利用するといいと思います(あまり追加が多いと待ってる側も不安かつイライラするものです..)

 ただこの機能もまだβ版のようです


iOS外部サービス連携】 Pankiaでは外部サービスとしてTwitter,Facebookのアカウントにリンクすることができ,それぞれタイムライン,ウォールへ投稿することができます

 スコア共有をアプリの紹介も兼ねて投稿してもらうと宣伝にもなっていいとおもいます。



以上で機能の説明を簡単にしました


次回から実際にPankiaの機能を組み込んでみたいと思います

Pankiaの導入 〜簡単にソーシャルオンラインゲームアプリ開発〜

前回まででつくったアプリで一応遊べたりしていましたが,これらだけでは個人でゲームを遊んで自己満足で終わり 飽きてしまいますが,
でハイスコアの共有や,オンライン対戦などiPhoneならではのソーシャル的なサービスを追加する事ができます。

そこで一番簡単で使いやすいPankiaというソーシャルゲームフレームワークの導入から使い方まで紹介します

その前にPankiaを実際にやってみたことがない人はやってみましょう
自分で組み込んだソースがあればそれでいろいろ試してみてもかまわないが,Pankia導入済のアプリでも試してみよう


現在はPankiaは一般公開されているので誰でも無料で開発に利用できます。

Pankiaで主に追加できる機能は

・リアルタイムオンライン対戦
・オンラインスコア管理, 目標設定
・アイテム, アドオンの管理, 課金設定
Twitter, facebookなどのSNSとの連携サービス

では導入の方法を説明します。

【1】まずPankiaに登録しましょう

Pankiaホームページから[Download the SDK for FREE]をクリックします
http://pankia.com/

するとログイン画面が出てくるのでもしアカウントを持っていればここからログインします。
今回は新規登録として説明します

右上の[新規登録]をクリックします

ユーザー名, メールアドレス, パスワード を記入して下の規約への同意をチェックして[新規登録]をクリックします

すると You will receive an email within the next few minutes. It contains instructions for confirming your account. とでてくるので 登録したメールアドレスに登録確認のメールがきます。

書いてあるリンクにアクセスしますと登録が完了します

右上の[Developer]をクリックしてログインします

ログインに成功をすれば登録完了となります。

【2】PankiaSDKのインストール

ログイン後のマイページの右項目の中にある[Downloads]をクリックします

Pankiaはかなり随時最新版が更新されていますので基本的に最新版をダウンロードするのがいいと思います
今回の場合はPankia iOS 3.4.0(2012/04/16現在)

Downloadリンクからzipファイルをダウンロードして解凍します

すると Pankia というディレクトリが作成されるので,
これをXcodeのプロジェクトファイル内にコピーします。

ここでファイル, ディレクトリの追加方法の確認ですが

プロジェクトのメインディレクトリにまずファイルをコピーします

その後, Xcodeにドラッグ&ドロップでファイルをいれます

次にPankiaを利用するにあたって追加しなければばらばいフレームワークがあります

・CFNetwork
CoreFoundation
・CoreGraphics
・GameKit
・MessageUI
・QuartzCore
・Security
・StoreKit
・SystemConfiguration
・libsqlite3
・Foundation
・UIKit

足りないものがあれば, 追加します

AppDelegate.m

//Pankiaのヘッダファイルのimport
#import "Pankia.h"

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    ....
    // Warning! Encrypt the GAME_KEY and GAME_SECRET !
    // Unencrypted strings can easily be extracted from executables!
    //これを追加しないとPankiaはいっさい呼ばれない
    [Pankia initWithGameKey:GAME_KEY gameSecret:GAME_SECRET title:GAME_TITLE delegate:self options:launchOptions];
    ....
    return YES;
}

ここでGAME_KEY, GAME_SECRET, GAME_TITLE, がわからないということになったと思います。

これはPankiaホームページで設定していきます。

とりあえずテストとしてアプリを登録してみましょう。

先ほどのページから[add a new game]をクリックします

指定項目を記入して作成すると

Game Key pw....a
Game Secret s9W..........vD

といったかたちで表示されるのでそれをプログラム内で管理しましょう

AppDelegate.h

#define GAME_KEY @"pw....a"
#define GAME_SECRET @"s9W..........vD"
#define GAME_TITLE @"HelloWorld"

と定義しておけば先ほどの部分はエラーにならずできたと思います。

これでPankiaの導入は完了です

その他機能や使い方は公式で日本語の説明もありますのでそちらを参考にもしてみて下さい。

Pankia Developer's WIKI

次回からはどのように実際使っていくのか説明していきます