[Part.1] EメールよりURLSchemes機能を活用してゲームレベルデータを送信する解決方法

僕のアプリでユーザを”自分のゲームレベルをデザインして友達に送信して遊べさせる”ような機能があったらいいなと思ったりしなかったかい?

マイサーバがありましたらそれは簡単に実現できます、或はopenfeintのチャレンジ機能とgamecenterを利用すればそれも実現できるのはず。(やったことがないんですけど−_−)

でも、これらの実現方法はそれぞれの要求を満足させなければならない、やっぱり、もっと簡単できそうな方法が欲しいです。

実はURLSchemesと言う機能をうまく利用すれば”自分のゲームレベルをデザインして友達に送信して遊べさせる”という機能も簡単に実現できます。

このチュートリアルには以下の内容が含まれている:

1.デモ用のシーン(CCScene/CCLayer)とクラスを用意する
2.JSONの使い方(読み込む・書き込み)
3.アプリ内でメールを送信する
4.URLSchemesの使い方(送信・受信)
5.まとめ

1.デモ用のシーン(CCScene/CCLayer)とクラスを用意する

このデモプロジェクトをできるだけ理解し易いさせるため以下のシーン(レーヤ)を用意します:

a.MainMenu Scene: 様々なメニュー選択項が含まれてる

b.MyEditor Scene: ”ゲームレベル”を自動的に生成して、それをメールで友達に送信することができる(生成した”ゲームレベル”は同時にローカルでセーブする)

c.MySentLevel Scene: 生成した”ゲームレベル”を表示し”再生”することができます

d.MyReceivedLevel Scene: メールから受信された”ゲームレベル”を表示し”再生”することができます

それらのシーンを除いて”GameDataManage”というクラス(シングルトン)も必要なんです。様々なデータと関数を提供してプロジェクトのどこからデモアクセスさせるようにね^_^

最後はJSONファイルのデータ構造と対応する”GameLevelData”というクラスが必要なんです。

これで必要なシーン(CCScene/CCLayer)とクラスの用意は全部できっているので次からは”JSONの使い方”を移動しよう^_^

2.JSONの使い方(読み込む・書き込み)

ゲームのデータをソースの中にではなく別々の設定ファイルに保存するのはいい習慣です。もちろんplistとxml使っても構わないんですがこのデモにはJSONを使用することになってます。

簡単なデータ構造を使用する場合は複雑なxmlではなくJSONを使用するほうがいい、それにcocos2dに含まれた”TouchJson”よりJSONファイルの読み込むと書き込みも楽々です。

このデモに使用するJSONデータ構造はいかになります:

[cc lang=”objc”] {
“PlayerName”: “SuperSuRaccoon”,
“SpriteArray”:
[
{
“SpriteName”: “Sprite1”,
“SpritePng”: “raccoon.png”,
“SpriteScale”: 1.2,
“SpritePosition”:
[
{
“XPos”: 120,
“YPos”: 150,
}
] },
{
“SpriteName”: “Sprite2”,
“SpritePng”: “rabbit.png”,
“SpriteScale”: 0.6,
“SpritePosition”:
[
{
“XPos”: 300,
“YPos”: 100,
}
] }
] }
[/cc]

ご覧の通りでデータは主には二つの部分に分かれている:”Playername”とCCSpriteのあらゆるの属性を持つ”SpriteArray”です

2.1 JSONを読み込む

TouchJsonを用いてJSONファイルを読み込むのは実に簡単です:

[cc lang=”objc”] NSString *testJsonFilePath = [[NSBundle mainBundle]pathForResource:@”test” ofType:@”json”];
NSData *testJsonFileData = [[NSFileManager defaultManager] contentsAtPath:testJsonFilePath];
CJSONDeserializer *jsonDeserializer = [CJSONDeserializer deserializer];
NSDictionary *testConfigDict = [jsonDeserializer deserializeAsDictionary:fileData error:nil];
[/cc]

まずはファイルの中にをNSDataに読み込んでそれでCJSONDeserializerよりNSDataをNSDictionaryに転換する

2.2 NSDictionary解析する

すべてのデータを持っているNSDictionaryがあるんのでそれを”GameLevelData”対象に解析すべきです。

GameLevelDataクラスは以下になります:

[cc lang=”objc”] @interface SpriteData : CCNode {

NSString *spriteName;
NSString *spritePng;
CGPoint spritePosition;
float spriteScale;
}

@property(nonatomic, retain) NSString *spriteName;
@property(nonatomic, retain) NSString *spritePng;
@property(nonatomic) CGPoint spritePosition;
@property(nonatomic) float spriteScale;

@end

@interface GameLevelData : CCNode {

NSString *playerName;
NSMutableArray *spriteArray;
}
@property(nonatomic, retain) NSString *playerName;
@property(nonatomic, retain) NSMutableArray *spriteArray;

@end
[/cc]

例えばNSDictionaryから”playername”を取り出す場合はこう:

[cc lang=”objc”] GameLevelData *glData = [[GameLevelData alloc] init];
glData.playerName = [testConfigDict objectForKey:@”PlayerName”];
[/cc]

簡単でしょう^_^

後はspriteArrayからデータを取り出す(少し面倒なんです):

