This live stream will go over tips and insights that will help you develop a game engine. I have accumulated these tips throughout the development of my game engine and I'm sharing them with you. Enjoy.
I wanted to write a post describing how easy it is to develop a game with the Untold Engine, the 3D game engine I developed. I wanted to create a simple mini-game that encompasses the features available in the Untold Engine.
For the first game, I decided to develop a game with one character, power-ups, and obstacles. The game design is as follows: the main character must collect all the power-ups. If the character collides with the Obstacles, the game is over. The game is shown below:
Let's go over the steps required to develop such a simple game.
Create the models and scene
I did not create the 3D models myself, (I don't have an artistic eye). Instead, I bought several 3D models from cgtrade. I then assembled the scene in Blender 3D as shown in the image below.
Once I was happy with the game scene, I proceeded to export the 3D models and scene using the Digital Asset Exporter (DAE). The Digital Asset Exporter extracts rendering information from a 3D object and provides the data to the Untold Engine.
The video below shows the 3D models in Blender 3D and the DAE being executed. Once the information is available to the Untold Engine, it is rendered on your iPhone or Mac.
Adding Walking Animation and Motion
I also created a walking animation for the character in Blender 3D. The animation is shown below:
The DAE, aside from exporting rendering information, can also import animation data. So, once the animation was ready, I used the DAE to export animation keyframes into the Untold Engine.
I also enable a controller, such as a gamepad, game controller, mouse, and keyboard, to control the movement of the main character.
As the video shows, I also added motion to the "tree trunks" that serve as obstacles in the game.
Enabling Collision Detection and Particle System
I wanted to create a visual effect whenever the main character eats a power-up. By enabling Collision Detection between the character and the powerup, I can determine whenever a collision between the two objects have occurred. Whenever such collision happens, particle systems are created. Thus, serving as visual cues.
Adding Knock-out Animation
I decided that it would be a good idea to create an additional animation that would execute whenever the Tree-Trunk hits the character. Like with the Walking animation, the Knock-out animation was created in Blender 3D. The animation is shown below.
The animation was exported with the DAE, and it runs whenever the character collides with the tree-trunk, as shown in the video below.
As I was playing around with the game, I realized that it would be a good idea to keep track of the powerups collected by the character.
To add text to the game, I used an app called Glyph Designer. The Untold Engine process the output from the Glyph Designer (.xml and .png files) and renders a text using the font type.
I decided to add a Text Object which displays the current number of powerups eaten.
Aside from that, the game will show a "Game Over" text whenever a tree-trunk hits the game character.
Adding a Skybox
Finally, I was not happy with the black background, so I decided to add a skybox. As you can see in the video, the skybox improves the visuals of the game.
I developed this game in parts throughout several days. However, overall it took less than three hours to develop. The hardest part was finding the right 3D models for the game. However, once I had the models, the Untold Engine made the development of the game easy.
If you are interested in developing a game using the Untold Engine, please visit our website: Untold Engine.
Thanks for reading.
In this version of the game, I implemented a Pathfinder algorithm. As the video below shows, the AI system computes a path towards the goal. Notice how the white jersey player drives the ball towards the goal.
Implementing a Pathfinder algorithm requires knowledge about Graph Theory and the Dijkstra's algorithm. I've heard about these topics, but I wasn't well versed on them. So I decided to spend my weekend reading about them. I did learn a lot. However, as I was about to implement the algorithm, I realized that the Dijkstra's algorithm might not be suitable for soccer.
Let me explain.
In Graph Theory, a graph is composed of nodes and edges, as shown in the figure below:
A node can represent a location. An edge represents a connection. For example, you can go from your Home to the School by taking the path towards the Park. Or by taking the path towards your friend's house and CoffeeHouse.
By scanning the image, you can see that the shortest path from your home to school is towards the park (only takes two connections). However, this route may not be the fastest.
If each edge is given a weight; in this case representing traffic, then the fastest path is the one towards your friend's house. The Dijkstra's algorithm is used for these instances. It analyzes a graph and determines the fastest path between two endpoints.
I figured that I could use the Dijkstra's algorithm in the game. My idea was to compute the path a dribbling player can pursue to reach the goal.
However, the Dijkstra's algorithm works well for static nodes. It does not operate well in a dynamic environment such as in soccer. For example, a path computed at time t=0s will be invalid at time t=1s.
So, instead of using Dijkstra's algorithm, I decided to implement a "Look and Go" algorithm. The algorithm works as follows:
Once a player obtains possession of the ball, the algorithm divides the player's surrounding area into 36 positions. The algorithm then scans each location. If an opposing player is close to the location, the algorithm discards the position.
The algorithm then analyzes the location that would bring the player closer to the goal. The AI system uses this information to move the player towards that direction.
Does this algorithm work? It works quite well as shown in the image below.
As you can see, unlike the Dijkstra's Algorithm, which computes a complete set of paths, the "Look and Go" algorithm analyzes one path at a time and is more suitable for dynamic environments.
The video below shows the latest implementations to the soccer game. In a nutshell, I cleaned up the AI architecture and implemented a Player Indicator.
Implemented modularity to the AI system
This month I focused on cleaning up the AI game architecture. As it turned out I was violating an OOP principle which states that:
A class should have only one responsibility.
In my case, one of the classes was not only responsible for assigning roles to each player, such as the attacker, defender and supporter role. It was also responsible for executing AI algorithms.
To remedy this, I created several classes responsible for AI operations. Specifically, I created an AI class responsible for Defending. And another class responsible for Attacking AI operations.
However, I went further and created an interface for these classes. Doing so provides modularity and flexibility whenever I need to change an AI strategy.
I also implemented methods in the AI to steal the ball from the attacking player. However, it does not know what to do once it gets possession of the ball, yet. I plan to fix this soon.
Added a Player Indicator
In the previous version of the game, it was somewhat hard to follow which player had possession of the ball. To remedy this, I added an indicator which shows who is the dribbling player and what is its heading. The indicator also points out the current defending player.
Improving the Soccer Kits
Finally, I decided to hire a game artist. I was not happy with the soccer kit texture; which was painted by me. He is currently working on the soccer kits, and I like what he has done as of now. Hopefully, by the next version update, I can show you a small video of the game with more realistic soccer kits.
Thanks for reading.
This week was a very productive week for the development of the soccer game. As you can see in the video, I implemented most of the 11 players per team. Currently, I'm missing the goalies.
I improved the performance of the game by disabling shadows and collision detection on all but three players; dribbling player, receiving player and defender. Thus, at any time, the engine only renders a shadow to the player currently dribbling, the player who will get a pass and the defender. The same logic was applied to the collision system. Only three players have collision detection enabled at any time. Doing so improved the performance by 20%.
You may say that doing so will reduce the aesthetics of the game, and you are right. However, when you play a soccer game, your eyes are mainly focused on the controlling player and the defender. Your vision ignores all other players' aesthetics.
I also improved the AI of the game. Supporter players no longer go out of bound whenever they search for a good passing angle. The same logic applies for defenders. They are smart enough not to go out of bound.
Additionally, I added a feature that controls the strength of the kick depending on how long you press the game buttons. The longer you press the buttons, the stronger the pass; thus the farthest the ball will travel.
Implementing the 4-4-2 team formation
Up to now, I have been developing the soccer game with relatively few game characters. The reason was obvious. I was focused on implementing the properties of individual players and not the team properties.
However, this week I focused on implementing intelligence into the team as a whole. My first task was to apply "Formation" logic into the game.
There are several formations used in soccer. I decided to use the 4-4-2 formation. That is four defenders, four midfielders and two forwards.
The idea of a formation is the following:
When the team is in attacking mode, the formation should spread out; thus creating space.
In contrast, when the team is in defending mode, the formation should shrink; reducing space. Notice that no matter the mode, the team should always keep the 4-4-2 structure.
Since at any time, the game characters could be running towards a passing angle or defending positions, it made sense to implement separate game objects that serve as reference points for the players.
These game objects (formation objects) would spread out or come together depending on the state (attacking/defending) of the team. Each player is assigned a formation object and would use the position of the formation object only as a reference. The formation objects are shown as squares in the image below.
Doing so keeps the structure of team compact and resembling a 4-4-2 formation throughout the game.
Thanks for reading.