Flythrough.Space Retrospective

I’m not going to rehash don’t remake an old game, but the principle very much applies. Flythrough.Space is a 3d remake of the EV series, and as such suffers from the “remastering someone else’s game” problem. That said, it was a long and involved software project, so there’s got to be something to take away from it, right?



Content Design

Don’t do content design up front. I had reams and reams of content for this project, a holdover from an even older project, making the oldest data seven years old! And the design of the map dates back to an EV Nova TC I attempted in 2005 or 6. The first plan involved using the graphics from Onyx’s Old Shipyard, back when the whole thing was going to be sprite based. FTS, while using the existing data, was 3d from the beginning so needed its own entire suite of assets.

I ended up using Blender because it’s Free Software and I wanted to keep the toolchain as free as possible. I wanted anyone to be able to pick up the same tools and build more content. It took me a while to become minimally proficient with Blender. One thing that ended up looking really cool was making rough textures with blender’s texture paint then applying a “paint” layer in GIMP with clean lines but dusted up with a rough brush and a makes for a worn look. The ships aren’t exactly up to modern standards, but I’m proud of the results nonetheless.

The planets turned out pretty good. Never did nail clouds though.

inshes.png

Technology

Flythrough.Space started out with very basic requirements. I wanted to do the game in 3d, I wanted menus, I wanted to be able to write object oriented code and I wanted to be able to break code into multiple files. Web was a platform I’d been working on for my whole career up to that point, and I wanted to make the game very easy to pick up and play, so web it was. There was a long period of using babel and Angular to compensate for the shortcomings of JS, but eventually we got all the goodies right in the browser! Once I was working in vanilla ES6 with no precompiler or other baggage, working with the code was pretty much a joy.

ECS

I tried to build an entity/component system. All of the game’s behavior is implemented in “systems” which are functions that get run each frame, requesting entities that have specific components to work on. For example:

export function velocitySystem(entMan){
  // Provides inertia.
  for (let ent of entMan.get_with(['velocity', 'position'])) {
    // Do physics
  }
}

The game state all belongs to entities or the player save object. This turned out to be a fairly awkward way to program a game. It was very nice that, say, velocity or AI could be added to any entity pretty easily. But there just weren’t that many different classes of things in FTS. A class hierarchy wouldn’t have become overly complicated, considering the small number of different entity types in the final game (ship, beam, planet, asteroid, projectile, explosion.) One major drawback was how it changed the code layout of the project. If you want to see what code controls the behavior of a ship, you need to browse several different files and it’s extremely unintuitive. Likewise, if you want to know what parameters a ship can have, there is similarly no single place to check out. There is no FTS bible. One possible evolution would be to put every possible ship param into the implicit base class, but then you’ve got a few parameters where absence matters…

Collisions

I wrote a primitive collision library myself, and my attempt to integrate a proper one later was frustrated by a lack of the primitives I needed, specifically objects with no rotation components.

The crowning achievement of the collision system is the line segment collider. Managing to implement (not invent, mind you, merely implement) allowed continuous collision detection which made combat work much better. It also enabled beams, which are a staple of the genre.

Missions

The missions system leverages ES6’s actually very nice text interpolation to make nice templated text. It uses eval all over the place to do it. It’s a bit fiendish how it works, and it works very nicely for stuff like “deliver cargo” but to add features like “go blow up ship” you’d need to add something in the system code to spawn ships depending on active missions. Probably wouldn’t even be so hard, but it’s low hanging fruit that I haven’t picked. Missions where a very late addition, right before the Alpha release. The json to define a mission looks like this:

  "smuggle": {
    "short_name": "Smuggle ${cgo(this.cargo.type)} to ${this.dest.spob}",
    "desc": "Some shady exporters need ${this.cargo.amount} tons of ${cgo(this.cargo.type)} moved discretely.",
    "offer_if": "true",
    "offer_state": "missions",
    "cargo": {
      "type": "${get_illegal_cargo()}",
      "amount": "randint(5,10)"
    },
    "dest": "get_spob_same_govt()",
    "reward": 14000,
    "accept_modal": {
      "text": "The dockhands quietly load the mislabeled containers of \"${cgo(get_legal_cargo())}\" into your hold."
    }
  },

