In this article I want to share with you the story of the creation of the first iOS game in our company and tell you about the experience of using 2d graphics engine - cocos2d. In the story we will go through some technical problems that we had to face during the development of the game, and tell you about the evolution of the gameplay from beginning to end.

In the morning I met with my colleagues Arseny and Valentin to work on the idea for the corporate hackathon, which is held monthly in our company. None of us had more or less serious experience in game development, but we thought it would be cool to develop a game.
Initially, the idea we chose was this: a juicy cake lay in front of the player, which needed to be quickly cut into small pieces in a short amount of time. To make the game dynamic, the cut pieces had to be animated using some kind of physics engine. After a short search, we decided that it would be most productive to make the game on the cocos2d engine (since I and Arseny iOS developers) and box2d (as it is free and works fine with cocos2d), and we limited ourselves to only one iOS platform.
')
The core for the project was found in an excellent
tutorial from Allen Tan , thus we did not have to dive into the implementation of the cutting and triangulation algorithms. The tutorial was based on the PRKit library, which can draw convex textured polygons. It also contained a convenient class PRFilledPolygon, whose subclass connected the physical representation of the polygon with its display. We decided that we would use this subclass as the basis for our future pieces of cake.
Inspired by the fact that the most time consuming part was written for us, we breathed a sigh of relief, but not for long - the first difficulties appeared fairly quickly. After launching the first prototype, we remembered the well-known limitation of box2d - no more than 8 vertices per figure. Based on the tutorial and the aforementioned library, we needed to make the figure of the cake being cut to be a polygon, since box2d does not know how to work with the segments of a circle (which would have been obtained by cutting a round cake). So, taking into account the box2d limitation and the fact that our cake should be close to its real shape, we decided that it would consist of an array of octagons, which ultimately form a figure close to a rounded shape. This decision led to problems with texturing, since the tutorial dealt with bodies that consist of exactly one figure. The problem was solved by passing to the PRFilledPolygon constructor an array of vertices that form only the outer border of the shape. Result:

The original cutting algorithm also needed to be modified to fit bodies consisting of many shapes. After a short discussion, it was decided to simply increase the maximum number of vertices of a figure from 8 to 24 (done by editing the corresponding parameter in box2d settings) and return to the bodies consisting of exactly one figure (for some projects this solution would be unacceptable, but for our purposes it is well suited). Profiling showed that there are no serious differences in the speed of work with eight peaks and 24 x. However, after increasing the number of pieces on the screen to two hundred or more, the FPS dropped sharply to 10, which made it almost impossible to play the game. About 20% of the CPU time was spent on collision counts, the rest on drawing the pieces and their animation.
The decision was not long in coming. As soon as the piece became small enough, we simply turned off the collision miscalculation for it. But still, the speed of the game left much to be desired, which prompted us to decide to slightly change the gameplay: small pieces should be removed from the screen and added to the player’s progress bar. The area of ​​the destroyed surface determined the quality of the passage level. Linear / angular damping was applied to the pieces, which did not allow them to randomly scatter around the screen.

By this time, Valentine created a model of the cake:

The rendered cake looked really impressive, but was too realistic for such a simplified cutting process, which is why we decided to replace it with a simple pizza picture:

However, with our simplified gameplay, pizza also didn’t look very harmonious, which made it possible to use abstract geometric primitives as a graphic base. Since the redesign required for this was quite simple, and the idea perfectly fit the technology used in PRFilledPolygon, we very quickly realized our plans. Each piece was added a stroke, which we implemented using CCDrawNode, passing as an array of vertices of the polygon and the stroke color as parameters. This slowed down the game a bit, but the FPS was still quite high. At the same time, the outlines of the shapes looked much better than those drawn using conventional ccDraw methods.

The game began to take on a more or less complete look, but the gameplay was still in its infancy. Definitely lacked some kind of competitive element. To solve this problem, we added a simple enemy - a red dot, which could not be cut without losing the points necessary to successfully complete the level. Great, but you can do better. What about moving lasers? Made by The implementation was quite simple and was based on the calculation of the distance from the position of the point of contact of the finger to the enemy.

So, the enemies and the main gameplay were ready. After that we decided to implement a system of worlds, each of which was divided into several levels. All levels were stored in separate .plist files that contained the description of the original figure, the position of the enemy, the duration of the level, and other parameters. The tree of game objects was built using standard KVC for Objective-C. For example:
To show the worlds and levels selection menu, we used CCMenu with some extensions:
CCMenu + Layout (allows you to arrange menu items on the grid) and
CCMenuAdvanced (adds scrolling). Valentin started designing levels, and Arseny and I set about implementing effects.
For visual effects, we used
CCBlade , a library that animates the user's touch. In addition, each cut of the figure was voiced by effects, like the sound of a Star Wars laser sword. Another effect we added is the disappearance of small pieces. Cutting without any effect looked pretty boring, so we decided to remove the pieces with a smooth change in transparency and add a “+” above the disappearing figure.
The transparency part was implemented by adding the CCLayerRGBA protocol to the PRFilledPolygon. To do this, we changed the standard shader program used in PRFilledPolygon to kCCShader_PositionTexture_uColor:
-(id) initWithPoints:(NSArray *)polygonPoints andTexture:(CCTexture2D *)fillTexture usingTriangulator: (id<PRTriangulator>) polygonTriangulator{ if( (self=[super init])) {
and handed her color uniform
It looked beautiful, but with the stroke and new effects, the FPS fell to an unplayable mark, especially if the user cut many pieces at once into small pieces. Googling, we did not find a solution and simply increased the minimum area of ​​the pieces to be deleted. This boosted FPS. The effect of the disappearance, we also removed, and the plus signs were added to CCSpriteBatchNode (strangely, they did not do it right away).

For sound effects, we wrote a little wrapper over the Simple audio engine. However, it was not without problems here: we were faced with unsupported .wav file formats, but, fortunately, it was resolved by simply converting files into a supported 8 or 16 bit PCM format. In the other case, the effect either did not play at all, or there was a crackle from the speaker.
After all this, we added to our game store where the user can buy the missing stars to open a new level or world.

He can also get them for free for passing a level or sharing the promotional image of the game on social networks.

By this time, the time allotted for development had come to an end and it was time to send the game to the AppStore. Quickly correcting the last bugs we found, we filled in the binary with the hope that we would go through the review the first time. And, as it turned out, they passed it without any problems.