Dev Story of our first iOS game

12
In this article I would like to share with you the story of creating our company’s first iOS game and the experience of using a wonderful 2d graphics engine Cocos2d . It covers some technical problems we’ve bumped into, while developing the game, as well as the process of creating the actual gameplay. The resulting app can be found here It was about 6 o'clock in the morning in Munich, when we met with my colleagues Anton and Valentine to work out an idea for an insidecompany hackathon, which has kind of turned into a monthly event in our company. None of us had had an experience with any serious game development, but we thought, it would be kind of cool to develop a game, since we were all tied up in the regular app projects for so long and wanted to try something new and exciting. The initial idea we chose was a pie slicer game, where you had a nice round piece of pie, which you had to vigorously cut into small pieces in a limited amount of time. The pieces were to be me moved with the power of some kind of a physics engine, so it all wouldn't look too boring. After some research and poking around, we found out, that we would be most productive with cocos2d (since Anton I are both iOSDevs) and box2d (since it's free and plays nicely with

Transcript of Dev Story of our first iOS game

Page 1: Dev Story of our first iOS game

In this article I would like to share with you the story of creating our company’s first iOSgame and the experience of using a wonderful 2d graphics engine Cocos2d. It covers sometechnical problems we’ve bumped into, while developing the game, as well as the process ofcreating the actual gameplay. The resulting app can be found here

It was about 6 o'clock in the morning in Munich, when we met with my colleagues Anton andValentine to work out an idea for an inside­company hackathon, which has kind of turned into amonthly event in our company. None of us had had an experience with any serious gamedevelopment, but we thought, it would be kind of cool to develop a game, since we were all tiedup in the regular app projects for so long and wanted to try something new and exciting.

The initial idea we chose was a pie slicer game, where you had a nice round piece of pie, whichyou had to vigorously cut into small pieces in a limited amount of time. The pieces were to be memoved with the power of some kind of a physics engine, so it all wouldn't look too boring. Aftersome research and poking around, we found out, that we would be most productive withcocos2d (since Anton I are both iOS­Devs) and box2d (since it's free and plays nicely with

Page 2: Dev Story of our first iOS game

cocos2d), and if we would limit ourselves only to the iOS platform.

