Recent Posts

Hi! The first month of active development is now over, and I've got some great progress to report! According to my Codealike statistics, I managed to spend over 5.5 times as much time coding and debugging than during the previous month.

New features implemented this month include: Turret and fixed weapon modules, projectile and beam weapons, basic missiles, damage system and targeting logic. What this means is that it is now possible to have actual battles between ships and fleets, even though combat AI is not yet implemented.

Please take a look at the video below for an overview of these features. I recommend watching it in 1080p (Full HD) as it allows you to better see the projectiles, missiles etc. that are quite small.



Weapons

There are currently 5 weapon modules in the game: Beam, gauss, plasma and missile launcher turrets, and a fixed "super gauss" cannon. The turreted weapons are mean to be medium or standard versions of these weapon types, with light and heavy variants being possibly added later. The turrets themselves have limited turning velocity, but it is high enough to allow the beam turrets to easily track and disable enemy missiles, performing a point-defence role. All weapons consume resources such as electricity, and have a reloading timer in addition to heat generation and dissipation properties that in combination define the fire rate.

Each weapon type is meant to have it's own distinct flavor, I don't intend to create 10 variants of weapons that all use the same basic principle such as firing a kinetic or plasma projectiles. Gauss cannons use electricity to fire a simple kinetic projectile that has unlimited range and high change of penetrating enemy armor, but deal less overall damage than plasma weapons at close range. Plasma weapons on the other hand have limited range because the gas expands and dissipates energy rapidly, but will melt armor and practically never ricochets. The beam weapons can be used for point defence and pinpoint accurate fire to drill through specific modules on the enemy ships, but for balance reasons also have limited range. Otherwise the AI could always just snipe you from across the battlefield. Beam reflection is being considered, but would complicate some things and possibly cause performance issues.

Missiles are fired from turrets and have their own control logic to hunt down a target specified at launch. Like the other weapon projectiles, they have a body in the physics engine, and follow the same Newtonian physics as the ships do. This means that they need to have quite powerful strafing thrusters in addition to the main one and thus differ from the traditional atmospheric missiles that can depend on air resistance to maintain the velocity vector pointing towards the heading. The current implementation deals a set amount damage to the target on contact, but advanced payloads such as multiple warheads that spread before point defence can knock them out have been planned. The missiles are balanced by limiting the amount carried by each launcher module and engine operation time before the fuel runs out.

Projectiles

Currently there are two main projectile types in the game: Plasma and kinetic (gauss). The kinetic projectile has two variants which differ on the velocity and delivered energy, one used by the gauss turret and the other by the larger fixed gauss cannon.

Plasma is a form of matter that is basically superheated gas. In vacuum this gas naturally will expand rapidly and lose its effectiveness, making such a weapon useless at realistic distances. However, since this game isn't aiming at realism on the combat distances aspect of things, this is only present in the mechanic that these projectiles have a limited range and immediately start losing energy when fired. The initial energy of plasma projectiles is higher than that of kinetic ones, and they travel faster, making them effective at close range and still viable at medium ranges. They also deal damage to armor because penetration and ricochets are very unlikely to happen.

Kinetic projectiles are made from hard and dense materials such as depleted uranium and will usually penetrate armor, causing damage to the functionality and structure of the hit module. The brutally simple kinetic energy of these projectiles can't really be stopped other than mechanically, and the more energetic ones may pass through multiple modules or even tear an unarmored ship apart with a single hit. Once shot, the projectile will travel at a constant velocity until it hits something or leaves the battle area. These are balanced by the relatively low velocity, which makes shooting at actively dodging targets ineffective at longer ranges.

Damage system

The damage system consist of two main parts: A deterministic algorithm to calculate damage to a single module on collision, and another one for finding all modules within the hit ship that the projectile may go through. The physics engine reports the projectile collisions with the edge modules of ships via C# events, and when a collision with a fixture belonging to an enemy ship is found, a grid intersection algorithm is used to find modules that are on the projectile's path. The collision algorithm is then run for these modules in order until the projectile's energy is depleted.

The collision evaluation algorithm is deterministic, which means that there are no random elements and thus the one input will always yield the same result. The damage to the module depends on the projectile's heading in relation to the hit surface normal, projectile type properties such as penetration & ricochet angle modifiers, and the state of the hit module. All modules have three separate "hit point" counters: armor, functional and structural. Armor is depleted first, but penetrating shots can also deal functional and structural damage even if the remaining armor HP is higher than the energy of the projectile. The relative state of the armor is also a factor on the change of penetration. When a module's functional HP is reduced to zero, it goes to a disabled state that can't be recovered during the battle, and when the structural HP hits zero, the module is destroyed, leaving a hole in the ship. Functional damage depends on how close to the center of the module the projectile's path gets to, meaning that hits that only grace a corner are unlikely to disable it, but more likely to pass through to the next module.

