Should you develop a game engine or a game?

As someone who developed a 3D game engine from scratch, you may want to listen to what I have to say.

If your goal is to learn what makes a game engine tick, then go ahead and develop an engine. It is the best thing you can do. I guarantee you that you will become an expert in computer graphics, OpenGL, Linear Algebra, and computational geometry algorithms.

However, developing a game engine is an INSANELY complicated task. It took me about four years to develop the basic framework of the engine. That's right. Just to develop the basic framework of a 3D game engine took that long. By "Basic" I mean that the engine has a collision detection system, a physics engine, rendering engine, animation system, a Digital Asset importer, etc.

To test the features of the engine, I decided to develop a full blown soccer game. It is still a work in progress. Here is a video of the latest game update:

 
 

Here is another video that showcases what the engine can currently do:

 
 

And here is one of the very first demos showcasing the basic framework:

 
 

All in all, it has taken me about four years to develop the engine. However, the engine is not complete yet. There are bugs and issues with it. As I work on the soccer game, I'm finding more and more issues.

An engine requires a lot of maintenance and time; time that could be better spent developing your game instead. Thus, if you just want to develop a game, use an existing game engine instead.

You may be curious how a game engine works. If that is the case, I wrote several articles on game engine development that should give you a pretty good idea how it works.

How does a game engine works?

How does a rendering engine works?

How does a physics engine works?

And if you are interested, you can get a copy of my eBook: Components of a Game Engine

Enjoy

How I managed to develop a game engine?

Recently I was analyzing how I was able to develop a game engine. It was a complex project which took approximately 15,330 hours. All in all, the basic framework of the engine took about three years to complete. So, how was I able to complete such enormous task?

I turned coding into a habit

Developing a game, app or a game engine can turn into a chaotic process if you don't break it down into simple tasks. And it can become overwhelming if you try to code things all at once. For example, the hardest part of a game engine is developing the physics engine. There are so many moving parts in a physics engine that can overwhelm anyone.

I manage this complex project by doing the following: For a particular feature of the engine, I would write down which Class I should implement. Then, I would write down all the methods/functions necessary for the Class. Then, instead of saying: "Today, I will implement Class X," I would instead focus on implementing ONLY one method/function a day. The key here is that I trained my brain to code every day. Even if I coded for only 15 mins, I still showed up to code every day.

By the second year of development, coding had become a lifestyle for me; just like working out and eating healthy is to me. The day I didn't code, it felt awkward. And I would find myself coding even if I wasn't planning to do so.

I used pen and paper before coding

I learned that using pen and paper before coding can save you hours of development. The first iteration of the engine was a total mess. I ended up throwing it into the trash can. The second time around, I started sketching the game engine operations, methods, classes on paper way before I started to code.

Nowadays, if I'm about to implement a method/function, I usually draw a sketch of its operation and how it may affect other parts of the engine. Having a sketch of what you are about to implement not only saves you hours of work, but it can help you avoid bugs which you may be introducing into your app unconsciously.

I used the power of visualization

You may think this is crazy, but trust me, it works. Visualizing the finish line is the most useful thing if you want to achieve your goals.

It took me about a year to implement the Collision Detection System of the engine. As I implemented the collision detection features, I would visualize the features working way before they were completed. For example, instead of me saying, "I'm implementing the GJK algorithm" I would say to myself "I'm DONE implementing the GJK algorithm" and I would visualize 3D objects colliding on the screen.

Call me crazy, but for some reason visualizing the finish line way before you cross it is a powerful tool. It worked for me, who knows it may also work for you.

Hope these tips can be of use to you.

Game Engine Beta v0.0.4

It has been a month and a half since I gave you an update on the engine. I have been very busy implementing new features and fixing several bugs with the engine. Some of the new features are shown in the video below:

 
 

Improvements

One of the major features that I implemented in v0.0.4 is a particle system. To be honest, the particle system is very primitive. I am still learning how to create several particle effects, so expect more effects soon. As you can see from the video, I was able to implement a "kind of" explosion effect.

I also implemented collision filters. Collision filters are useful whenever you want a particular type of objects to collide with one another but not with any other kind. For example, object A and object B can collide; object A and object C can collide, but any collision between object B and object C is ignored.

A minor detail which I had ignored all along was to enable multi-touch in the engine.

Issues

While developing the second game demo, I started noticing glitches with the OpenGL manager. With a particular type of objects, the OpenGL manager would spit out an error. This issue was hard to detect, and it took me quite a few weeks to find it. I thought I had fixed the bug, but as I was developing this beta version, the OpenGL manager complained again (once). The problem with this bug is that it is intermittent and very hard to reproduce.

I'm considering porting the engine to work with the Apple Graphics API, Metal. However, I'm still weighing the pros and cons of using OpenGL vs. Metal. One thing I have noticed is that Metal is a lot easier to work with than OpenGL, but that is just my opinion.

Thanks for reading

Algorithms in Game Engine Development

For a game character to experience physics, a game engine needs to compute the equations of motion, collision, contact points, etc. There is a set of basic algorithms that aids a character experience such effects. For example, the Runge-Kutta Method computes the Equations of Motion using numerical integration methods. The Gilbert-Johnson-Keerthi (GJK) algorithm detects collision using the Minkowski Difference. The Sutherland-Hodgman algorithm identifies collision contact points by clipping a polygon.

Numerical Integration Methods

Calculating the equations of motion allows a character to fall as if gravity was acting on the object. The Equations of Motion are Newton's Second Law:

and Rotational Force:

