Tuesday, June 21, 2005
A Recurring Problem
I've bogged myself down on fixing up the timing in the game because I have this annoy tendency to over-design stuff. I spend gobs of time designing and coding and refactoring and throwing stuff out and starting from scratch, ad infinitum. It's one of the big reasons that I've never gotten very far in any projects of my own, and that I'm hoping to break myself of by focusing on Egoboo.
But I still do it. Darnit.
See, right before I got started on replacing the timing code I remembered this cool article I'd read in Game Programming Gems 4, by Noel Lopis. He outlines a solid time keeping solution that helps smooth out spikes in the framerate, and enables you to create timers that run at different multiples of the main game clock, letting you do neat special effects like slowing down animations in special effects, or speeding up a hasted character, or Oh My God. It's a freaking clock, Jon.
Don't get me wrong, it's a nice and flexible time keeping solution, but for Egoboo, it's probably overkill.
So anyway, I get to implementing it, transcribing it down from C++ as I go, and I think "this is a pain, I should just use C++", so I compile the game code as C++, fix the errors that crop up because of it, and generally making a mess of things instead of leaving well enough alone.
But being ridiculously perfectionist, I'm not happy with moving the game to C++, so I revert all of that nonsense and do it in C. And now that I've done all that, I look back to my original problem (making sure that the game logic updates on a regular basis, instead of as fast as it can), and this whole new awesome system does zilch to solve it. Which is what I get for getting enamored with a solution and not thinking it all the way through.
Anyway, I'm going to use the abstracted clock part of it, because it's handy (I can easily use higher resolution timers than SDL makes available with it, and it could be useful for demo playbacks at some point). Dunno about the timer portion of it. I'll leave it in; there's no real, point in removing it, and it may be handy in the future. For the problem I'm actually supposed to be fixing, I'm going to introduce the concept of Tasks into the code.
Pretty much, anything that would be updated at a regular interval would be called a Task. Obvious examples would be the main game logic update, or collision detection, character animations, input gathering, network updates, etc. A not so obvious example might be updating the frame rate display. A Task will simply be a callback function that takes the elapsed time since the last time it was called as an argument. You'd register a function as a task, along with it's desired update interval, and call task_updateAllTasks() each frame. Those who's update interval has come will be called.
There should also be the ability to pause tasks, and obvious remove them at some point. So that's what I'm going to get started working on now. Lets see how many times I give up and re-write it 'til I'm happy.
Saturday, June 18, 2005
Wednesday, June 8, 2005
This release adds networking back into Egoboo. (There was once a link here, but no longer).
When Egoboo was written back in 1998 (I think), Programmer X added support for playing over a LAN using DirectPlay. Since that's a Windows-only technology (that's going the way of the dodo, as I understand it), it was removed when the game was ported to SDL/OpenGL. No one has bothered to try porting it until now.
In 2001 (I think), Aardappel started working on a game engine called Cube, for which he put together a simple but robust networking library called ENet. That's the library I chose to port the DirectPlay stuff over to.
For the most part, it's been pretty straightforward. The functions used to put packets together really didn't change, except for adding code to make them endian safe. Sending packets was just pointing them through a different API, the concept was the same. The difficult part so far has been getting games started (with a host & client computers), and copying files across the network.
Egoboo stores saved players as complete copies of the object directories they were created from in the first place. Same thing with any inventory items a character might have. Because of this, players tend to be at least 600k big, and contain 60+ files each. As it stands now (and did back in '98), each remote/client/non-host computer copies each character & item that local players (of which there can be 2 or 4, I'm not sure) will be using up to the host/server computer. Once the host has collected all of the files from all of the clients, it sends them all back out again so that each client gets a copy of all the files necessary. So far, this has been preventing me playing over the internet. Too much stuff to send.
Getting it working was actually fairly easy, though it took me awhile to realize it. The original Egoboo code would split the files up into 2k chunks and send them across one at a time. I assumed I'd need to do the same thing with ENet. I spent days trying to get it working reliably until I took a look into the Cube engine's code (since that's where ENet came from) to see how it was done there.
Cube just shoves the whole file into one packet and lets ENet sort it out. That seemed way too easy. But it worked. Shove a file at a time into an ENet packet, send it across, and have the other computer send an OK packet back when it successfully receives the file. Easy.
It doesn't entirely work perfectly, but I am getting files across reliably a lot more often, and with a lot more speed, than I was by splitting them up into chunks myself. I still have more work to do to make it totally robust, but it's getting there.
Getting the game started hasn't been too difficult, by comparison. DirectPlay handled a lot of the work getting games started up before; it has built in lobbying support and whatnot. Cube doesn't handle that, so I had to rework things a bit so that you can specify a computer to connect to. That part really wasn't all that hard, I just had to cut out the menu parts that refer to the lobbying functionality and add a new one for connecting directly. It's kludgy right now; you have to specify the address of the host computer in setup.txt before you run the game, but it works.
And with those things in place, the game now connects and runs on 2 computers over a LAN. (I've left it deliberately at 2 players for now, I haven't felt like figuring out how I should space out sending files to up 8 players at once yet.) The game runs ok, but the speed at which network updates are sent & received is very dependant on the speed of the computers, so it tends to get out of sync really quickly at the moment. So next up, I'm going to look into standardizing the rate at which the game performs it's various updates. Tune in next time!
Labels: egoboo
First Post
To whomever may be reading this: Hi, and thanks for stopping by. I'm putting this blog up as a kind of diary of the time I spend working on Egoboo. I have a number of changes and improvements I want to make to it, and as I do so I'll probably be talking about them quite a bit here.
I'm sure I'll also babble about other things that cross my mind.
So if you're not interested in game development, or watching a n00b thrash about trying to figure it out, this isn't the blog for you. :)