[cc lang=”objc”] NSArray *spriteArray = [testConfigDict valueForKey:@”SpriteArray”];
for (NSDictionary *spriteInfo in spriteArray) {

SpriteData *spData = [[SpriteData alloc] init];
spData.spriteName = [spriteInfo objectForKey:@”SpriteName”];
spData.spritePng = [spriteInfo objectForKey:@”SpritePng”];
spData.spriteScale = [[spriteInfo objectForKey:@”SpriteScale”] floatValue];

NSArray *spritePosArray = [spriteInfo valueForKey:@”SpritePosition”];
for (NSDictionary *spritePosInfo in spritePosArray) {

spData.spritePosition = ccp([[spritePosInfo objectForKey:@”XPos”] floatValue],
[[spritePosInfo objectForKey:@”YPos”] floatValue]);
}

[glData.spriteArray addObject:spData];
}
[/cc]

こういう感じです^_^

一回解析した結果をプリントして見よう:

[cc lang=”objc”] -(void) printGameLeveDataInfo:(GameLevelData *)glData
{
/*Debug Log*/
CCLOG(@”/**************Game level data**************/”);
CCLOG(@”PlayerName: %@”, glData.playerName);

for (SpriteData *spData in glData.spriteArray) {

CCLOG(@”SpriteName: %@”, spData.spriteName);
CCLOG(@”SpritePng: %@”, spData.spritePng);
CCLOG(@”SpritePng: %0.1f”, spData.spriteScale);
CCLOG(@”SpritePosition: %0.1f – %0.1f”, spData.spritePosition.x, spData.spritePosition.y);
}
CCLOG(@”/*******************************************/”);
/*Debug Log*/
}
[/cc]

コンソールから出た出力:

[cc lang=”objc”] URLSchemesDemo[1012:207] /**************Game level data**************/
URLSchemesDemo[1012:207] PlayerName: SuperSuRaccoon
URLSchemesDemo[1012:207] SpriteName: Sprite1
URLSchemesDemo[1012:207] SpritePng: raccoon.png
URLSchemesDemo[1012:207] SpritePng: 1.2
URLSchemesDemo[1012:207] SpritePosition: 120.0 – 150.0
URLSchemesDemo[1012:207] SpriteName: Sprite2
URLSchemesDemo[1012:207] SpritePng: rabbit.png
URLSchemesDemo[1012:207] SpritePng: 0.6
URLSchemesDemo[1012:207] SpritePosition: 300.0 – 100.0
URLSchemesDemo[1012:207] /***********************************************/
[/cc]

完璧だ! これでJSONの読み込むと解析が完成です。

2.3 JSONを書き込み

NSDataをJSONファイルに書き込みのはTouchJsonを使わなくっだていいんです。writeToFileで十分です:

[cc lang=”objc”] [jsonData writeToFile:filePath options:NSDataWritingAtomic error:nil];
[/cc]

が, NSDictinnaryをNSDataに転換するのはTouchJsonを使わなければならない:

[cc lang=”objc”] jsonData = [[CJSONSerializer serializer] serializeObject:gameLevelDic error:nil];
[/cc]

”gameLevelDic”は解析時と真逆な手順でNSDictionaryにJSONファイルと対応するデータを追加して出来たものです:

[cc lang=”objc”] //save all the level info into a Big Dic
NSMutableDictionary *gameLevelDic = [[NSMutableDictionary alloc] init];
[gameLevelDic setValue:@”sxc” forKey:@”PlayerName”];

NSMutableArray *spriteArray = [[NSMutableArray alloc] init];

//random num of sprites to generate
numOfSprites = 1 + CCRANDOM_0_1() * 10;

for (int i = 0; i < numOfSprites; i++) { //pick raccoon or rabbit NSString *spriteFile = @""; if (CCRANDOM_0_1() > 0.5f) {

spriteFile = @”raccoon.png”;
}
else {

spriteFile = @”rabbit.png”;
}
CCSprite *sprite = [CCSprite spriteWithFile:spriteFile];
sprite.scale = 0.1 + CCRANDOM_0_1() * 1;
sprite.position = ccp(20 + CCRANDOM_0_1() * 400, 20 + CCRANDOM_0_1() * 300);
sprite.tag = i;

[self addChild:sprite];

//Position info
NSMutableDictionary *positionDic = [[NSMutableDictionary alloc] init];
[positionDic setValue:[NSNumber numberWithFloat:sprite.position.x] forKey:@”XPos”];
[positionDic setValue:[NSNumber numberWithFloat:sprite.position.y] forKey:@”YPos”];

//Sprite info
NSMutableDictionary *spriteDic = [[NSMutableDictionary alloc] init];
[spriteDic setValue:spriteFile forKey:@”SpriteName”];
[spriteDic setValue:spriteFile forKey:@”SpritePng”];
[spriteDic setValue:[NSNumber numberWithFloat:sprite.scale] forKey:@”SpriteScale”];

NSMutableArray *posArray = [[NSMutableArray alloc] init];
[posArray addObject:positionDic];
[spriteDic setValue:posArray forKey:@”SpritePosition”];

[spriteArray addObject:spriteDic];
}

[gameLevelDic setValue:spriteArray forKey:@”SpriteArray”];
[/cc]

これで, 生成した”ゲームレベル”をJSONフォーマットしたらお仕事完了です。

PS: 生成したデータをJSONファイルに書き込んだ後ファイルには改行とインデントがないのでちょっと読み辛いです。

JSONの読み込む・書き込みが完成したのでそれをメールで送信しよう^_^

パート2を完成した後ソースコードを公開する予定です、お楽しみに^_^

デモスクリンショット:

☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆

If you feel all the stuffs in this site helped you a lot and you would buy me a beer 🙂

Or get a game I made 🙂


☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆

にほんブログ村 IT技術ブログ iPhoneアプリ開発へ にほんブログ村 IT技術ブログへ