Something I enjoyed a lot in Battletech games was handling overheat. A well aimed CPP shot could blow a mech up in a blink. CPPs, however, raised your mech’s heat a lot, and an overheated mech would switch off for a while. Installing enough heat sinks allowed you to control heat, but also standing knee deep in water or fighting on icy regions.
We wanted something like that, so we created the Heat component & system. Entities that may overheat and malfunction have a Heat component to keep track of their temperature. Laser weapons, for instance.
Heat components store an entity’s current temperature in a simplified way, with values ranging from 0 (operating temperature) to 1 (maximum operating temperature). Their dissipation rate is used by the Heat system to lower temperatures constantly. Any system that may increase the entity’s temperature will do so by adding an operating heat when used. External factors like flying close to a star can increase temperatures too.
We tested it with laser weapons. When triggered they increase the current temperature by their operating heat. If heat raises above 1 the laser weapon is jammed until temperature falls down back to zero.
We also added the LaserWeaponGunner component&system, which are able to shoot laser weapons when certain conditions are met: there is a locked target in the Entity Targeter Component and temperature is low enough in the Heat component. In this example the gunner ignores temperature and jams the laser weapon.
We are still trying to figure out how to properly work with ECS, still unsure about what makes a good System in an ECS. So far we are following two rules:
“A System that does more than one thing can be probably divided into many Systems”, which follows the SRP (single responsibility principle)
“If a piece of code appears in more than one System, it’s probably a System on its own”, which follows the DRY principle (Don’t Repeat Yourself, avoid code duplication).
Both or which are two key software principles anyway, so it probably won’t hurt.
Following #1, we separated the system that was previously responsible for rotations and movement into SpaceFlightSystem, which just updates velocities and an entity’s position in three dimensions, and HeadingSystem, which is now responsible for rotations. We also keep track of user input in separate systems and components (flight & heading), so we are able to control entities that move and rotate (spaceships), but also those that don’t move but rotate… like turrets. Here’s an early test:
We also decided that many entities would be interested in ‘going somewhere while heading toward somewhere else’, an action shared by behaviours like traveling, patrolling, chasing or surrounding an enemy. Thus the ApproachManeuverComponent & System were born, which we tested spawning a tracking missile:
A bit of code refactoring allowed us to simplify the way we check and fetch entity components thanks to C#’s TYPE class. But we’ll write about that when we are sure our ECS implementation makes sense, if that ever happens.
Finally, we took some basic graph theory and built a rough small random galaxy generator. By finding the minimum spanning tree of a bunch of randomly placed star systems and forcing a few cycles and some angle constraints we create the layout the galaxies we will traverse in our quest!
This week we refactored the flight control system. Heading and velocities are now independent components, allowing us to create entities that rotate and move, like our ship; entities that move but don’t rotate, like… railgun slugs? And entities that rotate but don’t move, like unmanned turrets. We created the later to test our new systems.
They are able to detect nearby targets in range, choose the closest one (AI is just the simplest), set a desired heading so their barrel faces towards the target and rotate:
They don’t shoot, yet. That will depend on the mounted weapon. Firing an energy weapon will require keeping an eye on heat while ballistic/kinetic weapons require managing ammo and reloading times. We’ll get there.
Fun fact: we can create elite-like gimbal-mounted weapons by simply attaching a turret to our ship and telling what to look for. This one is targeting the planetoid:
Furthermore… by separating the current input control system into heading (rotation) and velocity (thrust & strafe) we could easily get manned turrets! And we would be a step closer to this:
Here’s an early prototype of a space flight game we would like to turn into a proper game someday. Plus, it’s also our Christmas and New Year postcard this year! So Happy 2017!
So far we are already able to turn the spaceship with a mouse, accelerate (W), brake (S), strafe left (A) and right (D), fly upwards (Space) and downwards (Left Ctrl) and roll left (Q) and right (E). Yup, it works like a FPS! We can also shoot our lasers (Left mouse button) and a tractor beam (Right mouse button). We’ll add gamepad control at some point.
Behind the curtains we are also toying with an Entity Component System (ECS) architectural pattern on Unity, and so far we have a good feeling about it. Those gifts swarming around the Christmas tree are nothing but pure data!
Plenty of work ahead and surely lots of fun. And headaches. But that’s what game development is about: solving problems to create fun!