At the start of this year (2017), I decided to develop a full blown game using my game engine.
For a couple of weeks, I struggled to come up with the type of game to develop. Since I am not a gamer, this task was difficult. Although I am capable of developing a game (technically-wise), I lack gameplay knowledge.
So, I started playing several video games. Unfortunately, most of them bored me within a couple of minutes. I guess that is why I never got into games; some of the games I played in the past bored me quick. Of course, Super Mario and Pac-Man never had that effect on me.
As I searched for the type of game to develop, I ended up playing a soccer video game. Instantly, I knew this was the kind of game I wanted to develop. I didn't even think about it twice; I just knew this was it.
Not only do I enjoy playing soccer (Currently I play in two leagues), I also know the game quite well. I understand the role of each player and the strategies used. And since developing a soccer video game requires a lot of AI (Artificial Intelligence), this knowledge will be quite useful.
The video below shows the initial development stage of the game.
As the video shows, I was able to create the effect of dribbling and kicking motion through the use of the game engine's animation system and physics engine.
How did I do it?
Animations
The first thing that I focused on was in developing several animations. I am not an animator by any means, so I had to read several books and do several test animations. Luckily, I found this book The Animator's Survival Kit. It was a great help. With it, I was able to do a walking, running and kicking animation as shown below:
Now, one of the things that you need to consider is the transition between animations. To make it look smoothly, you need to blend each animation. I ended up doing this by interpolating the last keyframe of the previous animation with the first keyframe of the new animation. Here is a transition from running to kicking animation:
Creating the effect of a kick
The logic to kick a ball is very simple. Once there is a collision between the soccer ball and the player's feet, an impulse force is exerted on the ball, thus producing the kicking effect.
For a collision to occur, the collision detection system computes a convex-hull bounding volume for each model; ball and player. However, the problem is that the player's convex-hull is not updated during each animation. Let me explain the problem with more detail.
As you may know, a 3D animation is possible through the use of an armature. Unlike animation in 2D games, which consists of sprites played sequentially over a period, animation in 3D games consists of an armature influencing the vertices of a 3D model. An armature consists of several bones. The motion of these bones, affect the vertices of the mesh, thus creating the illusion of an animation. The video below shows the bones of a 3D model during a running animation (in Blender):
The video below shows the player with its convex-bounding volume using the game engine.
As you can see, the bounding volume does not follow the animation. Thus, when a player extends its foot, and the soccer ball is on the foot's path, the engine will not detect the collision.
You may ask, "Why don't you update the convex-hull on every animation?" The reason is that computing a convex hull is an expensive operation.
It took me while to figure out how to detect a collision with the foot and the ball. I ended up playing FIFA and other soccer games for hours trying to figure out how they do it. I tried different methods, but they all failed.
Finally, around 2 am, I got an idea how to implement the most logical solution to my problem. It took me about 4 hours to code it.
This is what I did:
Since I need to know the feet bone's position during each keyframe, I linked two cubes to the player as children objects. These cubes represent the position of the player's feet. I then retrieved the position of each feet bone during each keyframe and used this information as the cube's new position. Here is a video of the cubes following the feet path:
I then enabled collision detection between the soccer ball and the cubes. Thus, as the animation runs, the cubes follows the path of the feet. And if the ball happens to be on the cube's path, a collision is detected; thus exerting a force onto the ball. Here is a video showing the effect:
Is this how other studios do it? I have no idea, but it works for me.
State Machines
One of the reasons why I decided to develop a soccer game was because I wanted to know how to develop an AI (Artifical Intelligence) system. It so happens, that a soccer game requires a complex AI system. I felt that learning AI through a soccer game would be time well spent.
I bought this book Programming Game AI by Example. This book has a whole chapter on how to develop a soccer game's AI. To be honest, it has been a fantastic book and has helped me a lot through the initial stage of the game.
An AI system requires a Finite State Machine. In simple terms, a state machine transitions from one state to another state depending on a current condition.
As of today, the soccer player in my game has these states:
- Idle
- Halt Ball
- Dribble
- Kick Ball
Depending on a condition, the state machine transitions the player from its current state to a new state. For example, it can transition from a "dribble" state to a "kick ball" state.
You would agree that a simple way to implement the state machine would be to implement an "if-then" or a "switch" statement. However, this is a naive way to implement a state machine. And you should avoid these type of implementations in complex projects.
Instead, you should use State Patterns to implement a state machine. A state pattern is a design pattern which encapsulates each state in an object class. Each class contains the behavior for a particular state. Thus, instead of using "switch" statements, you will use objects that will implement the states' logic in a clean, modular way.
Thanks for reading