For you, I have prepared a series of articles about mobile game development, based on the experience gained and the past rake. The first article focuses on creating your own cross-platform engine for mobile games. In truth, not only mobile, and not just games.

Content
Part 1. Mobile cross-platform engine
Part 2.
Rendering UTF-8 text using an SDF fontPart 3.
Rendering drops with transparency and reflections.
Do you need your own engine at all?
Every time another popular engine becomes free or open, I ask myself this question. Let's look at the pros and cons:
pros- You always know how your projects work inside, and most importantly, you can influence their work as you wish. You do not need to storm the developer forums with requests to add the functionality you need or fix old bugs.
- You will be able to independently add support for new platforms and add new third-party SDKs.
- You will be able to use any data storage formats convenient for you (graphics, sounds, resources).
- You are not limited to any licenses.
Minuses')
- You will have to write everything yourself, as well as delve into all the nuances of each platform. This process will take quite a lot of time, so you shouldn’t do it just “for the sake of interest”. Another thing, if you do a game-dev professionally and plan to release quite a lot of games. Practice shows that most game studios sooner or later create their own SDK.
- If you make custom projects, not all customers are happy with your samopisny solutions. After all, it is possible to support the project will have a completely different people.
- Many popular engines have built-in visual 2D / 3D editors. You can argue about their convenience for a long time, but initially you will not have that either.
Of course, everyone will see their own pros and cons. My job is to warn. Go!
What is it made of?
We are talking primarily about the development of mobile games, so the basis will be uniquely on
C ++ / OpenGL . No options! However, without secondary languages, too, can not do. Let's see what is used on each platform:
Platform | The foundation | Wrapper | Graphics |
iOS | C ++ | ObjectiveC or Swift | Opengl |
Android | C ++ (NDK) | Java | Opengl |
Windowsphone | C ++ | C # | OpenGL via Wrapper or DirectX |
tvOS (AppleTV) | C ++ | ObjectiveC or Swift | Opengl |
Osx | C ++ | ObjectiveC or Swift | Opengl |
Linux | C ++ | C ++ | Opengl |
As you can see, C ++ and OpenGL are everywhere. On ObjectiveC / Java / C # you will have to write only a wrapper for working with the system of the device. The very same code of your projects will be the same - in C ++. On this note, we say: "Goodbye, painful porting!".
Opengl
I strongly recommend using OpenGL 2.0 and higher. The time of OpenGL 1.1 is long past, and the transition from 1.x to 2.x will be remembered in nightmares. However, do not rush to use the latest version of OpenGL without making sure that all target platforms support it. In most cases, OpenGL 2.0 is enough and all platforms support it.
C ++
The same situation with C ++ 11/14. If you are sure that all compilers are friends with him - super. I also have C ++ 98, so when adding a new platform - and there are plans to support consoles - I will be calm.
IDE
Xcode - for iOS, OSX, tvOS. Plugins through
CocoaPods .
Android Studio - for Android. Plugins via
Gradle .
Visual Studio is all under Windows.
Engine structure
First of all, the engine and projects should be carefully and logically stored on disk. As a result, I came to this structure:
- Engine (all that concerns the engine)
- Classes (.h, .cpp engine files)
- Modules (modules and third-party SDKs that are not needed in all projects)
- Promotional SDK
- Analytics
- Game center
- Images
- Social networks
- … etc.
- Platforms (platform specific classes)
- Android
- iOS
- Osx
- tvOS
- ... other platforms
- Test project
- iOS
- Project.xcworkspace
- Icons (application icons, * auto - the project builder fills these folders)
- Launch (pictures when starting the application, * auto)
- Res (application resources ready, * auto)
- Pods
- ... other project ios files, plist, build, etc.
- Android, OSX, tvOS ... the same for the meaning of the folder for different platforms and IDE. For Android Studio has its own project structure.
- Assets
- Icons (application icons of all sizes)
- Launch (Lunch Screens of all sizes)
- Resources (originals of project resources)
- General (core resources for all platforms)
- Lang (fonts and localization)
- Fonts (folder with SDF fonts)
- Lang.xls (translation file)
- Platform (platform specific resources)
- iOS
- Android
- ... other platforms
- Shaders (shaders)
- Sounds
- MP3 (for tracks)
- OGG (for sounds)
- Textures (texture format resources)
- Source (.h, .cpp files of the project itself)
- Config (project configuration file for collector)
Project builder
The project builder is responsible for preparing resources, formats, and packaging. Namely:
- Takes icons (or even one icon of maximum size 1024x1024) from Assets / Icons, makes other dimensions (from 16x16 to 1024x1024) and copies to folders by platform [Platform] / Icons
- It also comes with start screens from Assets / Launch
- Takes application resources from the following folders:
- Resources / General
- Resources / Shaders
- Resources / Sounds / MP3, OGG
- Resources / Textures / [desired texture format]
- Resources / Platform / [platform]
- Resources / Lang / Fonts
Next, the collector converts resources, encrypts, packages, and places them in [Platform] / Res.
The most important thing here is the conversion of files by extension. I use such conversions:
- PNG and JPEG are converted to WEBP. General conversion settings (for example, minimum quality) can be made into the Project / Config project settings, or you can specify it directly in the file name.
For example, image ~ q100.png will be compressed with the quality 100 parameter, and image ~ less.png will be compressed without loss of quality.
Presets are also well proven.For example, the 1st preset will be applied to image ~ p1.png , which will flip the image mirror and save with a quality of 90%.
- Text files and shaders (.txt, .vs, .ps) are encrypted in a simple way. Simple protection from curious.
- The localization file Resources / Lang / Lang.xls is parsed by language, encrypted and packaged in a binary format.
- Texture atlases are created on the fly. For example, from a folder named folder ~ atlas, all the pictures will be taken and packed into a single picture + the file with the coordinates will be saved.
- Sounds are converted to OGG format.
- 3D models are converted to the internal format of the engine.
- Files named file.pack are converted from text files to binary files. It is well suited for all sorts of game configs, levels, etc.
In this case, the collector looks at the time of the file change and converts only the changed files, which significantly speeds up its work. Specifically, my collector is written in PHP. Perhaps this is not the best choice, but it was easier for me. In addition, it can potentially be transferred to the server for teamwork.
Formats
I would recommend using these formats:
WEBP for pictures. Hardly for anyone this format will be new. And for those who hear about it for the first time - webp can store a picture without loss of quality as PNG, as well as with loss — like JPEG, but with noticeably better quality, less weight and transparency. Another advantage is the ability to scale pictures on the fly while reading a file. Libwebp is compiled for all platforms without problems.
OGG for sounds. Android natively understands the OGG format, and on iOS / OSX / tvOS I use the
Tremor library (fixed-point version of the Ogg Vorbis) to decode WAV sounds and feed them to OpenAL. Attempts to use OpenAL and on Android were not crowned with success (the sounds were delayed).
Classes and modules
Let us examine in more detail what classes the engine contains and why modules are needed?
The rule “what to make in the module, and what in the engine?” Is very simple:
Following this rule, I distributed the classes as follows:
Engine
- Work with the platform. Here the application is initialized, as well as the transfer of external events (pause, touchscreen, buttons) to the main engine class.
- Main class. Here the mainloop is spinning, incoming events are processed (already in a universal form independent of the platform), flows and background tasks are managed.
- Work with 2D. Display images, atlases, post-effects.
- Work with 3D models. Loading models, rendering, managing shaders.
- Standard UI elements. Windows, buttons, scrolling, notifications.
- Textures. Loading and unloading textures. The decoders themselves are in modules.
- Text output, rendering SDF fonts.
- Maths. All sorts of formulas, matrices, quaternions, etc.
- Social Sending letters, standard sharing, rate me. Themselves soc. Networks are rendered into modules.
- Reading / writing files.
- Work with UTF8 strings.
- Work with the network.
- Music / Sounds.
Modules
- Social
- Facebook
- Google Plus
- Twitter
- VK
- Replay Kit (screen recording for iOS)
- Json / xml
- Picture Decoders
- In-apps (internal payments)
- Game Center, Google Play Services
- Crashlytics (track crash)
- Branch (deep links)
- Analytics
- Google Analytics
- Game Analytics
- Flurry
- Advertising
Appodeal ( UPD Unfair Company)- Chartboost
- Fyber
- Adcolony
- Unityity
- Tapjoy
- Google Ads
- Heyzap
- Adtoap
In the following articles I will focus on specific classes and modules, with examples and usefulness. I want to pay special attention to rendering the SDF fonts (Signed Distance Field) and shaders in the game from the header.