The current implementation always destroys the projectile on impact even if it could go through the whole ship. This is because re-positioning the projectiles in the physics engine may have some adverse side effects, and since the projectiles aren't just points with zero surface area, calculating the exit point so that it doesn't overlap the ship's fixtures can be challenging. An undesirable consequence of this is that small pieces of debris can block even the most powerful projectiles.

A full battle demo

Here is an uncut, disorganized, fleet battle demonstration if you just want to see some action.



I will cover development goals for the next month and some other stuff in a separate post coming later this week, stay tuned!

Posted by Tomi Tuesday, September 30, 2014 0 comments READ FULL POST

As you can see, the site has got a major visual upgrade in the form of a banner and background art. The same elements are also used on the YouTube channel and Google+ page, and were contracted from Taylor Osborn. I have also added sharing options with ShareThis-widgets that are available on the sidebar of every page.

This is a technical overview about the current state of the game. For a general description of the concept, please take a look at the previous post Introducing Battlefleet Engineer.

Core technologies

The vast majority of the game is made with C# using XNA 4 and .NET 4.0 frameworks. XNA is nowadays getting a bit outdated with only DirectX 9 support, but the choice was actually made a couple of years ago. The main points in its favor were my (limited) existing experience from C#, good documentation, maturity and price (free). There is also the option to port the game to MonoGame that is still being developed and supported, and would allow to make a multi-platform release, while XNA is practically limited to Windows only. The game isn't actually pure XNA, as it uses some .NET features as well that are not available in the XNA framework.

XNA doesn't really have extensive, mature, and still supported UI libraries these days, and I didn't want to use Windows Forms or WPF (Windows Presentation Framework) as those aren't really designed for real time game use. I considered multiple options, and finally settled to integrate Awesomium into the project and use that for all of the more complex and less performance dependent UI features. Awesomium is basically a fully featured web browser engine without UI that renders into a memory buffer. It uses the WebKit layout and V8 JavaScript engines from Google Chrome. This means you can very easily load and display basically any website, but my use case is to create the game's UI as web pages using the familiar HTML, CSS and JavaScript technologies and couple those to the core game logic. This makes the UI moddable, and enforces a nice separation of the game logic and UI code that helps to manage the complexity.

Currently there is about 24500 lines of C#, and 1800 lines of JavaScript code in the game.

UI & game graphics

The UI is made with JQuery UI, and communicates with the C# side throught a event-based interface that Awesomium provides. It is possible to easily execute JavaScript code from the C# side and call registered C# event handlers from the JavaScript side. I also use .NET's JSON serialization functionality for moving more complex data between the two. There are some limitations to JSON serialization, but basically I can just serialize any C# object, send it to the UI, modify it with JavaScript, send it back again and deserialize to get a C# object. This means that I don't need to write any transformation or "glue" code for each class to use their data on the UI. I was able to implement a debug/development UI very quickly using this method. The biggest downside is that communication between the UI and C# code has some significant overhead, and thus it is not practical to eg. send JSON encoded data structures to the UI on each frame, but for event-based UI update it doesn't really matter.

Debug UI overlay that uses dat.gui library for the controls.
On the C# side, all drawing is done through the XNA's methods. XNA provides basic functionality such as 2D sprite rendering with draw call batching, GPU state and render target management, asset (texture) loading, and supports custom vertex and pixel shaders. One of the main technical difficulties with this game when it comes to graphics is the very large number of modules that need to be drawn on each frame. One of the design goals is to allow battles that have several thousands of modules total, and each module must have its own texture sprite(s). The ships can't really be pre-drawn to textures either because the structures change, I want to support simple animations and visual module state changes, and it would require a lot of texture memory to hold full-size ship images of even a medium sized fleet. This is where the XNA's sprite draw call batching is vital; when all module graphics are on a single sprite sheet, it can draw all of their visible instances within a single draw call to the GPU. However, the requirement of a single sprite sheet also drastically limits the sum of all module graphics' surface area.

The main feature of the game graphics system I have implemented is real-time lighting of the ships. This is done by using pixel shader based deferred rendering that combines diffuse, normal and self-illumination textures for 3D shading. The system is very similar to what is nowadays a standard in 3D games, but applying it to 2D has some special caveats I'm not going into here. I have made all of the module graphics as 3D models with 3ds max and then rendered the diffuse, normals and self-illumination textures from those. The models themselves aren't used in the game at all.

My particular implementation uses separate render targets for diffuse, normals, self-illumination and lighting passes. The diffuse pass has the color with ambient occlusion "baked in", while the normal map describes a surface normal for each pixel, and self-illumination has the color of those parts that the lighting doesn't affect. Self-illumination is also used for the bloom effect. Based on the scene lighting parameters and the already rendered normal map pass, a light map is drawn utilizing a pixel-shader implementation of Blinn-Phong shading. The intensity values from each light is summed to create a single light map that is then used with the diffuse and self-illumination maps to create the final shaded image. The shading/lighting system currently uses simple diffuse and specular, but can be extended to eg. utilize an environment map for reflections etc. The deferred approach allows theoretically unlimited number of lights with linear performance cost, and I'm looking forward to implementing eg. plasma projectiles with point lights and other similar effects using the system.

