Today I’ve added the final touch to the basic engine components including some extra debugging information like rendering the hierarchy of the scenegraph on the screen and a few tweaks here and there. The engine is now at a state were I can start coding some gameplay elements and slowly evolving the physics and the AI.
Physics
When it comes to game physics it all comes down to one thing: how physical forces alter the state of an object. This might be the gravity pulling things down, the way the player moves around, the trajectory that a particle from an explosion follows or what happens when an object falls onto another one.
When some objects are drawn on the screen, they are just a static picture. Moving them around in an either realistic or fun way is a key element for the game to have a good feel. While everything in the engine up to now was about software design and programming, when it comes to making the game objects behave in whatever way, classical physics and calculus come into play. For many might be a pain but for me this is exactly the whole magic in games programming: with a few lines of well planned code I’m giving life and character to otherwise a set of vertex bytes sitting in the memory.
In classical physics everything is about forces. How exactly an object will behave when a force is applied on it? This is when physics equations and calculus come into play. At least that’s the theory; but how to efficiently represent this on a computer is something even more challenging.
An object needs to keep track of its current state which includes, at the simplest case, position, rotation, mass, velocity and the forces currently applied on it. It can get really complex for more realistic behaviours but for the scope of this game I won’t probably need something more.
At first an object is static - its velocity and acceleration are 0, that is. When a force is applied on the object, by performing some integration we can calculate the actual values of the acceleration (which is force over mass) and the velocity (which is the acceleration for the current elapsed amount of time). Then we apply this velocity to the object’s position, in effect moving the object by some distance towards some direction. In other words it’s like pushing a cup on your desk and depending on the power you put and the direction you push it to, it will move accordingly. Then… why it stops? That’s another issue and it’s called friction which is it self just another force. Nature knows all about these stuff; computers know nothing. That’s why we have to code them in.
Gravity is just a constant force pulling objects “down”. That means that for every object in the game we constantly apply a downwards acceleration representing the gravity. While in real world this value is the famous 9.8 meters per second squared, in a game this value can be different. (If games followed physics precisely, when you shoot a laser from your spaceship or your laser gun, you wouldn’t even have a chance to see the actual beam coming out.) Everything sounds piece of cake: we apply the gravity acceleration on the object by using the above algorithm and we’re done right? Well… what happens when that object touches earth?
In the real world we all know the result: probably a hole in the ground or it might bounce up again if it’s a football. In a computer it’s a bit more magical; it would go straight through it. That’s because the computer has no idea about what to do. Making a computer properly interpret this situation is one of the most challenging aspects in computing: collision detection and response.
Detecting when an object’s surface touches with another object (collision detection) is one thing. Then calculating the exact resulting forces for the two (or more) objects involved (collision response) can get quite hard too. But having to describe all these through a computer language’s restrictions is the main challenge. When the screen will be full of thousands of objects flying around, this poor computer has to check each of these objects against eachother. Reducing the number of objects to be checked by logically, geometrically or mathematically excluding some impossible cases is of great importance. An example is separating the game world into many regions. Objects from one region can only interact with objects in the same region. Similar techniques are applied to make things more efficient.
But what exactly means that “two objects come in contact”? In the natural world we can use our brain to know when this is happening. In the computer world we have to break down the object’s structure to some simple shapes that we can actually geometrically compare against. This is usually cubes, spheres or other simple geometric objects. Breaking down a complex object into smaller objects can also get really hard.
How about the collision response then? Once again, classical physics come the rescue. The equations for these situations are well known for centuries. The problem is that in many cases they are very demanding in computational power and therefore we need to use simplifications.
Last but not least, there are physics for water waves, particles (explosions, snow, fire) and other situations, each with its own unique problems and implementation techniques.
All the above might be giving you nightmares already. That’s only the theory though. In practise getting all these done in a computer is… much harder than it sounds. That’s because all that data have to be maintained in nice structures that can communicate easily and efficiently to eachother. That’s exactly where my engine’s design pays off. I could get the outcome I currently have on the screen (a terrain and a box) with about 20 lines of code. Instead my engine contains 80 files already and many thousands of lines of code.
With the current design, the World (which is actually the root of the scene) runs through every object in the game world and applies the required physics on it. Except for automatically applying the required forces to the object (including gravity) it checks for any collisions between them and takes action if required. If the collision detection algorithm finds that two objects have collided, will trigger a callback function that will handle that very collision. In simple words it’s the “nature” of the real world.
AI (Artificial Intelligence) / Game logic
Having a way to move objects around is an excellent start. But there is another important question. Who’s actually moving them? Except from the gravity, there is no other way that our objects would move. And even if they were to move, we would like them to move in a logical way, complying with our expectations - at least the ones we have for the game we’re playing.
AI in games can get extremely complex. Even making a monster moving around in some sensible way is quite challenging. MMORPG games profit a lot from the fact that usually their monsters are just going around and around without doing much, waiting for you to initiate the fight. While my game is a multiplayer RPG, it’s not a massive online one so I can’t get away with the AI. I don’t just need to tell my monsters how to attack the hero but I also have to train them to avoid falling onto the walls, dodging the hero’s incoming fire, maybe attack in swarms and generally appear challenging enough to the player.
One important thing is the categorization of the objects. This is achieved through the object hierarchy and when it comes to AI, the highest the level, the better since when programming AI we don’t want to have to deal with any low-level technical details. Every game entity derives from the Entity class which offers the basic control functionality.
AI can’t be programmed in random or by trial-and-error. State and flow designs have to be drawn for every single entity (at least the ones that aren’t similar) and then translated into code through some software design. The design I’m going to use consists of a base control object that every game entity is attached with. This control object can be the player’s input in the easiest case, a finite state machine with several states or even a full scale neural network. In my game I’m not going to use the latest. All AI will be done using finite state machines; they might use fuzzy logic at some cases but it will still be state-based logic.
The controller runs through a state using any of the entities data or making the entity perform some actions (for example rotate or walk forward). If a condition is satisfied (or a threshold is reached) then the state changes. Each state can have its own conditions for switching to the other states.
Conclusion
For the few weeks to come I’ll be working on the prototype. The aim of this prototype is to reach a state that I’ll have the physics and part of the AI implemented so I’ll have a clear definition of the game world and its objects. Then I can move on to what will probably be the hardest part of all which is making the game running on the client/server architecture. Many functions of this prototype will split between the client and the server application, others will be shared and some will be lighten up for use in the client, where the server will be running the full algorithms.
For example the client doesn’t really need to perform any long term collision detection. The server will be the one that will have a very clear idea of where the player can go and not. On the other hand some fast basic collision detection is required for avoiding obvious collisions when the data from the server are yet to be received. Still though I don’t have a clear understanding of this process, so I’ll have to do a lot of experimentation.