LoneStranger’s Caverns Post-Mortem

Posted by of LoneStranger Designs (twitter: @lnstrngr)
August 31st, 2009 9:46 pm

This was probably the best Ludum Dare weekend I’ve had.  My game was more than just a tech demo or an ‘unfinished’ idea.  Of course, they never are truly complete after 48 hours time; there is always something else that can be tweaked or added.  When all was said and done, however, my entry was a playable game.

Background

The theme was not one that I had put much thought into before it was announced so I really had zero ideas at Go time.  One thing that kept popping into my head was the Kroz series of games by Apogee software back in the late 80’s/early 90’s.  They’re all pretty much the same engine with a new collection of levels, but one was called Caverns of Kroz.  The object of the game is to take your hero through twenty or thirty levels to find or capture some relic.  Along the way you had to run, whip or out-maneuver swarms of monsters and solve puzzles.  I had always thought those games were neat, and it would be interesting to try and ‘recreate’ some of that nostaliga.  Caverns of Kroz didn’t have anything special that made it more caverny than the rest in the series, but I thought I could do better with actual graphics instead of ASCII art.

Kingdom of Kroz

LoneStranger's Caverns level

Top-Kingdom of Kroz, Bottom-LoneStranger's Caverns

Graphics

One of the first things I do in a LD is grab a piece of printer paper and start sketching some objects.  More is better, even if I think I may not use them.  For LSC, I sketched a few doodles and scanned them in.  The designs were done in homage of the original ASCII characters and colors.  For example, my monsters look remiscent of the Ä, Ö and Ω characters.  The first problem I had to resolve was how big to make the map.  Kroz uses something like 60×24, but I don’t really like how smushed that is.  I wanted a square ratio on an 800×600 pixel window.  This led me to pick 16×16 as the tile size, which seemed small to me.   For the first couple tiles, the floor and the walls, I used 16×16 image to create them.  That went OK.  Next I took a look at my scans to turn them into tiles.  I did an overhead view of the player, basically just a head and shoulders.  I created the tile originally as a full 120×120 image with margins.  I colored him yellow and red like the Kroz hero.  I copied the merged image and pasted it into a new document that I then resized to 32×32.  Inside the drawing routines I have it again resized on the fly as 16×16.  The reason for this was that I may want to add a ‘zoom’ feature to the game in the future and it would be great if the images didn’t get pixelated.  I followed the same procedure for all the rest of the tiles.

The style of the art is not much different than the other LD entries I’ve done.  I don’t try to draw the straightest or the best.  I just draw to my ability.  Those are then scanned in and then modified in Photoshop.  Since I shrunk these down, you don’t see the imperfections as much, and maybe that’s better?  I don’t think some people ‘get’ that the imperfect art is part of my style and I think I get marked down for it sometimes.

Coding

This is the fourth time I’m using the same general base code for my LD entry.  I think it shows because I have a hang of it’s abilities and limitations and I can get what I need to get done faster and more efficiently.  Also, each LD I add more basic functionality to it so I don’t have to reinvent the wheel each time, as they say.  Additions this time are an unfinished menu system and a tile/map data structure.

Most everything that I coded worked fairly soon thereafter, even the changes that take 30 minutes in between builds.  I think I had only two major problems: monsters moving over walls and monsters not dying when they move onto the player.  The first problem was because I couldn’t figure out why my collision detection logic was failing for monsters.  And it wasn’t.  I had an errant semicolon tagging along the end of an if statement.  My logic was fine and the if was completing an empty statement.  Then the next line moved the monster anyway.  The second problem was weird in that the monsters would sometimes die when they moved into the player, but not always.  A majority of that problem was due to how I keep track of the monsters.  I have two references for them.  One is in a two dimentional array similar to the tile map.  Either the cell has a link to a monster, or it’s null.  The second reference is in a linked list.  The grid is used for monster-monster collision detection since I only have to check the cell next to the monster for another monster.   The linked list is used when I have to traverse each monster object and is faster than checking every cell in the grid.  It’s actually a great idea but I was trying to solve the monster-player collision problem without actually having a fully implemented monster-monster collision.  It turned out that the monsters were moving into the same spot and the second monster was overwriting the first monster’s entry in the grid.  It was weird but once I finished implementing that code the rest fell into place.

These two problems cost me about eight hours split over Saturday night and Sunday morning.  If I didn’t have those problems, then my game would have been that much more complete.

I didn’t try to do anything too fancy in my code.  I could have spent more time doing things in a more efficient way for the future, but instead I hardcoded some functions just to get it done.  For example, I have eight different functions for the different directions in many parts of the code.  Those could probably be pared down to one in each situation if I passed some variables in.  I’d also like to combine the collision detection and movement between the player and the monsters.  Maybe base them from the same Mobile class or something.

What I did Wrong

Other than those two issues that I mentioned above, there wasn’t a whole lot that I did wrong while coding.  I did have a few too many distractions over the weekend.  My folks came over on Saturday to swim (which is great because it was triple-digit weather) and have dinner so I lost a few hours there.  That by itself wasn’t a problem but when I was actually coding I had the TV on which split my attention.

I also forgot to tie the score in with anything being done by the player.  Not a big deal, since score isn’t really much in the game yet, but it should have added some points for killing monsters and grabbing gems and whips.

Apparently my sounds were a bit harsh.  I used DrPetter’s sfxr to create them, but I must have used some weird settings because they sound fine through my 5.1 speakers, but they are harsh through headphones.  I guess I’ll have to do sound through headphones next time and hope that translates through the speakers.

What I did Right

I think I was helped by trying to emulate the Kroz series of games and it wasn’t because I had a model to ‘copy’ from.  I think the key was that the limits on what I was setting out to accomplish were already fairly firm.  I didn’t have to try to build in some weird functionality for the future, since I already knew where I was ending up.  The other LD weekends started with an idea that was to be flushed out later.  The only problem is that later usually doesn’t come and I am stuck with an incomplete game or a complete ‘thing’ that isn’t fun.

What I Wanted to Do After Last Compo

I wanted to work on my basecode after LD48 #14, and I did that.  I also wanted to scale down my goals, and I think I was able to manage my goals this time around by not setting them too high.  I think it’s a win.

What’s Next?

I’d like to continue with this project and there are a few obvious things I can do.

  • Make the code more efficient and easier to read
  • Profiling execution.  I haven’t tested lots of monsters or animated tiles yet, but it will probably suffer from performance issues.
  • Level editor
  • More objects and tiles
  • Better level file format
  • Continue adding basic functions to the basecode

So Mortem?  This thing’s just getting started!

Tags: , ,


Leave a Reply

You must be logged in to post a comment.

[cache: storing page]