During the Spring Festival period, three freshmen students from the South China Normal University in Guangzhou, China took their 14 days of winter break to build a game. Together, they completed creating a science fiction mini-game, which has been released online on WeChat, and user satisfaction has been incredible. The game is entirely free, and there is no advertising.
The game tells a science fiction story about the survival of mankind. In the game, you can explore the universe’s infinite space and freely shuttle between dozens of different planets, stars, supernovas, comets, and black holes.
During the period, the main programmer, “HK-SHAO,” also wrote a weekly development log, sharing their work and posted it to the Chinese Cocos forum. This article is taken from their development. We hope the shared technology can help everyone.
Hello everyone, my name is HK-SHAO. With the continuous iteration of the game, the effects and content of the game are gradually improving. The game project and its code have more and more details that need attention.
So I will feature a diary to record some of the methods and principles of game effects that I need to pay attention to during the development process. At the same time, I am very grateful to Cocos for providing us with free development tools for game creation!
Due to the rush of time, the content may be slightly general and have errors. Forgive me.
A brief introduction to TS and Creator
It is precise because of the strong typing of TypeScript that the writing of TypeScript code is not prone to hidden errors because the IDE will give excellent error prompts, which can significantly improve the productivity of the code.
Also, if you use TypeScript to write game scripts, the IDE will prompt code, what types of object, what member variables and methods it has, and the functions of these methods. These IDEs will give prompts during the code writing process, eliminating the frequent search for answers within Cocos Creator official documents.
In Cocos Creator, every entity is a node (cc.Node), and the structure of these nodes is tree-like. I think this design is particularly good, not only for this game engine, but it can also improve the efficiency of particular algorithms, And it can save a lot of effort for game developers.
I want to mention here that the DOM (Document Object Model) of the web page is also tree-shaped in the front-end development. It is precisely because of this data structure’s superiority that the web page can be quickly rendered and updated.
To put it simply, Cocos Creator can package and publish to this platform with one click as long as it can open a browser to access the Internet.
Next, I will list some technical details in game development one by one
Dynamic and physical effects
Non-linear motion effects are much better in visual perception than linear and uniform motion effects. This is widely used in current mobile phone system animations. This game uses a non-linear function to achieve dynamic effects in many aspects to achieve smooth and soft visual effects.
This non-linear function is actually the differential equation y =The solution of y (1 − y ), which is a handy non-linear function and is widely used in various fields.
For example, in “Mainm,” the open source Python mathematical visualization engine, it can be found. Recently, the open-source animation engine movy.js also has its presence. Also, this magical function is also used in high school biological population density, demography, statistics, etc. It is very useful in many fields. Let’s solve this differential equation first.
If the constant C is 0, it can finally be transformed into:
This is actually the famous sigmoid function, which is also widely used in the field of artificial intelligence.
This function curve is S-shaped. It is also called the Logistic function. In the recent epidemic analysis, it also appears in the infectious disease model. Its shape is like this. We can see that its domain is the set of real numbers, the value domain is [0, 1 ], and the change from 0 to 1 is very gentle.
Okay, back to the topic, I frequently used this beautiful function curve in the game development of Cocos Creator to achieve a more pleasing and smooth animation effect.
Its implementation in the program is like this: y ← y ∗ (2 − y). More generally speaking, if I want a value t to change smoothly from min to max, I can write it like this in the update function.
- t += (max-t)*dt*speed;
Conversely, if I want a value t to change smoothly from max to min, I can write it like this in the update function.
- t -= (t-min)*dt*speed;
For example, I used this method to achieve a very smooth camera zoom effect that changes according to the touch.
The distance arrow is automatically displayed according to the distance from the earth to the sun and automatically hidden or displayed according to the touch, which also takes advantage of this feature.
To achieve a smooth visual effect in the game, I have adopted the method of changing the force of the entity in the game to avoid directly changing the speed because the direct change of the speed often occurs at the time of impact and as little as possible in other situations.
For example, controlling the advancement of the earth in the game is to give the earth rigid body a continuous force that changes according to the touch position. Changing the planet’s rotation angle avoids directly changing the earth’s rotation angle but gives a small constant force to the edge of the earth to change the earth’s angular momentum, thereby realizing the change of the earth’s rotation angle.
Also, I avoid the camera and the background directly following the camera, but by giving them the force corresponding to the rigid body, to achieve a sense of misalignment and smooth movement.
The normalization of a vector is the unit vector of this vector. In Cocos Creator, there are two types of vectors, cc.Vec2 and cc.Vec3. Both of them have the normalized method to obtain the unit vector. But sometimes, I want to normalize a real number. What should I do?
Astute readers may have thought of the sigmoid function mentioned above, but in addition, we can use the arctan function to normalize a real number so that its value is between 0 and 1. In fact, this function as an activation function is as widely used in the field of artificial intelligence as sigmoid.
After normalizing a real number, we can easily operate on the number. This method is widely used in graphics, such as Shader programming. I also used this method in the game script to make subsequent calculations and operations more straightforward.
In the game’s main function, there are a large number of operations between vectors to calculate the magnitude and direction of the force. For example, when rotating the earth, it is a very beautiful method to change the earth’s angular momentum by giving a continuous force to the edge of the planet, thereby changing the rotation angle.
Taking a black hole as an example, every celestial body and the earth will form forces of the same size and opposite directions, which conforms to Newton’s third law
In the physics engine, space is set as a weightless environment, and the linear velocity decay of the earth is set to 0, which conforms to Newton’s first law.
The gravitational force between the celestial body and the earth is calculated by Newton’s universal gravitation formula, which conforms to the law of universal gravitation.
In addition, in order to consider the length contraction effect of the particular theory of relativity, when the earth moves at high speed, it will shrink in a direction perpendicular to the speed so that the planet will become an ellipsoid to a certain extent.
Also, all celestial bodies in the game give the earth a force, so the gravitational field in which the planet is located is actually very complicated, which brings challenges to players to a certain extent.
The black hole in the game will have a strong gravitational force much higher than that of other celestial bodies, and the white hole in the game will have a strong repulsion force. Players can take advantage of this and use this feature to achieve some complex and technical operations.
The game’s design has a lot of details, and it is constantly being polished and improved. For example, a black hole will collide if it is sucked into a celestial body, two black holes will collide to form a larger black hole, and the collision of a black hole and a white hole will annihilate both.
The probability that players want to see these effects is low, but I believe that players can perform many interesting operations through these characteristics.
Nuclear bombs can be launched in the game, and these nuclear bombs will automatically find the closest strikeable celestial body and destroy it.
The comet in the game will automatically be destroyed when it hits with a great impulse, and it will also be automatically destroyed when a star or black hole catches it.
Every time the earth hits, the vibration-related API is called to achieve a more realistic effect
The game’s related reward and punishment mechanism are constantly adjusting parameters to achieve better results.
The game makes full use of particles to achieve better visual effects, which is particularly important when generating starry sky, comet tails, and flames.
In terms of visual effects, shaders play a significant role. However, the mobile GPU is terrible, and many shaders will run very poorly. This is a pity. Here I will introduce Cocos Creator’s Materials and Effects.
In Cocos Creator, each material can be bound to a Texture and Effects. Effects is a unique program of Cocos Creator. It contains configuration information, vertex shaders, and fragment shaders, among which the fragment shaders are very powerful.
For example, you can use the shader program to generate a dynamic three-dimensional starry sky:
Use shader to generate a rotating star:
Even a three-dimensional, dynamic black hole:
Or generate a galaxy, etc.:
Game performance optimization
With the continuous iteration of the game, I have achieved more and more effects, and the main logic of the game has become more and more complex. Also, there are more and more entities to be rendered. The frame rate of the game on the mobile terminal has a downward trend (actual Above, the game can run at 200 full frames on the computer web page, but the performance of the mobile terminal is relatively poor, it may be less than 60 frames or slightly dropped frames).
Let’s first look at the frame rate information of the game in debug mode:
Among them, FPS is Frame per Second (frames per second). Generally speaking, a frame rate of about 60 is enough. In fact, Cocos Creator locks the game at about 60 frames. Change the top of the game screen by modifying the program or debugging mode. The configuration can increase the upper limit of the game frame rate.
Now we see that the game is quite smooth. However, the smoothness of the computer does not mean the smoothness of the mobile phones. After some debugging, I found that the frame rate can be above 170, and the mobile phone can be relatively smooth. The picture above also hides a lot of information, which I will list below.
- Frame Time The time it takes for the game to run one frame
- FPS frames per second
- Draw Call The number of packages that the CPU packs and sends to the GPU for rendering
- Game Logic The game processing logic running on the CPU takes time per frame
- Renderer GPU rendering a frame of time required
- Whether to enable WebGL
Frame Time = Game Logic + Renderer, as you can see from the above data. The FPS is inversely proportional to Frame Time, so if we want to increase the game’s frame rate, we must start with Game Logic and Renderer.
Optimize Game Logic
Use cache, an algorithm
In terms of Game Logic, it is actually time-consuming for game scripts to run on the CPU. By caching game objects, automatically destroying useless nodes and mounts, and running scripts on them to improve game logic’s performance.
When the game loads, all necessary serialized objects are loaded and cached in a list.
The node.getComponent method must be called every time a rigid body object is obtained. It is better to cache in advance.
Called methods are cached for subsequent use as much as possible so that there is no need to call methods repeatedly, which significantly improves efficiency.
Also, some other algorithms can also be used to optimize game performance. For example, to detect and act on collisions within a range, you can use the quadtree algorithm (or the octree algorithm if it is three-dimensional).
In addition, for nodes that often appear in the game or need to be generated frequently, use the serialization function of Cocos Creator to serialize this node in advance to generate a Prefab file, and use the cc.instantiate method to reverse it when needed. Serialization is used so that a node object can be obtained more efficiently.
It should be noted that if the prefab needs to be deserialized repeatedly and frequently, the prefab needs to be set as follows:
Using the automatic atlas allows Cocos Creator to pack a series of pictures into a whole picture automatically. The advantage of using the automatic atlas is outstanding!
Compared with smaller images, an entire image has fewer network requests or does not require repeated hard disk reads and writes. From this aspect, using automatic atlases can reduce the pressure on the CPU, hard disk, and network.
More importantly, the use of the entire image allows the GPU to complete the rendering at one time, avoiding the CPU repeatedly calling the GPU for rendering, which can reduce the Draw Call, which significantly affects the rendering efficiency of the game image, so use the automatic atlas Can improve rendering efficiency.
Reduce the number of nodes
Reducing the number of nodes also improves game performance by reducing Draw Call, so when a node is not visible outside the map or is useless, consider automatically destroying the node.
Optimize textures (Materials and Effects)
Each material can mount an Effect, and Effects are plain. Even if the shader is divided into vertex shader and fragment shader, they are programs that run directly on the GPU, which can directly image the image at the GPU level. The operation is very efficient.
Using shaders to achieve effects when appropriate can significantly improve game performance.
However, even though the shader is running very sluggishly, it has to be adequate. The GPU performance of the mobile phone is much lower than that of the computer. Therefore, complex shaders that require a lot of calculations may slow down the rendering speed of the game image and significantly reduce the game performance.
For example, if the following shader is a full-frame on the computer, it will be sluggish on the mobile phone
Finally, I’m delighted to be able to have great cooperation on this project. I hope we can put this project together and continue to improve better.
The game has been released on WeChat.