Roles and Options

One of the more fun challenges in ship design here is getting any particular blob of ships to make sense as a fleet, rather than simply as a swarm of individual vessels. Not only do the individual ships have to be generally fun to fly on their own, but they have to have some clear purpose: a mission or role that they excel at doing compared to any other ships flying alongside them. Sometimes this is simple enough to figure out – “I’m a bomber! I blow things up!” Things get interesting when more subtle or more complex niches (say, “I’m a fighter/bomber meant for carriers too small to carry complete squadrons of both,” or “I’m a mobile point defense platform”) start to show up.

So, fleets. The goal’s not just to have a bunch of vessels which can each do a specific task; that’s just a swarm of individual ships. The goal’s to have that bunch of ships designed in a way where they directly complement each other and create a whole that’s better than the sum of its parts. You know, fleets. Or squadrons, or wings, or task forces, since it should work on a number of scales.

A lot of smaller-scale examples are obvious. Some ships are meant to be defended by others. A group of bombers will get mauled by a group of fighters unless they have support of their own; a warship may have all kinds of direct-fire damage output but be vulnerable to those same bombers (or other projectiles) due to its own size and sluggishness. The solutions for these are simple enough at first: fighters are around to protect bombers by destroying opposing fighters, and big warships are defended by smaller, more agile warships geared more towards defensive weapons.

Much of the initial burst of unit design was done in these sorts of terms, where we’d come up with pairs of units or unit types which complimented each other fairly well. After a fairly early point, the possibilities branch out quite a bit more: each new unit added has different interactions with every other one in there, after all. Unanticipated roles show up, like discovering that a quick and maneuverable interceptor is a terrific platform for intercepting torpedoes, or that a frigate built around anti-fighter weapons can protect bombers offensively as well as it can protect a carrier defensively. New roles show up as well: perhaps the big warships should have two smaller ships tagging along, with one being an escort and the other being a more medium-sized combatant to spare the flies the sledgehammer. More specialized fighter and bomber types give flight wings more versatility and flexibility. And so on and so forth.

In smaller skirmishes plenty of this isn’t likely to show up – there’s only so much you can do when two pairs of warships or a couple of fighter squadrons run into one another, after all.

At the larger scales, though…?

Fleet carrier and its task force

Implementing Strategy Design Pattern

For the various types of Ships, Projectiles, and Weapons, I need to set up variables to make them behave differently in the game. The Setup methods basically involve a parameter with a type and depending on this type, we set the correct settings using a switch statement.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
public Weapon(WeaponType inputWeaponType, ObjectManager manager, Vector3 inputPositionOffset, float inputDirectionOffset, bool Swap)
{
objectManager = manager;
BarrelNext = new[] { 0 };
IsBullet = true;
BarrelPositions = null;
DirectionOffset = inputDirectionOffset;
TurretInputPosition = inputPositionOffset;
this.Type = inputWeaponType;
switch (inputWeaponType)
{
#region Misc Weapons
case WeaponType.FastTorpedo:
MinStartVelocity = 450;
MaxStartVelocity = 450;
InitialDirectionRandomness = 0f;
ProjectileType = ProjectileType.Torpedo;
DetectRotate = .4f;
RotateRange = .4f;
Rotation = 0f;
BarrelDelay = 2000;
DetectRange = 9000;
psFire = new[]
{
new ParticleEmitSettings(objectManager._game.smokePlumeParticles, 20)
{
directionMult = 30,
directionPosOffset = 20,
velocityMultiplier = .5f
}
};
IsBullet = false;
break;
case WeaponType.FastHeavyIonCannon:
InitialDirectionRandomness = 0;
isLaser = true;
laserType = LaserType.FastHeavyIonCannon;
//RotateSpeed = .075f;
//RotateRange = .7f;
//DetectRotate = .7f;
Rotation = 0f;
BarrelDelay = 500;
DetectRange = 5000;
MuzzleYChange = -5;
break;
//.. ~1000 more lines ..
#endregion
}
DetectRangeSquared = DetectRange * DetectRange;
}

As you can see, this can get quite complicated to maintain and update because of how many case conditions and setup statements are on the page.

We can separate these similar setup statements by using a design pattern called Strategy Design Pattern.