The core for the project was found in the nice tutorial by Allen Tan(http://www.raywenderlich.com/14302/how­to­make­a­game­like­fruit­ninja­with­box2d­and­cocos2d­part­1), so we didn't have to go all hardcore on the implementation of cutting andtriangulation algorithms. The tutorial relies on the PRKit library(https://github.com/asinesio/cocos2d­PRKit), which allows drawing of a convex textured polygonand extends its PRFilledPolygon class in order to provide some additional functionality likesynching with the box2d's physical body. We decided to borrow this extended class to build ourimplementation on top of it.

In spite of the hardest part already being written for us, the first complications came soon. Afterthe inital project setup and a couple of test runs we found out about the famous 8 vertices perbody limitation of box2d. In order to use the example code and the provided libraries, the pie hadto be a polygon, because box2d doesn't allow a shape to be a segment of a circle (which wewould get after cutting the initial shape into multiple pieces). So since the pie had to be at leastrelatively round and cuttable at the same time, we had to compose it from an array of 8­verticedshapes. It created some minor texturing problems, since the initial tutorial only went in detailabout the implementation of such for the whole bodies. However, after some fiddling, wemanaged to overcome this difficulty by feeding the PRFilledPolygon an array of vertices,composing the outer body edge.

Everything seemed to be fine and dandy so far ­ our pie was floating in 0 gravity in theunpromising blackness of the iPad screen:

Page 3: Dev Story of our first iOS game

However the initial cutting algorithm for sprites had to be modified to support the bodiescomposed from multiple shapes. After some thinking we decided to overcome this difficulty bysimply increasing the 8­vertices per shape limit of the box2d. So we bumped up that number to24 vertices (which would be definitely too crazy for any relatively serious project). The profilingshowed, that in our use case it didn't make a huge difference, whether the pieces werecomposed of 8 or 24 vertices. However there was another problem: when the amount ofsmall­cut pieces was close to 200, the FPS dropped to about 10 frames, and made it prettymuch impossible to play the game. Part of that was calculation of the collisions (about 20% ofthe processor time) and another part was drawing and animating all the mini­pieces, bumpinginto each other after each cut.

The decision came quickly. As soon as a piece turned small enough, we turned off the collisionscalculation for it. The game was still pretty slow, which pushed us to slightly change thegameplay: the small pieces were to be removed from the screen and added to the payer's "jar".The size of the cleared area determined the performance of the player. Some degree of linearand angular damping were also applied to the pieces, so they wouldn't fly around the screen in a

Page 4: Dev Story of our first iOS game

crazy manner:

By this time Valentine had drawn a nice­looking pie picture. It looked awesome but seemed torealistic for such an oversimplified cutting process. So we decided to change it to a simplydrawn pizza (the credit for the textures goes to their original rights owners):

Page 5: Dev Story of our first iOS game

However it also felt too unnatural, and at this point it was clear that the design had to be changedto something not as realistic as a pie or a pizza. Cutting of simple geometrical primitivesseemed like the way to go. Since the redesign was easy and played nicely with the chosentechnology (PRFilledPolygon basically allowed to do exactly that), we implemented it prettyquickly. Every cut polygon was also stroked, which was done by adding a CCDrawNode to eachslice and feeding it an array of vertices, shaping the outer body of the polygon. It turned out to bepretty slow, but still faster and nicer­looking than using the standard ccDraw methods:

Page 6: Dev Story of our first iOS game

The game started to take the right direction, but the gameplay wasn't quite there yet. It definitelylacked some challenge. And what makes a better challenge than some obstacles and enemies?So we introduced a simple enemy ­ a red dot, that would interfere with cutting of the primitive.Good, but it could be better. How about some moving lasers? Done. The implementation wassimple and only involved calculation of the point­line distance to the user's touch point.

Page 7: Dev Story of our first iOS game

With the game design and enemies down, we wrote a world­based level system. All the levelswere stored in separate .plist files and described the shape, texturing rules, enemies positions,level duration and some other parameters. The game­objects tree was populated from the .plistsusing the standard Objective­C KVC. For example:

<code>//......­ (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)

Page 8: Dev Story of our first iOS game

LaserObstacleCondition *condition = [[[LaserObstacleCondition alloc] init] autorelease]; [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];

</code>

To represent the world­level system, we used the standard CCMenu with some additions to it:CCMenu+Layout (http://tonyngo.net/2011/11/ccmenu­grid­layout­2/ ­ lets you layout the items ina grid with a proper padding) and CCMenuAdvanced(https://github.com/psineur/CCMenuAdvanced ­ has a scroll addition to it). So Valentine got busywith the level design, and Anton and I took off to write some effects.

For the visual effects part we gladly borrowed CCBlade (https://github.com/hiepnd/CCBlade),which animates the user's touches, and powered it with some cool Star Wars­like sounds. Theother effect was disappearing of the small pieces. Cutting them without any interface feedbackwas too boring, so we decided to make them fade out with a small plus sign over them.

The fade out part involved adopting the CCLayerRGBA protocol by the PRfilledPolygon. To dothat we changed the default shader programm to kCCShader_PositionTexture_uColor:

<code>­(id) initWithPoints:(NSArray *)polygonPoints andTexture:(CCTexture2D *)fillTextureusingTriangulator: (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;</code>

Page 9: Dev Story of our first iOS game

and passed the color uniform to it:

<code>//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]; //...</code>

It looked kind of nice, but with the stroke and the other effects the FPS dropped pretty low,especially when cutting through a bulk of pieces, which involved a lot of animations. A quickgoogling didn't really give us anything, and we decided to move on by simply increasing theminimum area of the piece, that could be still present on the screen. It allowed a smaller amountof pieces to be simultaneously drawn and animated, which boosted the FPS. The fade out effectwas also removed, and all the plus sign sprites were moved into a batch node (which was dumbof us not to use in the first place):

Page 10: Dev Story of our first iOS game

The sound effects were done by writing a small convenience wrapper around the Simple audioengine. While implementing it, we bumped into the format problem: the .wav files we used, hadto be converted into 8 or 16 bit PCM. In the other case they either wouldn’t be played at all orplayed with some noticeable cracking sound.

After all of that done we finally implemented the shop, where a user could buy stars if he/shehadn't earned enough of them, while pacing through the game worlds, or share a picture in oneof the social networks to get the stars for free:

Page 11: Dev Story of our first iOS game
Page 12: Dev Story of our first iOS game

At this point the competition's time pressure was starting to get high and it was time to releasethe game to the public. Frantically fixing some late­found bugs, we uploaded the binary to the appstore in the hopes of it passing its first review.

Once again, the resulting app can be found here

Author: Arseniy Vershinin