But that sort of thing only covers random cargo missions. I’d designed the world for FTS without giving too much thought to how it would become involved in any sort of story, besides the idea that the Loyal Suns wanted to take everybody over and the Itaskans wanted you to visit every homeworld. This is a problem because in EV games, you’re supposed to play missions to unlock faction ships, and most of the ships in the game (especially the ones I’m most proud of) where faction ships. My inelegant solution: all ships available all the time. No dynamism. Nobody wins or looses. Some people just fight sometimes and if you hail them they’ll give you the slogans of their government. I think that without plotlines, there isn’t much of a hook. There’s certainly no endgame besides grinding up to an Absolver, Nightshade, Capital, Taoiseach, etc.

Data Driven

Every ship, star system, etc is defined in json files. Many previous game attempts had done a lot of work on making a perfect data loader. In this case, I was able to leverage Javascript’s own builtins to make something I’d consider basically perfect (or at least perfect in that it represents an idea taken to its full extent.) You can declare another object as a given object’s prototype and it just works, inheriting values that aren’t overridden. Objects are created on screen by instancing the data (with some enhancement, of course, but it’s all fairly easy to follow.) There’s no intermediary data is what I’m getting at; the javascript objects in the data directly translate to javascript objects in-game. Upgrades work by acting like a diff. Getting all of this to just work was one of the funnest parts of the project and will be the hardest part to let go of.

Community

The babylonjs community, by way of their forum, was extremely helpful. Having real live people who want your project to succeed and can help you use the tools they’ve built is a joy. I would definitely recommend treating community as a critical feature when picking frameworks and libraries.

That said, you also need to cultivate a community around your own project. That’s one angle where I failed in a big way. It isn’t easy to get other people to demo your game. Starting with something very you can get right into, rather than starting a player out as some sort of lowly level one wimp in an RPG might make a lot of sense. I eventually added cheat codes in the form of querystrings (bonus points if you can find them by looking through the source) so players could start in more powerful ships (and so that I could test them without grinding.) But without a large number of testers, tons of bugs slipped through the cracks. It took me way to long to realize that using Control as the fire button simply wasn’t going to work on mac, for example.

If you want to use FTS

I tried to do with FTS what Ambrosia never did with EV: make a totally open system that anyone can pick up, make a game, and truly own that game with. FTS is licensed under the GPL so if you throw in your own assets and release any code changes, you (yes, you!) can make a commercial EV Clone with it. The game scenario lives in the data and assets folders. If anyone has specific questions about how to implement something, I’d be glad to help. But I realized something: nobody is going to mod your game if they don’t love your game. Making a game easy to mod needs to be a secondary concern to making a great game. If you really truly want to build technology rather than a game, I would recommend partnering with someone with a vision for an excellent game, which brings us to our next point.

Putting the cart before the horse

I thought I knew exactly the game I was trying to build from scratch. However I was building it largely in a vacuum and I certainly wasn’t going back to EV Nova to see how the ship movement and turn speed compared. This was probably a mistake. I was so mired in what I could achieve technically that I wasn’t stopping to ask if the game I was building was actually fun or not.

I should have spent the bulk of the development on the basic combat loop, making sure the ship handling was fun, the AI was correct and tight and fun to play against, and the game balance was decent. Instead I focused on creating tons of content and features because I was trying to work from a feature checklist. Feature parity with a twenty year old game does not a compelling game make, as it turns out. On paper, FTS has what it needs, but I feel that it does not live up to that potential.

It’s a mistake I don’t intend to repeat. Future projects I’d like to get in front of people faster, I’d like to be less stuck on design decisions I didn’t even make, and I’d like to have the emotional fortitude to disengage from a project before it takes up half a decade.