Fleet Movement Improvements

Posted by

I've been working on improving the fleet movement logic and I think some good progress has been made so far.

Fleet moving between two stars, with details panel

Above, you can see I've got a fleet moving between Gora and Josius. You can now select in-flight fleets and get a summary of where they're going, how long they'll take and so on. The interface is pretty basic, but I think it makes sense and provides just enough info that you can see what's happening at a glance.

Another thing to note is that I've started using this sprite library from the game "Tyrian" for my ships (and also buildings, not shown here). As before, the sprites and graphics are only place-holders for now, but I like this library because it's got plenty of variety while still providing me with a coherent set of images.

Star selected, showing fleets around the star

Here you can see where I've got a star selected. You can now view both the planets and fleets around the star by switching between the two tabs. I'm also considering doing away with the tabs and just having a single list with both planets and fleets, but we'll see how that goes.

Another thing I want to tidy up is what's happening on the right there. Those two enormous buttons are taking up quite a lot of space and the real estate could be put to better use for something else. I'm not entirely sure what at this stage, perhaps I could just divide the bottom section into three and have planets and fleets listed side-by-side with the two extra buttons down the right somehow.

Anyway, that's pretty much it for today. Fleet movement is a pretty important mechanic in the game, though, so it's important that I spend time making sure it's as close to perfect as possible.

Progress Report, August 2012

Posted by

Over the last couple of weeks, I've mostly completed porting the screens to portrait mode, and I think the results look generally pretty good. It also generally makes the game easier to use with the phone in one hand, which I hope will be somewhat of a plus.

Anyway, here's a couple of screenshots of what it looks like in portrait mode:

Starfield view

