Oh yes, the adrenaline is certainly flowing. Today was a hugely productive day; I'm extremely happy and proud of my accomplishments. Yes, yes. I'll get to the details. :)
I put Draffurd in charge of creating a Test Map for any public Alpha tests we do, since the current 100x100 map is a little too big for that sort of thing. Thus I had to continually beef up the map editor with various features/fixes throughout the night. Aside from the bugfixes/minor tweaks, I added in Rect-Draw which lets you draw a rectangular area of the selected tile with the right mouse button, and plotting regular one-by-one tiles with the left mouse button. Not too exciting, but functionality is what counts!
Oh yeah. Been working my tail off the last few days on getting the online play going on Mystery Project. First thing I did was remove the entire class-wrapper I had for HawkNL and used WSockets instead (sorry Hawkers :P). Lost a lot of work, but gained a lot of productivity.
I decided that the ugly method of sending prebuilt structs ('records' in Delphi :P) wasn't preferrable, so I built a small C-style system that lets me built packets by appending data types into a memory stream, and fires it off to its destination at the end. Commands like PB_Clear, PB_WriteByte, PB_WriteString, PB_Send, etc. Works like a charm, and it additionally lets me tack together more information per-packet, such as sending player movement information. In my last online game (circa 2003) I sent an average of Players*(Players-1)*2 packets per second. Now with this system I'm only sending Players*2. That's an exponential increase! Thank markr and hplus of the Networking/Multiplayer forum for that tip. :D
Added in names below your player, too. Guess we can't hide under trees anymore:
Then I hit a massive snag -- a bug to end all bugs. Or something. You see, Delphi has four string types. That's right, four. Borland apparently thought, in their infinite wisdom, that this would be a nice addition. This 'nice' addition cost me several hours of debugging hell, trying to get a darned string sent across the network. I tried WideStrings, ShortStrings, AnsiStrings, and PChars (C char* equivalent). None were getting me anywhere. So I just grumbled and settled for building the strings in the packets character by character, fitting in the string length in the first byte slot. And it worked. And I was happy. Phew. One big bug down.
At this point players were now able to join the game. Not move. Not talk. Not shoot. Just join. Still, it felt good to launch another client and see "Player 1" sit there complacently. Now it was time to work on player movement! What happens on the server's end is it collects movement data from the player (which currently is sent every 500ms) and serverside it sets a flag on that player that they have new movement data. Every 500ms on the server (which is not necessarily at the same time as the client), it builds up a packet consisting of all players with new movement data, and sends it to all players, and resets the flag. This way I don't be sending old data that players already have, further optimising my bandwidth-output.
Had a bug with movement, too. Another biggy. I wasn't thinking straight, and I had something like this:
len := PB_ReadByte;
for a := 0 to len-1 do
pID := PB_ReadByte;
Plr := Players[pID];
if (Plr = nil) or (Plr = Local) then continue
Plr.tX := PB_ReadWord;
Plr.tY := PB_ReadWord;
Plr.tRotation := PB_ReadByte * (360/256);
Plr.Keys := PB_ReadByte;
Can you spot the bug that will occur there in my logic? It sure as heck took me forever, hehe. Anyone who can find it will get a nice big juicy cookie. Hint: it's a logic error. :P
Testing Testing Testing!
I must've run that goshdarn client and server well over 40 times. Well over. And testing with myself isn't that fun. So I decided to poke a recent friend of mine, ShoeStringGames, who I had been helping with his code throughout the evening, and coaxed him into helping me test the game. He didn't really resist. :P
Anyways, I sent the client, and hosted the server. And sat there patiently waiting for him to arrive. If it worked. Let's just say:
(Player names not implemented yet, but that's him, Mr. #1)
YIPPEE! Oh man, I was so happy to see us frollicking around in the fields of a Test Map. I'm still glowing with glee, really. Writing online games I find is the hardest sort to write, so getting this major step down makes me feel great. While it may not look like much, you're looking at packet building, movement prediction, trigonometic movement, pixel collision, animation, and a whole whack of hard work. What can possibly beat that, now that v0.02 is almost done?
v0.03 will have guns. :D (Testers welcome!)