联系
我们
投稿
反馈
评论 返回
顶部

内容字号: 默认 大号超大号

段落设置: 段首缩进取消段首缩进

字体设置:切换到微软雅黑切换到宋体

Cocos2D配Box2D:逆天小白程序员作iOS游戏

2017-02-22 11:38 出处:互联网 人气: 评论(
田中久一 金炫澈坑人 金蟾岛复仇记 今日家居李欣 津kb8888 锦州电信影院 禁欲丽装 尽在不言中txt新浪 劲松刘姐 劲舞团魔法花园

来自俄罗斯数据分析公司Empatika的Arseniy Vershinin和他的同事Anton、Valentine一起组队参加编程马拉松,此前,他们从未尝试过iOS游戏开发。但从idea思考到应用成功上架App Store,他们却只用了7天的时间。通过使用Cocos2D及Box2D引擎,成功开发出一款名为Slash Slash的多边形切割游戏。接下来,就让我们一起来看看,他们是如何做到的。


图:Arseniy等开发的iOS游戏 Slash Slash

以下为Arseniy Vershinin在赛后所写下的参赛过程与心得体会:

在慕尼黑早晨6点左右,我和我的同事Anton、Valentine会合,一起为公司的一个编程马拉松思考idea。在此之前,我们所有人都没有任何正式的游戏开发经验,但我们觉得能够开发出一款游戏真的非常酷。因为此前,我们一直在为一些千篇一律的应用项目忙得不可开交,很想尝试做一些新奇的事情。在此次的编程马拉松活动中,我们通过使用2D图形引擎Cocos2D成功地完成了我们的第一款iOS游戏。

如何使用Cocos2D及Box2D来开发一款类水果忍者的iOS游戏?

我们一开始选择是做一个切披萨的游戏,一块让人垂涎欲滴的圆形披萨饼,在限定的时间内将它切割成许多块,就像水果忍者那样。切割的小块披萨我通过使用一些物理引擎进行移动,让游戏看起来不会太无聊。在经过一番研究之后,我们发现通过使用Cocos2D和Box2D,效果非常明显。

随后,我们根据White Widget联合创始人之一Allen Tan的《如何使用Cocos2D及Box2D开发一款类水果忍者的iOS游戏?》教程指南来完成切割及三角算法等所有hardcore。Allen的教程指南主要依赖于PRKit库来实现凸纹理多边形的绘制,及扩展PRFilledPolygon类,以便于它能够提供一些其他功能,比如与Box2D物体保持同步。


尽管开发过程中最困难的一部分已得到解决,但在此之后我们还是遇到了许多未曾预料到的问题。比如在对初始项目做出调整,并进行了一系列的测试之后,我们发现Box2D限制了知名的8个顶点。为了运用到所有的示例代码及提供的库,我们将披萨设计为一个多边形,因为Box2D不允许将一个形状变为许多个弧形(即切割之后所获得的小块披萨形状)。因此,披萨不仅要偏圆形,还要可进行切割的,我们利用一组具有8个顶点的形状来构建它。但却也因此产生了一些细微的纹理问题,因为Allen Tan的教程在物体实现上介绍得非常详细。但是在进入深入开发阶段,我们设法通过为PRFilledPolygon输送一组顶点组成物体边缘来克服这一难题。

切披萨的碎片问题如何解决?

截至目前,一切似乎都非常完美,我们很好地完成了披萨饼的设计,但是到切割时却遇到了一个问题,一方面是当切割的披萨碎片数量达到200时,FPS会自动降低10帧左右,直接导致游戏无法继续进行。另一方面是对琐碎的碎片进行入画,因为切割而四溅的披萨碎片很容易相互碰撞。


这个问题让人头疼却也不难解决。我们进行了碰撞计算的设定,当一块碎片变得非常小时,这块碎片的碰撞计算就会自动关闭。但是游戏设置的修改进程仍然相当缓慢,因为我们想要在实现将细微碎片移除同时,玩家的金币值也要同步增加。为了避免琐碎的碎片在屏幕上疯狂地飞来飞去,我们还要为其设置一定的线性、角度缓冲值。


Valentine负责披萨的绘制,在我们对游戏设置进行开发时,他绘制出了一个非常引人食欲的披萨,而其切割过程也非常地简单、逼真。

切割无死角:简单到极致的多边形切割

然而,我们在测试中却明显地感觉到它并不太自然。我们的设计不是说一定要做到和披萨一模一样。首先需要保证的是切割无死角,因此,我们进行了披萨的重新设计,并且很快完成。通过向每个切片增加一个CCDrawNode及一组顶点,完全实现了多边形切割,此外,我们还为多边形的边缘部分进行塑造。这种效果要远比使用标准的CCDraw方式好得多,而且也更快。


切割操作很简单,因此我们以简单为原则,还设置了一个阻止切割的敌人——红点,以造成干扰。


此外,我们还编写了一个基于世界的级别系统。所有级别的.plist文件及形状描述、纹理规则、敌人位置、级别持续和其他一些参数都是单独存放的。.plists通过使用标准的Objective-C KVC包装游戏对象树。

//...... - (void)setValue:(id)value forKey:(NSString *)key{ if([key isEqualToString:@"position"] && [value isKindOfClass:[NSString class]]){ CGPoint pos = CGPointFromString(value); self.position = pos; } else if([key isEqualToString:@"laserConditions"]){ NSMutableArray *conditions = [NSMutableArray array]; for(NSDictionary *conditionDescription in value){ LaserObstacleCondition *condition = [[LaserObstacleCondition alloc] init]; [condition setValuesForKeysWithDictionary:conditionDescription]; [conditions addObject:condition]; } [super setValue:conditions forKey:key]; } else{ [super setValue:value forKey:key]; } } //...... //Afterawrds the values got set with the dictionary, read from the plist file: [self setValuesForKeysWithDictionary: dictionary];为了充分体现世界级别的系统,我们使用了标准的CCMenu,并加入了CCMenu+Layout(布局)及CCMenuAdvanced(滚动)。在其中,Valentine负责级别设计,而我和Anton则负责编写效果。

对于视觉效果,我们使用了非常酷的CCBlade。至于碎片淡出的部分则采用了PRfilledPolygon的CCLayerRGBA协议,为此,我们将默认的着色程序更改为kCCShader_PositionTexture_uColor。

-(id) initWithPoints:(NSArray *)polygonPoints andTexture:(CCTexture2D *)fillTexture usingTriangulator:(id<PRTriangulator>)polygonTriangulator{ if( (self=[super init])) { //Changing the default shader program to kCCShader_PositionTexture_uColor self.shaderProgram = [[CCShaderCache sharedShaderCache] programForKey:kCCShader_PositionTexture_uColor]; } return self; }并且将颜色统一。//first we configure the color in the color setter: colors[4] = {_displayedColor.r/255., _displayedColor.b/255., _displayedColor.g/255., _displayedOpacity/255.}; //then we pass this color as a uniform to the shader program, where colorLocation = glGetUniformLocation( _shaderProgram.program, "u_color") -(void) draw { //... [_shaderProgram setUniformLocation:colorLocation with4fv:colors count:1]; //... }


分享给小伙伴们:
本文标签:

更多文章

相关文章

Copyright © 2002-2014 版权所有