A game engine integrates the Equations of Motion to obtain the velocity and displacement of a character. The engine does this operation in a continuous loop which consists of the following steps:

  1. Identify all forces and moments acting on the object.
  2. Take the vector sum of all forces and moments.
  3. Solve the equation of motion for linear and angular acceleration.
  4. Integrate the acceleration with respect to time to find the linear and angular velocity.
  5. Integrate the velocity with respect to time to find the linear and angular displacement.

If a character experiences gravitational and torque forces, the continuous loop creates the illusion that an object falls and rotates.

The problem is the Integration of the acceleration and velocity. Computers can only approximate the value of an integral by using Numerical Integration techniques.

There are three numerical integration methods used in game engine development. They are:

  • Euler Method
  • Verlet Method
  • Runge-Kutta Method

The Euler's Method calculates the velocity at a time interval and predicts the next velocity at t+∆t. The method is simple to implement yet it is the least accurate.The illustration below shows the shortcoming of this approach. You can argue that making ∆t smaller, the closer you'll get to the exact solution. However, there is a practical limit as to how small a time step you can take.

The Runge-Kutta Method is a numerical integration technique which provides a better approximation to the equation of motion. Unlike the Euler's Method, which calculates one slope at an interval, the Runge-Kutta calculates four different slopes and uses them as weighted averages.

These slopes are commonly referred as k1, k2, k3 and k4, and an engine needs to compute them at every time step.

The Runga-Kutta uses these slopes as weighted average to better approximate the actual slope, velocity, of the object. The position of the object is then calculated using this new slope.

Collision Detection

Detecting collisions has trade-offs. A simple collision detection system is fast but unprecise. Whereas, a complex collision detection system is precise but very computationally expensive.

During collision detection, an engine bounds a game character with a geometrical volume. This volume is known as a Boundary Volume. And the most common are:

  • Sphere
  • OBB
  • AABB
  • Convex Hull

A collision detection system works by detecting if boundary volumes are intersecting. A system that uses Spherical Boundary Volumes are fast but returns many false detections.

Back in the 1980s, I'm sure a detection system using spherical boundary volumes was acceptable, but nowadays, gamers may not be so happy with many false detections.

A more precise detection system uses Convex Hulls as boundary volumes.

The intersection between Convex Hulls is computed using the Gilbert-Johnson-Keerthi (GJK) algorithm. Surprisingly, the mathematics behind this algorithm is quite simple. The algorithm determines if the volumes have intersected if their Minkowski Difference contains the origin point. The image below illustrates two convex hulls intersecting (left). Since the Minkowski Difference (right) includes the origin point, the algorithm reports the intersection.

Even though the mathematics behind the GJK algorithm is simple, it is very computationally expensive.

A collision system circumvents calling the GJK algorithm for every possible collision through a Two-Phase Detection System. These phases are known as Broad-Phase and Narrow Phase detection.

A Broad Phase detection system detects collision using spherical boundary volumes. This phase is fast and reports any possible collision to the Narrow Phase. The Narrow Phase tests the reported collision, but it uses the more expensive and precise GJK algorithm.

To further minimize calls to the GJK algorithm, a game engine parses the space of game characters and creates a tree-like structure known as a Boundary Volume Hierarchy (BVH).

The BVH algorithm parses the position of every object and assigns them to a particular node in the binary tree. The algorithm recursively analyzes each node until each node contains two characters most likely to collide.

Collision Response

A collision detection system reports if a collision has occurred. Unfortunately, it does not report the Contact-Manifold (contact points) of the collision. The contact-manifold are essential to determine the Collision Response (impulse and resulting velocities) of collided characters.

A game engine uses the Sutherland-Hodgman Algorithm to compute the contact manifolds of two colliding characters. The algorithm starts off by identifying a Reference and an Incident polygon.

The segments of the reference polygon serve as Reference Planes for the algorithm.

Once a reference polygon is identified, the algorithm tests each vertex of the incident polygon against each reference plane by using a Clipping rule.

Upon termination, the algorithm generates a new polygon whose vertices are the contact points (Contact Manifold) of two collided polygons.

Visualizing Game Engine Algorithms

Now that you know these game engine algorithms, you may want to know how to implement them. Several books go straight into the implementations of these algorithms without giving you a visual depiction of how they work. I think that if you can see a visual representation of an algorithm, you can implement them easier and faster. Thus, I wrote several posts where I provide a visual explanation for each algorithm. I hope they are helpful:

Enjoy.

PS. Sign up to my newsletter and get Game Engine development tips.

Game Engine Second Game Demo

To showcase the changes made in beta version v0.0.3, I decided to make a simple shooting game. Initially, the game was going to be a battle between tanks (see screenshots below). However, as I modeled the 3D game assets, it occurred to me to add an airplane and an anti-aircraft gun.

 
 
 
 

The final game demo ended up being a battle between the tank, aircraft and the anti-aircraft . Below is a video showcasing the game.

 
 

The game demo makes use of the camera rotation. The camera follows the anti-aircraft view direction, thus creating the illusion that the player is controlling the anti-aircraft gun.

The demo also makes use of the collision-detection system and scenegraph. The tank, airplane and anti-aircraft are composed of children game objects. For example, the tank is made of the tank head and the tank base. When a bullet hits the tank, the engine detects the collision. The game disassociates the tank children thus causing the tank head to move up. The same idea is implemented for the airplane.

So what is next?

I found several issues with the engine. The main issue is an occasional crash of the engine during gameplay. It seems to happen in the OpenGL Manager. I will also add several features to the engine such as graphical effects showing an explosion.

Hope to showcase these changes next year :)