📜 ⬆️ ⬇️

Cocos2d-x Design Patterns

Hi, Habr! I present to your attention the translation of the article " Design Patterns in Cocos2d-x " by Aleksei Pinchuk.

The article will be interesting for Cocos2d-x developers and those who study patterns. It is made in the form of a brief outline, in which you can quickly see where a particular pattern is applied in Cocos2d-x. The purpose of the article is not a complete description of each pattern.

Generating patterns


Prototype


Prototype defines an object copying interface. Creating a new object occurs by copying the state of the object. For example, if we call clone () on an Animation object, we will create an Animation object with exactly the same parameters.

image
')

Singleton


Yes, laaaadno.

Structural Patterns


Flyweight


Flyweight should be used for separate use of the same resources without creating a large number of instances of the same resource. This makes it possible to effectively use memory. This pattern is well suited for displaying text.

The Label class is used to display text. To display the text we need a font. To get a TTF font, you need to use the FontAtlasCache getFontAtlasTTF method. FontAtlasCache is a pool of all fonts used in the application. The font is stored until at least one object uses it. If we have 10 Label objects with the same font, they will all use the same instance of the FontAtlas class.

image

FontAtlas contains data for displaying the symbol — textures and coordinates. The size of the texture is 512x512 and there may be several such textures, if all the characters do not fit into one. Only those characters that are used by objects that reference this font are created. Label gets the FontLetterDefinition structure for each character from FontAtlas. Based on data from this structure, Label creates a sprite and places it in its BatchNode. In general, we can see how carefully Label is optimized.

image

Another good example of the separate use of resources is the use of textures by sprites. The texture for each uploaded file is stored in a single copy. Several sprites created from the same file, I will refer to the same copy of the texture.

image

We can find some pattern - if the class name ends with Cache, then it produces objects for separate use.

Bridge


Bridge separates abstraction and implementation. This pattern is most often used for the implementation of cross-platform objects. Classic Bridge can be found in EditBox and Downloader.

image

image

Also this pattern is well suited for GLView, AudioEngine, Controller and WebView. However, in them we can see different ways of implementing the same task - the separation of abstraction from implementation.

Composite


The Composite task is to build trees and unify access to the components of the tree. Usually the Composite scheme looks like this:

image

Composite is a composite object consisting of several objects inherited from the Component. Thus, we can perceive several objects as one. In Cocos2d-x, the Node is both Composite and Component.

image

Thanks to Node, a graph is created; each node is a Node.

Behavior patterns


Command


Command encapsulates the request as an object, thereby allowing queuing requests. Other uses will not be considered. In Cocos2d-x, this pattern is used to create a queue for the Renderer. Thanks to this pattern, the use of the OpenGL API inside objects was removed. The same code for OpenGL is displayed in one command and is not copied several times. It can also facilitate the transition to other graphical APIs, but will not make it easy.

image

Observer


Defines a one-to-many relationship between objects. In Cocos2d-x, the subject (subject) is EventDispatcher, and the observer (observer) is EventListener. EventDispatcher is not singleton, we can inherit from it our EventDispatcher. Director via EventDispatcher notifies observers about changes in the state of the accelerometer, mouse, keyboard, etc. You can also create custom EventCustom messages. These messages have a name and data that must be transmitted to the observer. This is an alternative for NotificationCenter which is already marked as deprecated. Director also defines several useful EventCustom, for example, EVENT_BEFORE_UPDATE, EVENT_AFTER_UPDATE, and others. EVENT_BEFORE_UPDATE is convenient to use when working with Box2D. For example, before updating the physical world, change linearVelocity to some object.

image

Connectivity Patterns (Decoupling Patterns)


Component


I think every game developer knows about Component-Based Architecture. Unity3d programmers should know for sure. Such a system reduces the connectivity of components and allows you to add components to an entity in such a way that the entity does not even know about it. This system is in Cocos2d-x. In each Node there is a container for components. You must inherit your components from the Component class. Each component has a link to the Node that it owns (owner), the update method, and the serialize method for processing messages between components and other objects.

image

Optimization patterns


Data locality


The purpose of this pattern is to accelerate memory access using more convenient data placement for processor caching. This pattern is often used to create particles. And in Cocos2d-x, it is also used to create particles. In ParticleSystem, all particle data is stored in ParticleData. ParticleData contains data for all particles. Virtually every member of ParticleData is an array. For example, in the array posx, the coordinates of the particles along the x axis are stored.

class ParticleData { public: float* posx; float* posy; //... }; 

Placing data in memory sequentially, in order to process them, allows them to be processed quickly and to avoid cache misses (cache miss) as much as possible.

Dirty flag


Quite often found in Sosos 2d-x. This pattern postpones the execution of slow work until its result is required. It can be found in the classes Scene, Camera, Node, Label, ParticleSystem, Sprite and many others.

Source: https://habr.com/ru/post/351666/


All Articles