September 23, 2013

Code of Interplanetary: Can I see some ID, please?

Hello there, dear reader. I'm Riku, you might remember me from that more technical post I wrote about making a GUI with Unity. In addition to blogging about our Unity woes, my task has been programming network functionality for Interplanetary.

The game uses a client-server model, where each game client records what the player on that client does during their turn. When the player ends their turn, the client sends all that information to a server for processing. When the server gets this data from all the players, it combines all the player actions together and then plays out the turn, figuring out the outcome. The clients then get back the results for the turn and display some pretty pretty particles flying around to show their player what happened and who shot who.

From the outset I decided that to implement this, I would give everything a unique ID that would be used by different clients and the server to make sure they are all talking about the same thing when communicating. For instance, whenever a building takes damage, the server takes note of the ID of the building, and then tells every client that building number 5 just took a hit. This way, to keep every client in sync so they are all on the same page, I'd just need to make sure they all use same IDs for each object. This sounded very simple at first, but ended up being a little bit tricky in practice.

Let's examine how a building gets assigned its ID. When a building is being built, it should be assigned an ID right away so it can be found again if it needs to be operated on later on. However, the game clients can not be the ones generating the IDs. Each ID needs to be globally unique, and the clients can really only generate IDs that are locally unique to only that one client. They could end up generating same IDs that some other client is also generating for themselves, at which point there would exists two buildings with the same ID. Let's illustrate this with an example. Imagine that ID is an integer, and generating an ID means using an integer one higher than the previous one used. The first building built would have ID 1, the second one 2 and so on and so forth.

Since clients do not have knowledge about each other, they would end up generating same IDs as everyone else. Then, when the information about these built buildings is sent to the server and combined together, the game world would have multiple buildings with, say, ID 2, and there would be no way to know which building ID 2 would refer to. Any time the server would send the clients a message about building 2 taking damage, the clients could not possibly know for sure which building had actually taken damage. This is why all the IDs need to be generated on the same machine, so there won't be duplicates.

The natural option to use here is to generate all the IDs on the server. However, building the buildings happens on the clients' end. It would be possible to ask the server for an ID every time a building is built, but that would create a waiting period whenever a player would build a building and the client waited for the server's response over a network. It was decided that all network traffic would be centralized at the ends of turns, and communicating with the server during a turn would be avoided whenever possible. Because of this, buildings get their ID assigned to them at the end of the turn during which they are built. When the server notices that a player built a building during their turn, it generates and assigns an ID to it. When other clients receive the information that a building has been built, they get the ID for the building in the same package, along with other data like the position and type of the building.

There is one issue left to solve, however. The ID for the building needs to be delivered to the client who built the building, as well. It does not sound complicated at all, but it has some practical implications. For the other clients, the ID was delivered together with the information on how to build the building. They can, therefore, assign the ID to the building as they build it. The one client who already has the building only gets the ID. When it receives the ID from the server, it needs to know which building to assign it to. Normally, whenever the server sends a client instructions about operating on a building, it refers to the building with its ID. However, at this point in time, the building does not have an ID yet! A solution to this is to use temporary local IDs. When a client builds a building, it does still assign a locally unique ID to it. It is not going to be unique across all clients, but it does not need to, as it is only going to be used temporarily until the global ID assigned by the server arrives to the client. The local ID is sent to the server alongside other information about the built building, basically telling the server: "Yo, I just built a building with local ID 5". The server then assigns a globally unique ID to the building and tells the client: "Your building 5 now has ID 7", at which point the client switches the building's ID from 5 to 7. At the same time, other clients just get information about building 7 being built, being blissfully unaware of 5 having been involved with the building at all.

So far things have been relatively straightforward, and were easy to anticipate and prepare for when I was implementing this system. However, there is one complication left to solve, and I admit overlooked it and did not see it coming before I was at the point where it made things not work. Let's look at what might happen when a client builds some buildings.

There are two buildings built on previous turns and the two clients in the game are synced up to that point. Then they both start building buildings and assign local IDs to them, beginning from 3. One client builds one building, with local ID 3. The other one builds two buildings, with local IDs 3 and 4. The server then gets information about this and assigns globally unique IDs to all the buildings.

The global IDs assigned start from 3 and go up to 5. Now, let's look at the second client receiving instructions to replace its local IDs with the newly assigned global ones. It finds the building with ID 3 and switches that building's ID to 4. It then goes to find the building with ID 4, to replace that building's ID with 5. The problem here is that now there are two buildings with ID 4, because of the previous building 3 that was just updated to have ID 4.

