Recently, I've mostly been working on this orc related RTS game, currently named Runes of Yore. I'm using the Slick library to render client side, and I've been recording progress over here. I was asked on a news post to explain a little more about what I meant by Multiplayer Online Persistent RTS and how that effects networking. Given it's not really Slick related I thought I'd bring the rambling over here.
Ok, so what is it I want to write. Well, most of the time I'm not 100% on this but here's what I think I mean by the terms above:
Multiplayer - more than one player can connect to the game and play against others. I'm not claiming "Massively Multiplayer" because I'm of the opinion that this isn't possible for a non-funded operation. Obviously it'd be wonderful if the game did support this and hence the design has to try and account for that.
Online - the game is going to be playable across the internet. This brings some interesting networking challenges. If a game is only LAN playable you can take some fantastic liberties with regards to latency. On the wonderous entity that is the internet, players will expect to be able to play their friend on the other side of the world without issue. Factor in round-trip times of around 300-400 ms.
Persistent - the game world exists at all time, whether players are logged in or not. The game events continue to happen when you're not involved, so the game state may be completely different when you connect next time.
RTS - (game). The game to be played will be a real-time strategy, that is you control a group of units which you can order to take actions in the game. You use strategy to defeat other players or achieve goals. This gives some interesting problems for networking, in many games the player controls one character - which must be sycnrhonized between the clients. However, in an RTS the player can control 10's sometimes 100's of units - each of these needs ot be synchronized across the network - even with a small number of players we may be talking about 100's of "characters" to sync.
So, ok, thats what I'm talking about - but how is this applied in Runes of Yore (ROY)? The game of ROY places you as a mage in the world of Yore. As mage you're part of one of the four(?) factions of magic. When joining the game you'll see the top level strategic map showing the complete world of Yore and the current state of each province within the world. Provinces will be owned by different factions, one of the objectives being that you help your faction to take over the world.
Objective 1: Take over the world as part of your faction.
Magic in the world is fueled by several things. Primarily the mage's focus is used to guage how many different spells he or she can have cast and maintain at the same time. This magical focus grows with experience which is gained during skirmishes.
Objective 2: Gain experience, improve magical focus.
The second thing that fuels magic in the world is the Runes. (story mode on) Long ago the mages of Yore discovered that the magical stones that grew in the world. With time and concentration the mages learnt that this ornate stones could be absorbed into the body posessing the absorber with a intense feeling of power. Before the mages came to understand the powers of casting, the runes and their absorbtion were seen as a narcotic. It was only as the elders learnt the words of powers did they realise the importantce of these power giving artefacts. (store mode off). The runes spawning is controlled by the "winds of magic" which can be visualised on the strategic map. Like a weather system, the "high pressure" areas will have a higher spawn rate of runes.
Objective 3: Gather runes for power
So, our user is at the world strategic map. They see a province is under attack by another faction and delve into that province. On selecting the province they're taken to a game play screen in which they can place their mage (by casting it into existence) into the province and begin defending.
Defending/Attacking consists of conjuring units (orcs, humans, archers etc) into the world or by throwing direct spell attacks (fireball, protection etc). Within the world the mage can find and claim runes. The process of absorbing runes takes time and focus. The mage must be defended from direct attack while this takes place otherwise the rune can not be absorbed. Hence the mage must use their units to run interference while they take the rune - getting more magic - allowing the to cast more units and on and on.
The only other facet of the game thats been thought about so far is how your faction takes ownership of the province. The provinces will have a selection of wizard/mage towers. Claiming these will increase your faction standing in a province and potentially give some bonus elsewhere. As you can tell the game isn't what you could call planned out. It's just a seed of an idea that I'd like to see written some day. Friends and I (Endolf, Snodge, Tweety, Dan) have been talking this idea over since I worked at Lucent - whats that, 5 or 6 years ago.
The original point of this blog was to talk about networking issues involved, it seems to have turned into a big of a game design session, sorry about that. So, on to the networking. Looking at the game described above and the descriptions for the terms there are several issues to work round:
Fit's into Project Darkstar quite nicely, don't you think? Well at least the third point does, the darkstar server software should allow me to scale the game later to a fault tolerant architecture. Right now the networking layer is abstract over a simple TCP implementation - however it's explicitly designed with the purpose of porting to DarkStar later.
Looking at the first two we have the same issues as most network games, only on a bigger scale. How can the game sycnhonize a large number of units between clients.
The first approach most people think of is simple sending the state of the units across the network several times a second - thus keeping everything in sync. First, this only works for an extremely limited amount of data. Second this isn't friendly to bandwidth, if you factor in how many players you want to support against how much data you'll be sending a second - the cost of server package to support this become prohibitive for a indie/hobbiest. You could probably get away with it if you just wanted to throw cash away, but big business normally means big player base, so it's no good for anyone.
Another, possibly better approach is the Quake 3 style networking model. Only send what's changed in the world - and compress these changes by concatonating them. If Bob moved from A to B then B to A, Bob didn't move. Compress these packages into UDP packets and spit them out all the clients. Make sure the client sends an ack of a frame number so you can stop sending them changes up to that point. This could work for Runes, but it still seems like too much data to me.
The approach I'm taking with ROY is derived from a method sometimes called "lock step" - that I learnt about talking to Jeff (Sun) and Elias (OddLabs) - obviously this is my understand of it, and not their fault if I get it wrong ;). Each client has a game world, I refer to as a deterministic simulation due to some career background I have ;). The server periodically sends out a message to the clients to tell them to move their simulation forward a step. Each client does so, gathers any requests they have, and sends back the requests and confirmation that the simulation has been moved forward. The server locks until all clients tell it they've moved forward. It then applies the requests it's recieved to the simulation (sending the to the clients as well). Finally it steps the simulation again. The benefit here is that only the original user input has to be sent, so if I move 100 units to 10,10 then only move, 100 IDs and the 10,10 needs to be sent once. Since the simulations running on all clients and the server are deterministic and they are updated in identical ways - they stay in perfect synchronization.
Of course there are down sides to this:
With me so far? We have a server moving it's simulation forward, and client's lagging behind the server a bit also moving their simulations forward but never overtaking the server. There's some jiggery pokery to speed up or slow down clients as they get too far or too close to server time.
When a client submits a request to change the world the server sends it to all clients, with a timestamp of the current server time. Each client recieves it and schedules it into thier simulation. There is no way the client has moved past the time of the request, because they're not allowed to move past the server time. The simulations on all clients and server proceed and stay synchronized. The really nice thing about this method is that if a client lags the only person that notices is that client, their orders take longer to act out. They can also catch up by running their simulation a little faster. All of this with minimum network traffic. Woot! :)
The final complexity here is the fact the game is persistent, a client can join a simulation half way through but have no state to apply requests to. The client has to download the state of the game from the server - no problem. However, we haven't talked about random numbers. The simulation may want to have random influences, but must stay deterministic. To achieve this the random number generator is seeded with a common value for all client. Unfortunately the client that joins half way through can get the seed but can't determine where in the random sequence everyone is. This is handled by reinitialisng the random number generator with a new common seed every time someone connects to the game world.
And that.. is that. What it isn't a brute force approach to network - "hey, everyone has broadband now, just sync everything all the time". It would work for physics - though you wouldn't be able to effect the world instantly.
Ok, apologies for the long blog post, it got out of control. It's been pretty useful for me writing it all down, it's been stuck in my head for a while now. To be honest, I'm not sure if thats really helpful to anyone else but me, but heh, for once my blog works for me :)
Note that the views on this page are not intended to offend. If they do, you might be taking the content too seriously.
2D OpenGL Based Game Library
2D Game Physics Engine in Java
How about a list of the developers doing interesting things in java gaming.
Game Dev Resources
Looking for Game Development Resources? Check out the List!