Lost in the Depths – Postmortem
This is my second Ludum Dare entry, my first being in LD20. For this one, I really wanted to try making a multiplayer game, as I it seemed like an interesting thing to do in 48 hours. My concept was a roguelike game where the player was part of an adventuring party who must escape from a dungeon after things go wrong. Because I figured many people would end up playing the game solo, I also wanted the ability for players to carve messages into the floor (an idea straight out of Nethack, I’ll admit). I was thinking that maybe people would carve hints or some such.
What Went Right
The Graphics/Audio/Networking Library
I was using a modified version of my base code from the last Ludum Dare, with a networking component I grabbed from another one of my projects and added to my base code. It generally worked really well, with few notable problems. I worked out most of the kinks last time (mostly related to applet startup/shutdown). I did have to fix a single performance issue with the renderer, though.
Server Performance
My main game server is running on a small virtual server, and I was worried that it would run out of CPU if more than a few people connected. But so far, it has handled the load very well. There also have been no problems with bandwidth on the server side.
Backend/Threading/etc.
I went with a weird architecture that had a separate thread for each zone (which was a bit pointless in retrospect as my server only really has one core). Still, I’m happy that it works without crashing excessively. Even with a few players connected CPU utilization is low on the server. Also, I was a bit concerned that the communication between the threads could lead to some kind of deadlock, but that doesn’t seem to happen, which is good.
Pathfinding
I wanted to give the player character the ability to path around obstacles, which would make the game more user-friendly. To do this, I made a simple implementation of the A* pathfinding algorithm. Because the pathfinding was server side, I was worried that it would overload the small server. But it actually works pretty well with no noticeable stutters. There is the slight issue that you can order it to path to places where the entire path isn’t on screen, though. Using this trick a player can find paths to anywhere onscreen, even if the actual path runs all over the level.
What Went Wrong
Responsiveness
As any good UI designer will tell you, a good GUI must be very responsive, aka it must respond immediately to user actions. To ensure this, most multiplayer games use client side prediction to create the illusion that the game responds instantly to player actions. However, to simplify things, Lost in the Depths uses a “dumb client” model where all game logic is processed on the server side, and the client serves as a sort of glorified renderer. As a result, any action requires at least double the ping time to the server before the user sees any response. This problem is exacerbated by the fact that the server only runs 4 logic ticks per second, so the request must wait for the server to get to the next tick before it processes it. Finally, there is an error in my code that delays all actions by an additional 1 tick (250ms), which does not help either.
Testing
My design for this game was somewhat complex, probably too complex. I did not have enough time to completely test and balance all the components, and as a result there are several balance issues. Plate armor is grossly underpowered, and robes are probably overpowered, just to name a few. Another issue came up on the last day when I was about to test multiplayer. The problem, of course, was that there was only one of me so I couldn’t fully test actual multiplayer, in an allegedly multiplayer game. As a result, the multiplayer game itself isn’t very well balanced.
Level Design
I’m fairly happy with most of the level design, except for Level 2, the Labyrinth. It is supposed to be a bit of a confusing maze, but the result is way too confusing, and there are too few monsters, making it boring to play. This is exacerbated by the lack of an auto-map, leaving players wandering.
Artwork
In my LD20 entry, a lot of the main graphics were made in Blender, and were of robots, which are a lot easier to draw then people. In this game, I relied more heavily on hand-drawn graphics, and unfortunately, I’m not very good at drawing. It also didn’t help that I ended up making most of the graphics last, and at 3 in the morning.
GUI
Some parts of the game require text input, and my plan was to use the Swing part of Java to get this input. The problem was my graphics library was based on AWT and wasn’t designed to work with other GUI components. This wasn’t a showstopper, but it did take a few hours of tweaking to get this right.
Overall, it was an interesting experiment, but I’m not that happy with how it turned out. Working on a complex entry like this was fun even if the result is a bit sluggish. If I were to do it over again I would simplify the game a bit and focus more on tweaking the network performance to make the game more responsive.