The solution I used for this was to fetch a building that needed its ID updated, store its upcoming global ID with it without actually yet updating the ID, and then repeating this process for each building in a need of an ID update. Then I go through all those buildings again, assigning each the ID that was stored with them. In the above example this amounts to finding the building with ID 3, and telling it "your ID is going to be 4, but not yet", then finding the building with ID 4 and telling it it would have its ID updated to 5, and then telling both the buildings to now switch their current ID to whatever ID they were told to switch into.

That is the essence of how things get their identifications in our game so every computer involved can talk about the world state with each other and are able to keep in sync when it comes to the state of the objects. For different objects than buildings the process of assigning the ID is a little different, but that’s something for another blog post. Stay tuned, and maybe I’ll get assigned to talk about those other things in the next episode!

September 16, 2013

Inside Interplanetary: Targeting Problems

One of these must hit!
Hello. I'm Sasu and I like to write blogs.

Everyone's been very busy lately. We're working hard to get everything essential working without a hitch, but hitches keep coming along. Well, that's the reality of game development and there's not much you can do about that. Except maybe try to design things in a more detailed way.

So, today, let's try something a bit different. Instead of me just telling you about a game mechanic, I'll explain some problems we've come across in testing and some solutions we've formed up.

Let's discuss...

The Difficulty of Hitting Your Enemy

Well, I guess one did.
While testing Interplanetary, we've repeatedly come across a tiny problem with the Targeting System: it's darn difficult to hit your opponent! There are many things that play a part in this.

The planetary system is alive. Once you've set the trajectory and fired your cannon, time unfreezes and the planets start orbiting. It can be very difficult to foresee the movements of this slightly chaotic system. The biggest problem here is that the planets have a large influence on their surroundings, thanks to their...

Strong gravitational fields. Now, this is something that's almost impossible to predict for a mere human. Sure, you can account for a planet moving in front of your firing line, but can you calculate how exactly it affects your firing trajectory with its gravitational pull? We can't.

The planets are quite tiny. Small things are more difficult to hit than big things. Who knew?

When shooting a single railgun slug at your enemy planet, the odds of hitting it are very small, even if it happens to be right next to you. Building 15 railguns and firing them all makes it a bit easier, but managing to maintain such an artillery would be very difficult and time consuming in the final game, not to mention the bother of targeting each and every one of them every time. Something needs to change, but what?

We Have Some Ideas

A planetary prediction system would make it much easier see the future positions of planets. We have plans for a system that shows the player the "shadows" of the planets' upcoming positions, depending on the current trajectory drawn. The future trajectory of the railgun slug, affected by the position of the planets, would also be shown as a shadow.

Looks a bit complicated on paper.

The obvious problem with this solution would be that it takes away the element of predicting planet positions and may make the game way too easy to play. Of course, there would be extensive balancing done to accommodate for this feature.

Lowering the effect of gravitation would be an easier way to tackle the problem, but doing so would also make the game less interesting. In the earlier builds, you only really needed to worry about the gravity of the sun. Other planets' pull was much weaker, so it was possible to actually pull off very accurate attacks. This did take away some of the fun, since crazy, unexpected trajectories didn't happen.

We could just make the planets bigger. This might be the easiest solution and the least problematic for now. The biggest foreseeable problem with it is the change to the visual style. We're trying to keep a "realistic" feel to the game and to sort of keep it grounded. Bigger planets might give the planetary system a caricatured feel. Or, maybe we should give the planetary system more of a "war room"-feel. It doesn't look particularly realistic as it is, so maybe adding more elements to make it look more like a tactical representation of the real thing, would be a good idea.

Now, we simply pick one idea, implement it and test. Or maybe we should use them all? Or something completely different? What do you think?

September 9, 2013

Art of Interplanetary: Maps

The end result
Hello folks, Jukka here again. I'll share a bit of the process that goes into a creating planet texture for Interplanetary.

From chaos to order... Sort of

Usually, when I've made planet textures or painted planets, I've started with either using Photoshop's cloud filters and level adjustments or custom brushes to create the terrain shapes... And if you simply want to make a planet, this works fine, but for Interplanetary, going with just random shapes isn't that simple, since the texture is a factor in the game balance. For example, small continents will restrict player's choice on where he can build and also can make it harder for the other player to hit buildings, although a successful hit on densely built area would have the potential for greater damage.

