Over the course of the weekend, I’ve been programming on that Death magic Volley game I talked about earlier, and since it’s a multiplayer game. I’ve started out with the bare necessities being “Network Coding”
First off, hats off to all multiplayer games out there. It’s not that difficult a concept to wrap your mind around, but the implementation and the consequences that come with certain decisions can be overwhelming. Right now, I think that it’s mostly a matter of working with it, suffering these consequences and getting better at it.
Over the course of the weekend, my main occupation was smoothening and interpolating the network data a client received from the server for the death ball.
The thing is that a server merely sends snapshots of data to clients, which clients have to interpret as fast and accurate as they can.
There’s a big difference between the server having the luxury of deciding what happens, and the client trying its best to represent the received data in an accurate fashion. The server sends little packages containing snapshots of what has happened to the clients, usually about 40ms apart and a lot can happen in between packages, the ball could have bounced off a wall, or have been hit by a player.
Secondly, the server nor client can guarantee that all packages are sent or received at the anticipated time, so the client has no way of telling how far apart the received packages should lie in game time.
An article I read on server verification ( and local client assumption ) suggested sending a sequence number along across the network that allows the server to authorize certain events.
But why stop at a sequence number? Right now, I have the server send the balls “lifetime” along with a position and direction.
It’s nothing more than a record on how long the ball has existed, and it allows me to pinpoint events and synchronize my data with near exact precision.
Clients also track the lifetime of the object and use the data & time received from the server to set up keyframes on which to base interpolation.
And because the client has a local lifetime it tracks ( and since I’m assuming that this game is not going to be played in space OR any other reason to account for time dilation ) it can use its own update step ( and deltaTime ) to smooth it the motions using the local update times instead of Lerping server data, that can be oddly spaced out at times.
If this rambling seems a bit confusing, think of it as my server sending keyframes to my clients which the client tries to play back at its own speed ( normally the same speed as the server is creating them, but with a tiny bit of delay ).
It can even go as far as that, if I store all the keyframes in a buffer or file, it shouldn’t be that hard to create an entire replay system that allows for rewinds, speedups and slowdowns. But I could be wrong.
Now, I’ve added this lifetime factor to just the ball, and it would be better to send the game’s clock itself. That way I’ll have an easier time sorting bursts of data.
Come to think of it, while working on the game, I keep on asking myself if “Magers” is a fun name for the game. At the very least I think that the player characters should be called Magers.
Having spent an entire weekend looking at balls and capsules bouncing around a level has pointed out to me that I have not properly envisioned a Game start-state. Most importantly being, where does the Deathball come from? And what direction does it go the moment it starts moving?
So for the time being I’ve decided to put the orb in stasis in the middle of the room. Waiting for a first hit to be set in motion. This could mean that players will seek to NOT HIT the ball at all. And to that end, I intend to make the ball a ticking time bomb. Killing EVERYONE if it is not set in motion in the first 10 seconds of the game.
Collision: From the start, I knew that programming multiplayer collisions between players is a fate worse than opening pandora’s box. So I’ve opted out of having players push or collide with each other. Rather I’ve taken a look at the Flow-Field and Flocking behaviour of units in StarCraft II and Supreme Commander 2. I’ve not actually written any flocking or boid code. But I have taken a look at the essence of what they can do which is “they displace each other when they come close” and so, I’ve written it, so that player character models will slightly shift when they get too close. Players do NOT collide with each other.
Combat: As I was chatting with a friend of mine, he asked me if players could hit each other. My first reaction was: “No, I don’t want it to turn into PVP, players can’t inflict damage”. But then I imagined the possibilities of players launching each other. And the only result I can think of is hilarious. So from now on, when a player hits another player, that player is launched backwards. Losing control for a split second. That should at the very least make players keep their distance. I’m still debating if there is a chain reaction or something when a player is knocked into another player. But for the time being I’ll leave it at that.
Knockback: I think it’s best that players get knocked back a small amount when they hit something. This should give the players some feedback on their actions, pulling them in just a bit more. What direction? Away from whatever they hit I think. This does mean that I will have to account for this in the network code.
PS: I need to start adding some clarifying images. I’ll do that later though