This involves:

  • a Context
  • a Strategy
  • and multiple Concrete Strategies.

 
Let’s start out with a Strategy. It’s an interface which describes what your concrete strategies will all hold in common. In this case, I want to be able to pass in my object manager and the weapon we are trying to set up.

C#
1
2
3
4
public interface IWeaponSetupStrategy
{
void Setup(ObjectManager objectManager, Weapon weapon);
}

 
We can then create a Concrete Strategy implementing the Strategy interface. This class sets up all the necessary variables.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class FastTorpedo : IWeaponSetupStrategy
{
public void Setup(ObjectManager objectManager, Weapon weapon)
{
weapon.MinStartVelocity = 450;
weapon.MaxStartVelocity = 450;
weapon.InitialDirectionRandomness = 0f;
weapon.ProjectileType = ProjectileType.Torpedo;
weapon.DetectRotate = .4f;
weapon.RotateRange = .4f;
weapon.Rotation = 0f;
weapon.BarrelDelay = 2000;
weapon.DetectRange = 9000;
weapon.psFire = new[]
{
new ParticleEmitSettings(objectManager._game.smokePlumeParticles, 20)
{
directionMult = 30,
directionPosOffset = 20,
velocityMultiplier = .5f
}
};
weapon.IsBullet = false;
}
}

 
The Context is where we create a static array of these strategies for later use. Since it is static, we won’t have to re-instantiate the Concrete Strategies whenever we want to use it.

C#
1
2
3
4
5
6
7
8
9
10
11
12
public class WeaponContext
{
public static IWeaponSetupStrategy[] Strategies;
static WeaponContext()
{
Strategies = new IWeaponSetupStrategy[Enum.GetValues(typeof(WeaponType)).Length];
Strategies[(int)WeaponType.FastTorpedo] = new FastTorpedo();
// add more strategies here...
}
}

 
Let’s go back to the Weapon class and hook the strategies in.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public Weapon(WeaponType inputWeaponType, ObjectManager manager, Vector3 inputPositionOffset, float inputDirectionOffset, bool Swap)
{
objectManager = manager;
BarrelNext = new[] { 0 };
IsBullet = true;
BarrelPositions = null;
DirectionOffset = inputDirectionOffset;
TurretInputPosition = inputPositionOffset;
this.Type = inputWeaponType;
WeaponContext.Strategies[(int)inputWeaponType].Setup(manager, this);
DetectRangeSquared = DetectRange * DetectRange;
}

The constructor is much shorter and we can separate out weapon setups into separate files.

Dramatis Vehiculae

I came into this project with a bit more of a grognardy background than, well, most reasonable human beings, which is one of the reasons we’re blurring a lot of strategy into the genre stew that SFX will hopefully become in the coming months. This means, among other things, that I like the idea of variety: choices, options, room for multiple play styles and techniques within the same environment.

In a game like this the obvious way to do that is to have a number of ships to choose from. That’s a pretty standard thing in games even vaguely like this, often boiling down to “you have your small, agile, weak ship, your medium well-rounded ship, your brick that flies like a brick and hits like a brick, and your gimmick option.” A whole lot can be done, and be done astonishingly well, with that kind of setup; it was in fact originally what SFX was going to consist of. One day, we decided to try plugging a small warship in – for certain values of “small,” as we’re trying to keep all of the ships to scale – and, before we knew what we were getting ourselves into, we’d started piecing together elements of a complete fleet.

A handful of ship types? We found ourselves looking at a score of ship types, the rough variety and set of roles that one would need for a navy of some sort. The basic themes of the initial handful of choices were still there, with a consistent range of sizes, but the wider variety let us put in some more divisions and specialized roles. There was suddenly room for, say, a standoff interceptor, or light and heavy bombers, or carriers (which bring in whole kettles of fish on their own, of course).

What this fleet didn’t have, however, was an opponent. (You can see where this is going.)

In a final fit of madness we decided that the variety we put into the first fleet of ships we started planning out was going to be extended not to one other fleet, but to three. Each fleet would have its own complete variety of vessels, able to undertake different roles and missions, and each of which would require a subtly to radically different play style to use effectively. As of this writing, thirty-one of the ships have been plugged into the game to one degree or another; not counting space stations, “terrain” units (e.g., jumpgates, armed asteroids, etc) and some “generic” civilian and transport craft, this is a little under half of the planned total.