The way we're trying to ensure that the maps wont be a totally unknown factor in the game balance is by using a specific ratio for land and ocean. So far we don't have much data from testing on the subject, so we simply decided to start out with 50/50 ratio and see how it works, but with this, the players would at least have the same potential area to build on.

White is land... Or was it the other way around...
Because the land-ocean ratio has be to taken into account, using random shapes to create the continents would become much more time consuming. So, we employed the use of this handy planet generator, which allows you to specify how much water you want. I care mostly about the division of the land masses, so I only pull out the black&white landmask from the generator, which I take to Photoshop for refining. 
The shapes produced by the generator are very ragged and "broken", so I shift parts of the continents and islands around and get rid of the excess of  small islands and lakes.

Touch of fictitious realism

Once I have landmasses ready, I block in some background information, like tectonic plates and ocean currents. I'm not an expert on geography so I just wing it. Even if it wouldn't be entirely accurate rendering it lends some logic into how the map turns out. And, of course, since we're not talking about Earth, there would be many, many things to take into consideration, if we wanted to get close to actual realism.

Lots of iron in the soil, or maybe it's dyed red from the blood of vanquished foes.

The next step is to throw in some colors and plan what kind of environment goes where. And from this point on, it's about painting in the terrain and details. For this I have some brushes I made from NASA's satellite photos, which I use to lay in texture. I go over each area several times with different brushes and slightly different colors to make the terrain look more detailed and natural. I also go in with a small basic brush to clean up and add precise detail to certain areas like mountains and river deltas.

If only planets were cubes

Due to the way the planet model is unwrapped, the poles need some more attention to minimize the amount of ugly distortion (there are a few methods for unwrapping a sphere to avoid the pole distortion, but I won't go into more details now as there'd probably be enough there for a whole new post and it is also still something I'm hoping to improve myself in). I use Photoshop's Polar coordinates -filter to wrap the texture into a circle so that I can see how the pole looks and then paint the details I want near the poles and use the Polar coordinates again (this time with the 'polar to rectangular' setting) to bring it back to rectangle shape.

Left: After using polar coordinates Right: How it looks in unity in my test scene.
That's it for now, but feel free to ask questions, and I'll answer the best I can, and see you again in the future.

Check out our IndieDB-page for more goodies!

September 2, 2013

Inside Interplanetary: Random Events

Quite chaotic, but not completely random.
Sasu, here! I design games! Mainly Interplanetary at the moment, though.

Interesting times are ahead for our team: we are about to move into new premises. This, of course, affects our pace a little bit, but it can't be helped. Also, many new expenditures are introduced with the change, but we'll manage somehow. We might chronicle our experiences here some other time, just as a curiosity.

But today, something completely different:

Random Events

There are many things to manage when your planet is being bombed by an extraplanetary threat. It can get overwhelming, especially considering all the other things related to keeping up a planetary civilization. We call these other things Random Events.

At the end of the turn, your Event Log shows all the notable things that took place in the Action Phase between turns. Messages like: "Power Plant No.3 was heavily damaged" and "New Intelligence Acquired" are quite common and self-explanatory, but sometimes, something unexpected creeps in. Whoops, a meteoroid is heading straight towards a city and the Nuclear Power Plant No. 3 had a reactor explosion.

Despite their name, Random Events aren't truly random. The odds of them occurring often have a lot to do with player actions; they are just risks that you have to take. For example, building many Nuclear Power Plants naturally increases the odds of accidents happening and developing a sentient AI will have dangers of its own. Of course, some things, such as natural disasters, tend to happen whenever they feel like it, but they are usually reported on in advance. You can always at least alleviate the damage and a Random Event is almost never truly devastating, unless you really mess up your reaction to it.

A good old forcefield can handle pesky celestial bodies raining on you.
Random Events aren't always bad. Your scientists might make unexpected discoveries or your mines could strike into a particularly plentiful vein of Material. Bad events for your enemy are also good for you. Even seemingly negative things you might be able to turn into profit by reacting appropriately.

It's the reaction to these incidents that count. If, for example, something threatens one of your cities, you should spare some resources to build some defenses around it. Sometimes, you may even get a clear choice of action in the event report itself:
Workers of Mine No. 7 have gone on strike.
A) Start negotiations
B) Arrest the workers
C) Terminate the workers
Two of these options are extremely bad for Morale. Can you guess which ones?

That's the gist of it. At a first glance, this system may feel a little unfair, but rest assured, there is a balance to everything. You win some, you lose some and it's the same for your opponent. It's just another layer of complexity that gives you things to do, even during the quieter times. See you next time!