Physics & Movement

One of the core features of the game that sets it apart from other similar titles is the uncompromising physics simulation that doesn't cut corners to make the game easier to create or play. The actual simulation is handled by Farseer Physics Engine that is based on the very popular Box2D physics library. Implementing my own physics engine would have been foolish, simply because these free, fully featured and tested libraries have more code and effort put into them than all the other features currently in the game combined.

All movement control goes through the physics engine. This is true for both input from the player and from the ship's internal flight controller logic. In order to simplify the control of what can be dozens of thrusters on a large ship, they are grouped by function so that we get four translation groups (forward, backward, left, right) and two rotation groups (CW, CCW). The grouping can be done automatically by an algorithm that tries to find and group thruster pairs so that they have minimal negative effect while simultaneously maximizing the wanted effect. For example, the translation groups should yield maximum acceleration in the corresponding direction, and cause zero angular acceleration (and thus rotation) on the ship. Each basic thruster has a single degree of freedom, as the power can be modulated, but finding the best solution gets very tricky when omnidirectional thrusters with 2 DOF are added into the mix. The thruster grouping algorithm works in two steps: First is tries to find the best thruster pairs using max throttle on each thruster and sets them to groups. The second step is to balance the group by calculating thruster throttle weighting and using omnidirectional thrusters & reaction wheels to cancel unwanted linear and angular effects respectively.

The movement control of dynamic, modular ships that can take nearly any shape and have poorly designed thruster configurations is a very complex and difficult problem to solve. The fact that my physics simulation does not have any friction to balance things out and stop movement or rotation also makes this even more difficult. Even the tiniest of impulse can make the ship move indefinitely in some direction unless it is stopped by an exact counter impulse. The movement logic builds on top of the thruster grouping logic and cached values for each group's effect on the ship when it is fired. The current system for maintaining position and heading drives the ship by its local X and Y axes independently to the target coordinates, and thus requires all of the movement groups to function. Move-to-point logic uses the same principle, but is actually a rather complex state machine that first turns the ship toward the target, moves it, stops "drifting" if necessary, approaches the target etc. It works quite well for reasonably well designed ships.

In order to implement perfect control that can always stop the ship at precisely the wanted point, we would need a perfect model of the system to use for prediction. While the effects of individual thruster groups can be calculated precisely, the biggest control errors arise from unpredictable aspects such as overlap between thruster groups, lack of resources to run the engines, collisions between ships, and ship structure changes mid-maneuver. Prediction is required for everything, as each linear or angular movement needs to be done in two stages: acceleration and deacceleration. In order to know when to start deaccelerating, we need to predict how long it will take and then compare it to the current state. At this point of development, the thruster group overlap is the most notable source of error, as same thrusters can be used in multiple groups and the use of those groups can't really be predicted. For example, maintaining the correct heading very often interferes with linear deacceleration required to stop at the target position, causing the ship to overshoot.

Resource system

The resource system is currently used primarily for electricity, but can be easily expanded for all kinds of consumables. The main premise of the system is that there are producers, storage and consumers. Resource exchange depends on two types of connections between modules: Full and structural only, which dictate if the module can take part in the resource distribution. 

The basic working principle of the resource system is this:
  1. All generated resources are counted and temporarily pooled ship-wide.
  2. Resource logic queries all active modules about what resources they require, request and offer. For example: Thrusters don't have storage and require a certain amount of electricity when fired, while capacitors request electricity to fill their storage.
  3. Resource needs are fulfilled (required first) primarily from newly generated resources, and secondarily from stored (offered) resources. If generation was greater than requirement for a resource, the rest is sent to storage. (storage modules request resources they can store).
  4. Excess generated resources (that cannot be stored) are discarded.
The resource distribution order can also be modified by player-definable priority resource groups that first distribute within themselves and then any excess is given to the ship-wide distribution pass. In a nutshell: The game doesn't simulate moving of the resources from module to another per se, but the ship's structure plays a role, and the resource amounts are stored in the modules themselves. 

The flexibility of the system makes it possible to simulate balances such as heat production and dissipation that allow e.g. boosting weapon fire rate by adding heat dissipation modules to the ship. This is also one of my ideas to make more use from limited number of weapon modules. A large ship can make a better use of the same weapon module than a small one, because it can have more available power for charging it up faster and can dissipate the generated heat more effectively.



That's it for now, I'm looking forward to this first month (September) of much more intense development, and I will report on the progress at the end of the month. The main topic will be weapon and damage systems, the game will finally have combat aspects!

Posted by Tomi Monday, September 1, 2014 0 comments READ FULL POST