With that said, here’s a brief intro to each of the fleets and their implied playstyles. (Any actual detailed lore and background is still half-formed at best, and I’ll save that discussion for future posts.)

Fleet One: The initial force we started with, and by far the most developed in terms of number and variety of ships. This fleet is one of the two “balanced” forces in the game. The fighters and other small craft are built around missiles and kinetic weapons – simply put, they fight loudly – while the warships rely on broadsides of powerful short-ranged beam weapons with a few standoff weapons for long-range actions. Carriers only pack basic defensive weaponry, but can launch large complements of fighters and bombers quickly, and those fighters and bombers are the main long-ranged heavy-hitters of the whole organization. Most of this fleet’s ships are straight out of your standard military science fiction tropes – fighters, bombers, interceptors, and the standard spread of space warships   (cruisers, frigates, and so on) anachronistically named after their wet-navy equivalents.

Fleet Two: One of the two “unbalanced” fleets, these guys rely almost entirely on small craft. Instead of a group of warships comprising a fleet, these guys will have one or two motherships – very large carriers which have no interest in closing with enemy forces when they can get dozens or scores of their little buddies to do the work for them. Fighter and bomber roles in this fleet are reversed; the hard-hitting power is in small, agile attack vessels with big guns, and corvette-sized escort “fighters” which provide air defense and other support for them. Both will be supplemented by highly expendable attack drones because, by God, at least one fleet in this game needed those.

Fleet Three: The other balanced fleet. This one started as an attempt to just reverse Fleet One’s aesthetics – instead of the fighters using kinetics and the warships using energy weapons, we wanted to have the reverse look and a similar spread of units. Things got a bit more nuanced, and we ended up with a fleet that behaved kind of as the opposite of Fleet One: the fighters and bombers operate in more of a defense and support role, while the warships – slow and cumbersome, but carrying powerful, long-ranged weapons – do most of the damage. The second-biggest priority for this fleet will be controlling engagement range; the biggest priority will be letting them hurl cannon broadsides around like Age of Sail ships of the line.

Fleet Four: The other unbalanced fleet, these guys are Fleet 2′s opposite, with their emphasis being almost entirely on warships. A small handful of fighters and fighter types will very much be support ships, used for scouting and bomber defense, with most of the work being done by much more specialized warships than the other fleets use. The bulk of the fleet is small and medum-sized warships built around a core of a few heavy hitters, and the vessels will be faster on average than equivalents from other fleets. Subtlety of maneuver isn’t intended to be a strong point here. (Several of their cruisers firing at some poor doomed target is the stylized header image for this blog right now.)

And there you have it, a brief overview of what we’re all getting ourselves into. I hope to make a weekly thing of such posts, so I’ll probably update on or after the weekend with a look into another aspect of the game.

Ribbon Trails

Over the weekend, I was finally able to get ribbon trails into the game.

A ribbon trail is basically a bunch of axis-constrained billboards, so let’s start out with an axis-constrained billboard.

 

Nothing interesting here, we basically have a rectangle plane that’s being rotated along the blue vector.

When you put them side by side, there’s no problem. However if you start turning, there’s going to be problems because of gaps.

What we need to do is make intersecting edges match each other. This changes the the shape of the billboards into trapezoids.

How do we create the trapezoid? We’ll need to get the correct angle to generate the top point and the bottom point. We want to get a vector that is 90 degrees to this.

How do we get this green arrow? If you look closely the green vector is the average of the blue and red. So all we have to do is add the normalized vectors of blue and red, then normalize it.

Now to actually put this to use:

It’s a very good idea to draw the vectors to help with debugging. It’ll save you a lot of time if you don’t get it right the first time!

Now increase the update time from every 1 second to 0.1 seconds and add some fade.

 

Just play around with the texture, update speed, how many segments it should be, etc… and voilà, you got yourself your very own ribbon trail.

Yet Another Introduction

Hello everyone, I’m ace. As mentioned, I’m the programmer that turns caffeinated beverages into new features for SFX.

Hrmm, I guess a brief history is in order.

