In my third year of Game Programming at SAE Institute we were tasked of building a game using a custom C++ engine, which can be played on the Nintendo Switch and to do so we developed the AerRacer project.
During the first phase of the project, the C++ engine was still in development and not ready for the implementation of the game mechanics. We had to develop a first prototype using the Unity Engine instead.
The team is used to develop using Unity Engine, this allowed us to design a quick prototype and to quickly iterate through the controls to better understand what where our limitations and goals.
Our main task was to implement an Input Manager that uses the inputs of a controller and to use the Input Manager inside the Ship Controller to move the ship.
When the controls and the inputs where done and the Engine was ready for game mechanics implementation, the code will be transcribed into C++ into the new engine.
In the game, the ships are controlled by two propellers on each wing, and each propeller is controlled by one joystick, the Input Manager is there to simplify the reading of the values and to convert them into Gestures, which will be used to easily control the ship.
The Input Manager first take the raw inputs from SDL, and then convert it to Directions
Those directions where then used to determine which Gesture was being done by the joysticks.
The Ship Controller serves many purposes, the first one is to control and direct the ship in the direction that the player want, the second is to hover above the ground at a certain distance and the third is to rotate the ship according to the angle of the terrain that the ship is currently hovering above.
In the CalculateThrust function the thrust is calculated but also the rotation of the ship.
The torque and the thrust inputs are taken from the Input Manager:
Then using those variables we apply the torque and calculate the propulsion force that need to be applied. In the C++ engine we are using PhysX as our physics engine which is the same used by the Unity Engine.
To hover correctly and realistically the ship controller cannot just stay at the same height during all the race. The movement need to be fluid, as if it were on a cushion of air.
For that, we need a variable that will give us the right amount of force to hover but not too much or too low so we don’t overshoot or undershoot our desired height.
To do so, there is a PID controller, which is a control loop employing a feedback that is mainly used in industrial control systems. A PID controller calculate an error using the desired value we want to obtain and the current value we have now and then give us a value to use in our position correction.
It’s based on the proportional, integral and derivative terms (P, I, D) each value has to be tuned so that the control response is accurate and adapted to our need.
Tuning the PID can result in many fluctuation of the value during a time, a bad tuning can result in too much oscillations, undershoot, overshoot or un-natural motion in our case. (Which we don’t want)
We are getting the correction value here, using the desired height, the current height and a time parameter.
We are getting the correction value here, using the desired height, the current height and a time parameter.
We then need to correct the ship incline to match the slope of the terrain the ship is currently on, to do so we calculate the normal to the ground, and project it on a plane.
A rotation is then calculated using Quaternion::LookRotation between the ground normal and the projection.
We then apply the rotation to the ship by using a lerp function.
Using the inputs and the movements, we can now control the ships using the Nintendo switch Joycons and an Xbox or PS controller. The ships are correctly adjusting to the terrain and hovering correctly at a desired height
By doing this task I learned how C++ game mechanics integration work, and how to solve specific problems by using other field technology to implement solutions.
I learned a lot about organizing my code to do tasks efficiently and with a good readability.
As I implemented my code to solve the ship movements problem, I had to remake things multiple times to make the controls feels interesting and fun, iteration was part of the development but not complicate things help a lot.