How To Build a Game In A Week From Scratch With No Budget
Intermission – Crisis Management!At this point I realize I'm more than 3/5ths of the way through my schedule, and that I have less then 15 hours left to finish the game. I go through my list of Things To Do, and assuming one hour per feature, it'll take around twenty-five hours to finish it all. That's ten hours over my limit I'm halfway through the time I'd allocated to getting the environment active, and I've not really started on it yet. The project is officially in jeopardy. Going overtime is really not an option I'm allowing myself. Hiring additional help or buying some more code / resources isn't an option, either. Since I'm only counting real "development" time for my 40 hours, I'm already pretty maxed out on productivity – I can't think of any way to be more efficient. Aside from spending a lot of time on the Internet looking for magical free solutions to my problems, I really have no choice here but to cut features, and see what I can do to simplify my design.
While deciding what I won't do (or what I'm dropping down in priority to highly-unlikely status), it's equally important to decide what I absolutely must do – what needs to be made top priority. There are a lot of elements to the planned game that I consider very important – like searching for traps, finding secret doors (well, secret portals now), and unlocking chests. But the core of the game is combat. If that's not there, nothing else matters. So I decide I must focus on that, and getting combat working is top priority. I set a goal that by hour 30, monsters will be working – at least enough that the player can kill them. With my adjusted priorities in place, I move on to continue development. Hour 26 – The Roll of the DiceI work out the core "dice" mechanic, something I've had in mind for about the last week --- how the random chances come into play. Since we're not limited to using real dice, we can make a random number of any range we want. Like 1-33, or 6-17. So what I do for a "standard" roll is a weighted, random roll against the total of the attacker's score plus the defender's score. If the number is above the defender's score, the attacker wins. For example, let's say I have a total attack rating of 15. I'm attacking a monster with a total defense rating of 10. My odds are 15:25 (25 is 15 + 10), or 3:5. So the game will generate a number between 1 and 25, and if it's above a ten, I win. Damage uses a slightly different type of roll. I add the defender's "armor" rating together with the attack's "damage" rating. I generate a random number between 1 and this total, and then subtract the armor rating. If the total is less than one, the defender takes no damage. Otherwise, he takes the amount indicated. So if a monster with a damage rating of 10 attacks the player with an armor rating of 5, the game will roll a number between 1 and 15, and then subtract 5 for the damage. This explanation took more time to document here than it did to write. The dice-rolling code looks like this: from random import randint def StandardRoll(attackerScore,defenderScore): if (attackerScore<1): # If the attack rating is 0, the attack always fails return 0 if (defenderScore<1): # Otherwise, automatic success on defense rating of 0 return 1 roll = randint(1,attackerScore+defenderScore) if (roll>defenderScore): return 1 return 0 def DamageRoll(attackAmount, defenseAmount): if (attackAmount<1): # 0 attack rating? No damage will be done return 0 if (defenseAmount < 1): # Man, don't screw with us with negative numbers defenseAmount= 0 total = randint(1,attackAmount + defenseAmount) total -= defenseAmount if (total<1): return 0 return total Filling out the hour, I decrease the window size for drawing the dungeon to get a slight framerate increase --- the section to the right will now be entirely User Interface stuff. I also make sure the player's movement is corrected for frame- rate. Hour 27 – Building A MonsterI have a lot to worry about to get monsters working. I have to change the game update system to make it turn-based. The player needs a variety of ways to interact with creatures (bribery, combat, spell-casting). The monster has to interact back. There's AI and pathfinding considerations. And graphics! DO I display the monster with the same top-down perspective? I can't worry about all these at once – I need to start small. Just putting a monster in the room and displaying in the correct position on the screen is a good start.
Hour 28 – The Monster Appears, and the Player Has to Change His Armor
Hour 29 – Time to Come Out Swinging
Hour 30 – With this Sword, I Thee SlashHour 31 – Entering the Final Stretch
Hour 32 – Why Can't We All Just Get Along?
In order to save time, I cheat on monsters chasing players through a portal. I just assign a random chance of the monster going through the portal each round. This gives the player a better chance to escape, anyway. Hour 33 – Wandering Artwork
Hour 34 – 35 – Drink Me!
Equipment items are a little tricky. Since I don't have an "inventory" of unused equipment, you can't carry a spare sword around with you. If you pick up an item and you already have another item in the "slot", the game asks you if you want to replace the old item, or cash in the new item for treasure. For items where only a single slot is permitted (like a weapon, or armor), that's not too hard. Wands and rings are more complicated, since those can be in one of several slots. After almost an hour of working on this, I realize that I've got the player running through two menus (one to pick up an item, and another to choose what to replace) for items is really ugly. It's far better to have the game be "smart" about it and reflect these options in a single menu. I end up overhauling some of what was already done, throwing away a little bit of code, to make this change to a simpler system. Hour 36 – HACKENSLASH!
Hour 37 – We Don't Need No Stinkin' Word-Wrap!I create a scrolling "text box" class to display game mechanics information. This is useful both for player feedback and for debugging purposes. Without any user controls (like scroll bars), development goes extremely quickly. It actually takes more time to send it lines of text from various events in the game (picking up items, attack results, etc). Some of my preliminary work back in the first 20 hours is FINALLY paying off - there's a good framework in place for calculating the bonuses for skills based on equipment. All items have a 'dictionary' (a great Python construct) of bonuses and penalties to SOMETHING (the name of the roll). So when I get ready to make a roll, say, an attack roll, I just run through the equipment list and apply all adjustments with an "attack" key. I'll do something similar for spell effects. Next, I work on the menu for opening chests – and decide to simplify it significantly. Why not just assume the player is ALWAYS going to check it for traps, and will ALWAYS attempt to unlock it if it's locked? The extra steps in there are tedious. No sense in having trivial choices floating around. Hour 38 – A Little Bit of MagicI'm frantic now. Three hours left – I have to work on ONLY what MUST be in the final game.
Hour 39 – Crisis Management, Part IIWhat I'm missing:
There is no way I can get these all in with a little over 100 minutes to go. I can handle maybe three or four of these if I'm fast. What is the minimal set of items needed to make a playable game? I decide on the following
The initial room (the one up the stairs) becomes the the "rest" room (pay no attention to the awful pun – aw, heck, it's part of the charm). There will be no monsters in this room, ever. I add a new dynamic entry into the player menu when he's in a rest area – the "rest option." Then I create a routine to "re-initialize" the dungeon while the player is resting. Right now it's a stub. I add the remaining equipment graphics in GiMP. I have no time to make them look any good. I simply draw them in 32 x 32, blur them in areas to hide my awful artwork, and then sparingly add some highlighting so they don't just look like a blurry mess. Now they look like a touched-up blurry mess. For the random equipment generator, I have the game pick one or two random abilities and slap them onto the item, with a possible range based on the player's "level" (Editorial note: Unfortunately, the player's level is never actually displayed on the screen anywhere. D'oh!). Certain items have mandatory effects – a sword has to improve either your attack or your damage rating, armor must improve your armor rating, and a shield improves your defense rating. I add these constraints… and we're now already well into hour 40. Hour 40 – The End Is NearI have no time to create actual unique monster types – so I frantically work on just changing the names and stats of the one monster I have – the goblin. I throw some silly-sounding adjectives in front of the goblin names, and I have them "level up" similarly to the player based on the player's level. I finish up the "re-initialization" routine to repopulate the dungeon while the player rests. I finish up some routines to deactivate monsters that are far away from the player, and to make them become active when the player enters the room. I add a couple more rooms to the dungeon, and then I'm out of time. Post-Development Work: Wrapping It Up With a BowAfter talking with a friend, I'm convinced that I shouldn't work on fixing any bugs except the ones that crash the game. Since the purpose of this project is to show off what can be done in 40 hours, I leave it in that state. There are lots of non-critical bugs: stats aren't being displayed properly in the right-hand panel; I don't think goblin hit points are increasing with level; I'm not convinced monsters are properly de-activating; monsters are ignoring collision detection; treasures are appearing inside interior walls; monsters are ignoring magic attacks from long range… I leave them, and focus on the crash bugs. This means playing the game quite a bit. It's actually pretty fun. Not play-this-game-for-hours fun, but certainly an amusing diversion. Once the crash bugs appear to be mostly quashed, I work on the distribution. Py2exe is supposed to make things ridiculously easy, allowing you to package a Python program as a native Windows executable, including everything you need so that users don't need to have Python installed to run the program. It's not quite so easy as all that. First, it tells me there are missing modules, and the executable crashes in the font code. I check on the Internet, and find that the 'missing modules' are red herrings, and what I'm missing is a font file that needs to be copied over manually. After I do this, I get another crash in the executable. This is much harder to track down. It turns out that I need an icon for the window – something that didn't seem required in the non-compiled version. Once I have that in place, everything works. I run a few more tests – and I seem golden. WHEW! I create a zip file of the distribution (I'm not going to bother with an installer / setup program), and I'm DONE. My week-long project actually took two-and-a-half weeks of real-world, part-time effort. It's definitely not everything I hoped it would be, but I'm pretty proud of what I accomplished: http://www.rampantgames.com/hackenslash.html |
|