The development started out as a side project back in freshman year of college. From one single ship with primitive spheres as bullets, to fully working weapon systems, detailed ships, unit and squad AI, the project has matured greatly. I didn’t do this alone of course. I managed to get Zibblsnrt to help me out with the project. Little by little, he and his spectacular stellar space ship factory has also been cranking out small fighters and warships to where it is today. There are over 30 playable ships in the game as of this writing!

We’re currently working on higher levels of AI that will manage Carriers and Battlegroups (groups of squads) alike. We’re also working on some visual goodies such as dense star fields and nebulae.

Stay tuned for updates!

Meanwhile, you can entertain yourself with some old videos.

An Introduction

So, some sort of intro probably isn’t too out of line here.

I’m Zibblsnrt, part of the vast hive of, uh, two people currently working on the project we’ve been calling “SFX” until we can put together enough gameplay and lore to warrant an actual name. Insofar as either of us have anything close to actual “roles” in this project, I’m mostly the art guy and unit designer, trying to figure out what things look like and how they’ll play, and attempting to see how much of both I can learn as I go along. Ace will be along soon for his own introduction. (Won’t you?)

Earth fleet carrier and cruiserSo what sort of project is it that we actually  have going here, anyway? The short answer is that it’s a work in progress and we’re not entirely sure where it’s going to end up. The more interesting one is (activating Pretentious Artiste Mode!) that we hope to come up with something somewhat genuinely different, blurring the boundaries between a few different game genres and just maybe create something new in the process.

Dogfight!In its original form SFX was playing around with the idea of creating another top-down space shoot-em-up, an excuse for Ace and I to practice our coding and graphics skills respectively and, well, get the ability to blow things up to show for it. As we got better at that and shifting interests or inspirations hit, the composition of the game snowballed for awhile, and the resulting ad-hoc jumble actually managed to coalesce into an actual vision of some sort.

The current plan still shares the core of the original idea: a game in which you can pilot little spaceships around a 2D plane to blow up other little spaceships. The views have complexified somewhat with a controllable camera, and the art has (I like to think) improved a lot over the previous versions. The gameplay has expanded quite a bit, however; the small zippy fighters now include a range of not-small-at-all warships, and the long-term goals involve a vastly more strategic style of play, with task forces and fleets instead of single ships or small squadrons.

Summanus-class battleshipSo is it going to be an RTS? To a point. We’re not trying to just emulate Homeworld (except maybe its gorgeous aesthetics at points), and we’re certainly not trying to bring the click-click-spez-rush play style of other modern RTSes into play. To a point, it’s also going to continue to be that “fly around in a zippy fighter and blow stuff up” game, and it’s also going to be a larger-scaled, slower-paced strategy game for the armchair admirals. The goal is to have a game where people can drop in at multiple levels in a fleet combat environment: from dodging flak and enemy interceptors in a fighter, to maneuvering a cruiser in the main battleline, to directing an entire campaign from the CIC of the flagship. We’ve got our general goal – providing something fun for noble the blowing-things-up-in-space demographic – and would like to cast as wide a net in that goal’s direction as possible. And yes, making that as multiplayerable as possible is, as far as we are both concerned, mandatory.

Bosada cruisersA more technically difficult and ambitious goal we’re giving ourselves is the development of an involved AI system for the game as well. The ship counts we’re expecting a typical battle to have are well beyond casual online multiplayer numbers; unless people are expecting to coordinate a hundred or more participants in a battle there’s just going to have to be some computer-controlled units to pick up the slack. The challenge – and it’s easily the biggest challenge we’re giving ourselves here – is to put together a system whose basic behaviours can compliment a human player (as opposed to requiring one to micromanage his entire fleet), and also reliably challenge said player as a capable and adaptable enemy. Making as much of the AI as possible third-party scriptable is also in the books, both to give future players another realm in which to compete by letting them design their own doctrines, and also to allow for all sorts of delightful, unexpected emergent behaviours that none of us saw coming.

Thunderer versus Summanus

Surprise is, after all, an important part of all kinds of fun. We like to encourage it. We’ve surprised ourselves often enough so far as we started to put all of this together, and as we share the process and progress with you as time goes by we plan not only to provide a steady stream of new surprises (and, eventually, gameplay), but we also hope to receive a few of our own.