This is the (now-familiar, I'm sure) Starfield view. A nice background on the lower pane makes it look much more "polished" than the plain grey we had last time.

List of colonies

When you click on "Empire" from the starfield view, it switches to this screen where you can see all your colonies and whatnot. Again, nothing we haven't seen before, but now in portrait mode (and also a separate Activity, rather than just a popup dialog).

Solarsystem view

Here we have again the familiar solar system view.

Buildings

Clicking on the "Build" button brings up this screen where you can see all of your buildings, upgrade and build new ones. As well as clicking on "Ships" to build new ships and "Queue" to see your current build queue for that colony.

Moving Fleets

Posted by

The next feature of War Worlds is a pretty big one: moving fleets between stars. It's also interesting because it's forced me to think quite a bit about the general UX of the whole game. There's plenty of tweaking and fiddling that can be done, and sometimes I've got to force myself to just stop with the tweaks and get features implemented: the quicker we get to feature-(mostly-)complete, the quicker we can start play-testing. And that's when all the tweaks can happen.

Anyway, we saw last time that I'd mostly finished converting the game to run in portrait mode, so let's continue from where we left off there.

Empire view

Firstly, lets take a look at the updated starfield view:

Starfield view showing empire icons and fleet icons around the stars

Here we can see the latest version of the starfield view. I've updated the icons around the stars so that you can see when an empire has a colony on a planet, the empire's name shows up around the star. Also showing up is an icon representing the fleets that are orbiting the star.

The number after the colony indicator is the number of colonies that empire has on planets (so for example, "Farce" has one colony and "Killerz" two around the Baradhrand star). The number after the fleet indicator is the total number of ships around that star (So "Killers" has one ship on Baradhrand and 2 on Lanadandur)

If we click on the "Empire" button, we get to see an overview of your empire. Clicking on the "Fleets" tab, we see:

The 'Fleets' tab of the Empire overview

This is the list of all ships you have in your empire. It's sorted by star and grouped into fleets. You can use the "Split" function to turn a fleet of ships into two fleets (we saw this back in June) and you can see I've done that with the scouts on UrĂºvion.

Moving Fleets

If you click on "Move" it brings up the move dialog:

The move dialog when you first bring it up

As you can see, we're centred on the UrĂºvion star where the fleet is currently sitting. You can scroll the view around to select the star you want to move to:

We're moving to the star Garia

Here we've scrolled up a bit and select the "Garia" star as the destination. Click "Move" and the fleet starts moving. It takes a while to actually move between stars (the kind of ships in the fleet determines how fast they can move -- e.g. scouts move much faster than colony ships, etc), but you can track the progress of the fleet directly on the starfield view:

Tracking the progress of the fleet, it's moved about half-way so far

Work in progress

Clearly, this is all very much work-in-progress. There's a lot of information that's currently not being shown that probably should be. For example, on the "Move" dialog, it would be nice to show an estimate of the movement time when you select a star (e.g. "The fleet will arrive in 2 hrs 32 min" or something). It would also help to show that information somehow directly on the starfield view.

I'm also not entirely sure I like the look of the white line representing the path of the ship. Perhaps we could hide the lines and only show them when you tap the fleet. I imagine with lots of fleets moving around, it could get quite busy on this screen.

Which is better: portrait or landscape?

Posted by

One of the questions I decided early on in my design for War Worlds is that it was going to be played in Landscape-orientation only. To be honest, I'm not really sure why I chose landscape, though I guess coming from a desktop computer, that seems the most "natural".

But thinking about it a bit more, a phone interface is naturally portrait orientation. You can hold your phone in one hand and navigate with your thumb in portrait mode - in landscape mode, you're pretty much forced to use both hands. That's fine for Angry Birds, but I think for War Worlds, where you're going to checking up on your empire frequently throughout the day (rather than sitting down for a solid 30 minutes at stretch) the more I think about it, the more portrait mode seems like the natural choice.

Now, obviously allowing the game to run in either mode would be ideal. And the Android SDK makes it quite simple to just define two different layouts for each orientation. But being the one-man team that I am, I don't think I can suffer the additional development and testing that supporting both would require.

So I've been doing some experiments with portrait orientation. Here's a couple of shots showing the difference between portrait and landscape mode for the starfield view:

Portrait mode starfield view

Landscape mode starfield view

And for the solar system view:

Portrait mode solarsystem view

Landscape mode solarsystem view

I'm not entirely convinced yet, but that may just be because I haven't tweaked the portrait layouts as much as I had the landscape layouts. I think I'm going to stick with the portrait view for a while and see whether it starts to grow on me.

What about the tablet?

On the tablet, the "natural" orientation is going to be landscape. So what should I do if I want to support tablets (and I do!). Right now (at least, after my setback), I don't have a tablet to test with. But playing around on the emulator, I think I can make portrait mode work there as well.

But for now, I'm happy to just "ignore" the tablet market. We'll see where that takes us in the future.

Last Point

If you're observant, you might also notice the "selection circle" is different in the portrait mode starfield view. I had a play around with adding an animation for the selection (so those two circles rotate in opposite directions). I think it looks pretty cool, and I'd like to add more of that kind of "flair" in the future.

Using custom properties to reduce the number of entities you need to store in App Engine

Posted by

One of the issues I've run into with the backend of War Worlds is the sheer number of entities. The universe is made up of sectors, each sector contains around 30 stars and each star has (on average) 5 planets. Up until now, I'd been storing each of those things as a separate entity (so one entity for the "sector", one for the "star" and one for the "planet").

Proliferation of Entities

The problem with that is it means there's around 1,629 entities in a 9x9 grid of sectors (the game works on a 9x9 grid of sectors and as you scroll around, we try to keep your view centred on that 9x9 grid). This is a pretty major cost not only in terms for performance, but also in terms of actual dollar cost (App Engine charges you per entity read/written).

Everything is kept in memcache, of course, but even with that, just doing some testing by myself, I could easily use up App Engine's "free" quota for data store reads in a single day (you get 50,000 entity reads for free)

I wanted to find some way to reduce the number of entities, without over complicating the code (i.e. without totally re-inventing the data store myself). Thinking about it, I came up with two solutions:

  1. Since the random number generator used to generate the sectors was fixed and predicable, I could simply not store the stars and planets at all, and just re-generate them on demand from a fixed random number seed, or
  2. Somehow "consolidate" the disparate entities into a binary blob stored in one container entity.

#1 is quite tempting, but I eventually decided against it because it means once a sector has been generated, not only do I need to know the seed used to re-generate it, I need to know the exact algorithm I used. That is, if I ever decided to change the generation algorithm (to tweak parameters or whatever), I would need to keep the old algorithm around just to keep re-generating the same stars/planets as before -- you can't have a sector where a player has colonies and so on change out from under him just because I tweak a few parameters!

The other problem with #1 is that if I ever decide to add a new "kind" of planet (say), I wouldn't be able to retroactively go through existing sectors and just add/update some of the planets.

So that leaves #2, and it turns out it's actually not that difficult to do.

Custom Properties on your model

I decided that the most bang-for-buck could be had by storing the planets as a collection of objects directly in the "star" entity. Making just that change would reduce the number of entites in a 9x9 grid of sectors from 1,629 to 279.

So to begin, App Engine only has a few built-in property types. If we want to store a new kind of object as a property, then we need to come up with our own property type. Our planets are already described by a protocol buffer, pb.Planet, so I just hijack that type to store in the data store as well:

class PlanetsProperty(db.Property):
  def get_value_for_datastore(self, model_instance):
    """Takes the list of pb.Planet objects that we have in the model
    converts it to a db.Blob for storing in the data store."""
    planets = super(PlanetsProperty, self).get_value_for_datastore(
                                               model_instance)
    protobuf = pb.Planets()
    protobuf.planets.extend(planets)
    return db.Blob(protobuf.SerializeToString())

  def make_value_from_datastore(self, value):
    """Converts the stored blob back into a list of pb.Planet
    objects."""
    protobuf = pb.Planets()
    protobuf.ParseFromString(value)
    planets = []
    for planet in protobuf.planets:
      planets.append(planet)
    return planets

  def validate(self, value):
    """Ensures the given value is valid for this property."""
    value = super(PlanetsProperty, self).validate(value)
    if value is None:
      return value
    if isinstance(value, list):
      for elem in value:
        if not isinstance(elem, pb.Planet):
          raise db.BadValueError(
              "All elements of %s must be of type pb.Planet" % self.name)
      return value

    raise db.BadValueError("Property %s must be a list of pb.Planet"
                           % self.name)

App Engine only requires the get_value_for_datastore and make_value_from_datastore, but it's also a good idea to implement validate as well, so that we can make sure you're populating the property with the correct types, and so that you can get a nice exception if you use the wrong type, rather than some cryptic serialization error otherwise.

As you can see, the code will convert the list of pb.Planet objects into a serialized protocol buffer value, and then return that as a db.Blob (which is a subclass of str that doesn't try to do any encoding magic). On the way back out from the data store, we deserialize the protocol buffer back into a list of pb.Planets again.

One advantage of using protocol buffers here is that it lets us modify the planet type in the future without having to re-store all of the data again (for example, if we add a new optional field, it'll be deserialized as None)

Using this new property type is just like using any other model property in App Engine:

class Star(db.Model):
  sector = db.ReferenceProperty(Sector)
  name = db.StringProperty()
  size = db.IntegerProperty()
  . . .
  planets = PlanetsProperty()


def generateSector(x, y):
  sector = mdl.Sector()
  sector.x = x
  sector.y = y
  . . .
  sector.put()

  for _ in num_stars:
    star = mdl.Star()
    star.sector = sector
    star.name = "Star Name"
    . . .

    for index in num_planets:
      planet = pb.Planet()
      planet.planet_type = #whatever
      . . .

      star.planets.append(planet)

    star.put()

This is just a snippet, of course, but gives you an idea. Using the planets property of the star is quite simple and the changes required throughout my code to support this change was actually surprisingly fairly minor.

Looking Further

There's actually quite a few entities that hang off the star which could potentially benefit from this kind of optimization. For example the "colony" entity is bound to a planet, so why not serialize the colony itself with the planet?

The problem I found with taking this model too far is that it makes it impossible to fetch the entity outside of the container itself. For example, one of the queries we do (for the "Empire Overview" screen I talked about just yesterday) is a "fetch all colonies beloning to this empire".

If the colonies were serialized as part of the planet (which itself is serialized with the star) then I would have to modify that query to "fetch all stars which have a colony beloning to this empire" which then means I would need to store as part of the star the fact that a colony exists for one or more empires.

It's doable, but in the end, I think it would make the code too complicated overall. Just reducing the planets to serialized blobs has significantly reduced the amount of entities in the game, and I think that's good enough for this rather early stage of development. Of course, we could come back and revisit this at a later date.

Screenshots

Just because I hate to have a wall of text and no pictures, here's some random screenshots for you:

Empire overview screen, list of colonies

Baradhrand IV

Megildagle IV

Thorhallug III