如果你有自己的服务器的话当然可以实现,或是使用openfeint的挑战功能以及Gamecenter(这个木有试过)来实现。
但是这些方法总是有些麻烦…要么得有台服务器,要么得使用penfeint/gamecenter(有的用户可能并没有用这些功能)。
其实,使用URLSchemes可以很简单的实现”游戏关卡发送“的功能^_^
本问包括了以下的内容:
1.准备需要的Scene和类
2.JSON文件的读写
3.在游戏内发送邮件
4.使用URLSchemes发送和接收数据
5.总结
1.准备需要的Scene和类
为了保证项目简单易懂,我们首先准备了以下几个Scene:
a.MainMenu Scene: 主菜单,包含了一些跳转的菜单项
b.MyEditor Scene: 随机生成”游戏关卡“并同时保存至本地,也可以通过邮件发送给朋友
c.MySentLevel Scene: 显示所有”发送的关卡“,可以选择关卡进行加载显示内容
d.MyReceivedLevel Scene: 显示所有”通过邮件接收的关卡“,可以选择关卡进行加载显示内容
除了这些Scene以外我们还需要一个使用单件模式的”GameDataManage“类来保存一些数据和提供一些方法,这样我们就可以在项目的所有地方对其进行访问。
最后需要的,是一个与JSON中保存数据结构一一对应的”GameLevelData”类。
OK,准备工作完成,接下来就开始JSON的读写部分^_^
2.JSON文件的读写
写游戏的一个好习惯自然是把一些数据和代码分离出来,用配置文件来进行保存。你可以使用plist或是xml,不过本项目选择使用JSON。
当你的游戏数据结构比较简单的时候,JSON会是一个不错的选择,通过cocos2d自带的”TouchJson”三方库,可以帮助你很轻松的读写JSON文件。
本项目所使用的JSON文件结构:
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 | { "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, } ] } ] } |
结构比较简单,主要是一个用户名,以及保存了CCSprite各种属性的大小可变的”SpriteArray”。
2.1 读取JSON文件
读取JSON格式的文件非常简单:
1 2 3 4 | 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]; |
首先把文件内容读入NSData,再使用CJSONDeserializer来将NSData转换为NSDictionary。
2.2 解析NSDictionary
NSDictionary中包含了我们所有的游戏数据信息,我们需要将其解析为我们的”GameLevelData”类对:
”GameLevelData“类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | @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 |
如何读取”playername“属性内容:
1 2 | GameLevelData *glData = [[GameLevelData alloc] init]; glData.playerName = [testConfigDict objectForKey:@"PlayerName"]; |
很简单吧^_^
读取spriteArray的话就相对比较麻烦了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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]; } |
搞定。
顺便把解析后的数据打印出来检查一下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | -(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*/ } |
控制台输出结果:
1 2 3 4 5 6 7 8 9 10 11 | 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] /***********************************************/ |
好了, 现在我们已经成功的读取并解析了JSON文件。接下来就是保存JSON文件了。
2.3 JSON文件的保存
其实将NSData保存为JSON文件并不需要使用到TouchJson,只需要:
1 | [jsonData writeToFile:filePath options:NSDataWritingAtomic error:nil]; |
就可以了。
但是我们需要使用TouchJson来将NSDictinnary转换为NSData:
1 | jsonData = [[CJSONSerializer serializer] serializeObject:gameLevelDic error:nil]; |
NSDictionary中包含的数据必须与JSON的数据结构一一对应,其实就是我们读取解析JSON的一个逆操作:
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 | //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"]; |
这样我们就可以把NSDictioany转换为NSData并写入JSON文件了。
PS: 这里保存好的JSON文件在格式上有一点小问题,文件中没有换行符和缩进,所以看起来比较麻烦,当然你可以自己写一段程序来解决这个问题。
接下来,我们就要在游戏中,通过邮件来发送我们的”游戏关卡“内容了^_^
我会在第二部分完成后把整个项目的源代码下载地址发布出来^_^
项目截图:
☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆
If you feel all the stuffs in this site helped you a lot and you would buy me a beer
我有一个QQ群,学开发的,可以一起学习:195949812