Advanced Java Game Development: State Data
Part 1 of this series: Advanced Java Game Development: Introduction
Strip away the fancy graphics, graceful animations, streaming TCP/IP sockets, and eardrum-beating sound effects, and you'll notice that games no matter their genre or complexity amount to nothing more than a pile of bytes. Every player's move and every artificial intelligence decision eventually expresses itself as a change to this core game state data.
Java makes it quite easy to keep an abstract notion of game state.
Ideally, the game state should be a central repository that tells the animation component of your game what it should draw and advises the networking part of your game what to send through the wires. State will be changed and accessed a lot, and thus should be as tightly written as possible.
Java makes it quite easy to keep an abstract notion of game state. Just create a class with all the data structures you need, tap in methods to access or change that data, and you're off and running. By designing state as an object, various parts of the state can quickly be accessed and altered.
Once you've written out the game logic, you'll want somebody to play with. That's where networking comes into play. The core Java libraries make it easy to communicate over the Internet. It's possible to set up an extremely dumb and simple TCP/IP client-server system within minutes. Just create a socket, listen for a new connection, connect the client to the server, and you're off and running.
The big challenge to you, as a game developer, is deciding how much of the state to actually send over the network, what to store in the game client, and how much responsibility to give the server.
The first and perhaps most obvious approach is to forget about servers altogether. If your game involves two players competing, why have a middleman? Just have the first player send her IP address to the second player, create a connection, and then communicate. In other words, treat both clients like their own mini-servers.
This is known as peer-to-peer communications. The beauty of this approach is that there's no server to build or maintain. Also, since there's only one network jump from one peer to the other the speed is nice and quick. But that's assuming there are only two peers. If you have three peers, your speed gets cut down exponentially, since everyone must be able to communicate with everyone else. Four or more people in the mix, and your game begins to feel some heavy pain. Since every peer is reliant on data from the other peers, you're only as fast as the slowest connection. One glitchy or sluggish client can ruin the whole show. That's peer pressure.
There are other problems, too. Without a server keeping track of things, peer to peer connections often fly out of synch. If one of the clients gets confused about the state, you'll have a hard time figuring out who's in the right. This makes it easy for cheaters and hackers to come in and modify the network packets and ruin everyone's day.
It only gets worse. If your game is Tic Tac Toe, you're probably willing to live with the client doing all of the tough work. However, for a huge multiplayer real-time strategy universe, your client will quickly get bogged down with artificial intelligence calculations, physics modeling, data synching, and kick-butt graphics rendering.
Wait, it gets even worse! There are two more spoilers: Firstly, peer-to-peer networking doesn't work via applets -- an applet can not accept connections from remote servers, due to security restrictions. Secondly, peer to peer generally doesn't work over firewalls. The snafu goes like this: Most firewalls mask the client's real IP address with a fake address. If you try to talk directly to the real IP address, the firewall will rudely block any traffic. You can try to require that anybody who wants to play your game open up a specific port for communications, but that becomes an imposition and is not possible on many corporate setups.
Fat Client, Server on a Diet
Okay, so you decided you need a little more server in your life. But there's no need for a server to have everything in it but the kitchen sink. You might want to investigate putting all the game rules on the client and just crafting a small, dumb server that sits there watching the world go by, happily passing along any messages. This type of server is pretty easy to write, and should take up little of its host's processing time or memory.
If you create a good network gaming protocol and a resilient enough client, you could use the same client for a number of games.
The only worry here is that, just as with peer to peer, the client may be biting off more bytes than it can chew. Clients will have to do all the computing work and resolve any conflicts. Once again, it's easy for one client to cheat, or get confused, or send along totally illegal moves.
Also, what if you want a more advanced gaming table? At PlayLink, Inc., for instance, we try to run a friendly sort of place, letting people drop in at any time and play, observe, or wait around to play the next game. Assuming that the game's players manage to stay synchronized, who'll pass along the latest game state to newcomers? If you have one of the clients do that work, you'll have to be ultra-sure that the client has the latest state. It's easy to get wires crossed, and have out-out-date states passed back and forth, tripping up everyone.
Dumb Client, Absolute Server Power
Given all the forehead-scratching hassles that a client might deal with, maybe the best idea is to have the server do it all. The client could be nothing more than a rendering engine that the server controls. This hearkens back to the good old days of mainframes and null terminals.
If you create a good network gaming protocol and a resilient enough client, you could use the same client for a number of games Tic Tac Toe, Chess, Backgammon, card games, etc. Just have the server send down the graphics and the locations at which to paint those graphics. The client, meanwhile, could keep track of mouse clicks and keyboard presses and immediately send that info to the server.
There are a lot of great reasons to do something like this. It's nearly impossible to cheat, since the server figures out all the rules you can easily tell if somebody is clicking where she shouldn't be clicking. You're always perfectly in synch, since the server knows exactly what's going on, and when. This setup also makes it horribly easy to update the game rules and fix gameplay issues one small fix on the server affects every client in the world.