In my article I would like to share the technical part of the game, which was made by two people. The main architectural patterns (design patterns) and techniques, additional libraries, porting features when working with the cocos2dx engine will be considered. The source code is
here .

The game is called Beaver time. My sister was responsible for the design. Development was conducted on the cocos2dx engine, in the c ++ language.
Gameplay
Based on the mechanics of the game Tetris. Added destruction of identical squares horizontally and vertically (4 in a row), a variety of spells, abilities of the player, different winning conditions, different unpleasant moments to complicate the game and square-bosses.
')
Architecture
MVCThe main template used in the game code is MVC (
described in Wikipedia ,
Apple documentation ). A template consists of three parts: a model, a view, and a controller. The controller mediates between the model and the view. Moreover, each of its parts has its own duties. As an example, you can give the implementation of the game board (game world):
1) Model. The following main game entities were highlighted: a square, a detail from squares. The game also has a game board (
GameBoardViewDataSource ), where coordinates correspond to each cell (for example (1, 1), (32, 48)). The board is a collection of squares. However, it is a data model. The detail is essentially a small board.
2) Controller. The game board controller (
GameBoardController ) decides when to draw a model. He does not know the internal structure of the model (array, linked list). He knows only the number of cells and how to get information about each cell. In the context of cocos2dx, this is the heir of the Node class.
3) Submission (Sprite). The representation draws squares (the rendering code) without knowing anything about their data structure. In the context of cocos2dx, this is the Sprite class. The controller contains a collection of sprites, which gives data for drawing (textures, positions).
When developing the game, passive MVC was mainly used - the controller itself takes data from the model when necessary.
The game has a main controller (
GameWorldController ), which instructs the game board controller and animation controller to update its states. In addition, he still updates the state of gaming systems:
1) Win-lose system (
WinGameSystem ) - decides when the player won, and when he lost.
2) The system of game events - decides when you need to run a malicious event (speed up the game, throw off a couple of unnecessary details).
3) The system of game logic (
TetrisLogicSystem ) - whether the row of squares, 4 identical squares is assembled vertically or horizontally.
4) Spell System (
SpellRechargeSystem ) - monitors spell states.
5) The control system of the current player details (
CurrentDetailController ) - control the detail, lowering it down one step, etc.
6) The system for tracking the status of bosses.
For each element of the gameplay has its own system. The animation controller consists of separate controllers for each system. They are based on the Action class and its subclasses. Usually some kind of event should occur after the animation (increase in points, delete the bottom row, etc.), so the systems send callback functions to the controllers, for example, lambdas in c ++ 11. This is an example of using active MVC - the model itself calls the controller when necessary.
The advantage of such a system is flexibility, because To add a new gameplay element, you just need to add a new system and possibly an animation controller. Minus in its complexity and in the amount of code for its implementation. Sometimes there are implicit dependencies between systems due to their update order.
Single motherIn the development of the game is also often used template Singleton (
ServiceLocator ). In the source code, this is not pure Singleton, but simply a global variable hidden by access methods. In fact, it was a container for models. For example, when a player selects a level on the map, the loader (
GameLogicLoader ) loads the necessary models (data for the current level, system) into this container. And then the controllers get the necessary models from it. It would be possible to make models directly in controllers, but this would cause additional dependencies.
FactoryThe Factory pattern was often used (Factory Method) There are 7 scenes (Screens) in the game and a factory was made for each screen that loads the necessary models and collects a scene graph from the controllers. For example, the class
LoadingGameSceneFactory .
ObserverThe Observer pattern was also used. In a scene where there are hidden items that are shown on a specific event (pop-up windows), an object is created, and observers (pop-up windows) are signed to it for certain messages. Then, when an event occurs, a notification is sent to this object, then the object sends a notification to the necessary observers and pop-up windows are shown. For example, the class
RegulateSoundPopUp, when initialized, subscribes to messages from GamePopUpsController.
StrategyAlso used the Strategy template. For example, different bosses have different behaviors: some do nothing, others escape from danger. To implement their behavior was used a set of strategies. A collection of strategies is created and populated with the necessary ones. By adding different strategies, we add different behaviors to the boss. For example, the
AIMovementStrategy class is one of the strategies that adds the ability to move the boss.
Additional libraries.To collect player statistics, it was decided to use google analytics. There is a google analytics sdk for ios and android, but there was no implementation for windows. After reading the sdk documentation, it was decided to use the
Google Analytics Measurement Protocol . An example (
GATrackerpp ) of using such a protocol was found on the Internet using the curl library. The result was a cross-platform implementation of sending analytics. However, to send information you need a unique player identifier according to the standard GUID. I also found a library for cross-platform generation of GUID-identifiers (crossguid). But in the end, for android, it was decided to use one GUID for all, as did not understand with connection with ++ to java.
To parse the xml-files with the level settings, it was decided to use the
pugiXML cross-platform parser. This is a DOM parser, which was chosen because it did not need to parse large files and was advised on the cocos2dx forum.
Features of porting.
At the beginning, development was carried out for windows, a regular window application. Then a port for windows store was made - on windowsRT. Then a version for android was made. To organize a cross-platform project, a branch system in git was chosen. For each platform, a separate branch is created. The main error was that the code base of the branches is slightly different, i.e. There is no single kernel, as for example in the
cocos2dx repository. Later, I learned that it would be possible to initially use the preprocessor with ++, while encapsulating the preprocessor commands into factory classes (the Factory template). But the branches were still useful, because different platforms have different graphics and interface elements positions. In this case, all the code for android was initially tested and debugged under windows, and then it was built for android.
Another important point was finding the path to save files in the file system of different platforms, as well as archiving the apk-file in android.
Sound formats did not cause problems - mp3 was used for all platforms.
Oddities during development:1) In one class, the post-increment (i ++) was not compiled, it was necessary to do a pre-increment (++ i) - in the version for android.
2) The engine did not support the path with the Cyrillic alphabet. If the windows username is written in Russian, the game will cause an error and will not start.
3) Once it turned out that the sound does not work, because the implementation of the method is not in the engine. I had to use another class.
Results:In conclusion, I would like to mention the main templates that were used: MVC, Factory, Single, Observer, Strategy. The main additional libraries were curl and pugiXML. It took six months to develop the game. Of them:
- 2-3 weeks thinking through the mechanics and writing technical specifications,
- a month of thinking through the architecture and writing the model classes,
- a month for building the engine and writing classes for drawing and animation,
- month to test and adjust the balance of the game,
- 2-3 weeks for porting for WindowsRT (game in full screen)
- 2-3 weeks for porting to android (setting up the environment for building the project, testing on the simulator).
The source code of the entire project can be viewed
here , the project on windows with filters (directories for source files)
here .
In the end, I released my game and got a lot of experience and pleasure when working on a project.
Thank you all for your attention.