Tag Archives: python

Building Tools

One of the things that makes coding particularly awesome—especially in the case of Python—is the ability to reuse code. If the programmer writes things in such a way as to make them generic enough, he can then take those generic sections of code and apply them to different situations. As one might expect, reusing code that has already been written speeds up development time considerably by allowing the programmer to automate different chunks of the program. To illustrate, let’s put this in the context of one of my apparently recurring themes, doughnuts.

Say you decide one morning that you’re going to start your own bakery. You get the space, buy the equipment and groceries, and refine your recipes. The problem with your bakery setup, however, is that you’re the only employee, which means you’re responsible for everything from purchasing groceries to preparing pastries to dealing with the customers to cleaning up afterward. If you continue in this fashion for a while, you will get things done. In fact, you might even turn a profit if you’re lucky. Unfortunately, though, your business won’t grow very much until you can get some help, and, quite frankly, you’re getting tired.

To take some of the pressure off of you, you decide to hire and train someone to help out around the place. You hire a new kid, train him to do basic jobs like cleaning the seating area and washing dishes, and as a result, free up more of your time to invent, cook, and socialize with customers. Things are going just fine for a while, but you eventually come to realize that your business could be even more productive if you hired a third person to help you with the morning doughnut frying and filling. Side note: jelly doughnuts, you guys. Seriously. Jelly doughnuts.

Reusing code is a lot like the metaphorical bakery. You find a task you have to accomplish pretty regularly, and you farm the work of that task out to a separate process. Either that, or you take a complicated, time-consuming activity and wrap that up in a function somewhere. Here’s an example in non-bakery terms.

I am currently using Pygame for its ability to process keys. When I want to figure out what keys are being pressed, it can look a little something like this:

  1. for event in pygame.event.get():
  2. if event.type == pygame.KEYDOWN:
  3. if event.key == pygame.K_LEFT:
  4. player.walk(x=-1, y=0)
  5. if event.type == pygame.KEYDOWN:
  6. if event.key == pygame.K_RIGHT:
  7. player.walk(x=1, y=0)
  8. if event.type == pygame.KEYDOWN:
  9. if event.key == pygame.K_UP:
  10. player.walk(x=-0, y=1)
  11. if event.type == pygame.KEYDOWN:
  12. if event.key == pygame.K_DOWN:
  13. player.walk(x=0, y=-1)

If you didn’t bother reading all of that, I don’t blame you. I certainly don’t want to have to write it every time I want to create a game. To solve the problem, I created a code module whose job it is to carry out those basic functions, and all I have to do is give it two pieces of information: which key should call which function, and when the module should check to see what keys have been pressed down. The code for the first part looks like this:

  1. keyboard_handler.register_keydown(‘left’, player.move, x=-1, y=0)
  2. keyboard_handler.register_keydown(‘right’, player.move, x=1, y=0)
  3. keyboard_handler.register_keydown(‘up’, player.move, x=0, y=1)
  4. keyboard_handler.register_keydown(‘down’, player.move, x=0, y=-1)

And when I want to have the program check which keys are down, I just do this:

  1. for event in pygame.event.get():
  2. keyboard_handler.process_key_events(event)

With a single call to process_key_events, I tell the program to go look at my shiny, new keyboard handler and run all that bloated code you saw above. Instead of having to type 13 lines of code, I now only need to type 6, thus slashing my required code by more than half. This makes my programs easier to write because there is less writing to do. At the same time the code is easier to debug because there is less of it to read. Productivity 1, frustration 0.

I’m excited to be finished with the tool-making process—at least for now. I’m equally excited, however, to have designed something that can really speed up coding and simplify development, not just for myself, but for anyone who wants to code in Pygame. Che Martin of Blind Adrenaline Simulations once told me about two weeks he spent building a module to make jaws speak in his games. At the time I couldn’t fathom spending two weeks coding something that wasn’t directly connected to a game. Now that I’ve spent 8 days creating my own tool to build into all of my future projects, though, I understand what he meant, and I appreciate the experience.

Downs and Ups

I looked at the website today as Randi and I were searching for the renewal email, and it occurred to me that I haven’t posted an update in over a month. In fact, it has been closer to two months since I posted anything, and as of my last writing, I was still hard at work on boxing. I think the biggest reason for my absence has been that while a lot has happened, not much has been accomplished. Let me try to explain.

My last post was full of optimism about the coming break and the progress I would make on the boxing game. As soon as school finished for the year, however, I managed to contract a really nasty piece of malware, and I found myself having to reformat my computer. As I was upgrading from Windows XP to Windows 7, however, I neglected the fact that the new install didn’t wipe out the old one, but rather installed alongside and throughout it. Thus, I wound up with a tangled amalgamation of two operating systems with a virus lying dormant somewhere in the ruins of the Windows XP side.

No problem, I thought. I’ll just reformat again.

This time, the reformat and reinstall went off without a hitch, and I figured I was Scott free. Side note: I bet there is totally some dude out there named Scott Freeh, and he probably gets a lot of grief from people. Poor guy. Anyhow, I set up Carbonite to start restoring my files, but a mislabeled checkbox caused the program to start dumping the entire backed-up contents of my old format into my pristine new one. This meant that I had directories for Windows 7 that were bare and desolate, and I had jam-packed directories that followed the Windows XP folder structure, all of which were hopelessly entangled once again. Because several gigs had been dumped into my pristine format before I realized the error—that’s what I get for restoring overnight—there was no way to quickly fix the problem.

You can probably guess what I ended up having to do yet again.

Amongst my 3 reformats were all the things that ordinarily occur throughout the holiday season: traveling, dinners, spending time with family, etc. As a result, New Year’s came and went, and I hadn’t written a single line of code. I ended up going back to work on January 2 having accomplished absolutely nothing during the Christmas break.

And then came the coding craziness. I finally realized, after banging my head against the problem for some time, that there was no immediately plausible way to carry out key commands that utilized multiple key presses. For example, holding up arrow and pressing a could not throw a left hook to the head using my current library. So I needed to find a new library—one that would allow me to press multiple keys simultaneously.

First, I tried looking for python-based solutions to the problem. The only solution I could find, however, was the Pygame library. In talking to other audio game developers, I found very little support for Pygame, with criticisms ranging from speed of execution to a lackluster sound library. When I brought up Sound RTS as an example of a great game that just happened to be written in Pygame, it was pointed out to me—accurately, I might add—that even it suffers from very slight execution lag on things like key presses.

So, scared off by the boogie monster of latency, I started looking at BGT, the audio game development toolkit written by Philip Bennefall of Blastbay Studios. Because the core components of BGT are written in C++, execution of almost anything is incredibly speedy. Another feather in its cap is the fact that Philip is an INCREDIBLY NICE GUY! I cannot stress that last point enough.

However, I soon discovered two problems with using BGT, neither of which had anything to do with the language itself. The first of these was the fact that I had already spent a year learning to program in Python, and I was loathe to throw away all of that practice and knowledge in favor of a different language. The second was that I had incredible difficulty switching from a Python mindset to a BGT one, and as almost everyone who has ever rerolled their character and become a newbie again will tell you, starting over sucks.

In order to reconcile the conflict in my head—Python versus anything else, speed of execution versus speed of development—I did what I should have done a long time ago. I signed up for the Pygame mailing list and started asking questions. I received a number of intriguing answers, but probably the best of them went something like this:

You’re so busy spending all of this time worrying about speed and lag and all of these other things that haven’t come up yet that you haven’t even written a single line of code. Many, many people have written great games in Pygame, and they haven’t run up against a speed barrier. So program something—anything—and if you start having problems with speed, there are work-arounds for that.

When I decided to adopt this mindset, it opened up a whole new world of possibility to me. Instead of seeing potential difficulties as obstacles, I started seeing them as barriers to be broken down. Instead of looking at things through a lens of negativity, I started finding more positives. So what if Sound RTS has a tenth-of-a-second lag on key presses. It’s not like that style of game requires lightning reflexes anyhow. And I didn’t even notice the lag until someone pointed out to me, so what did I care? It’s still a great game.

But I didn’t want that lag, because the kind of games I’d like to develop will require lightning reflexes. So I started looking into why it existed in the first place, and almost immediately, I found the answer. It turns out the chief Python critic on the Audyssey list was right, though it chaps my hide to admit it. The sound support for Pygame isn’t the greatest, and when used in a certain way, it can create all sorts of slowdown in programs to the point that, if you make the sound buffer size too large, it can take over a second to modify any currently playing sounds. Huge problem, right?

Well no. If the Pygame sound module slows things down too much, don’t use it. Problem solved! Seriously, it’s that simple!

And just like that, I’m back in business. I’m using the Pygame keyboard module to handle all of my key presses, and I’m stoked about the things it can do:

  • It keeps track of each key press that the user generates, and it gives the program the opportunity to act on these. If, when looking through the key presses, the program finds an “up” in the list, it can run through its analyses and decide to make the player jump.
  • It has a key_pressed function which allows the program to check what keys are held down. If, while walking across a level, the player holds down the control key, the get_pressed function will see this and make the player run.
  • It tracks when players release keys, and it can use this information to call additional events. If, for example, I wanted to program a laser gun that charged itself up as long as the player held down the control key, then fired when the control key was released, I could do that!

As for the sound library, I just switched back to using sound_lib, the library that’s served me well through both Block Party and boxing. It has all of the functionality I need to program with none of the lag, and if I need it to do more, I can tweak the programming myself.

With all of this in place, I have one last hurdle to overcome, and that’s learning to write comfortably in Pygame. I’ve made a car engine that revs up and fades as you press the up and down arrow keys and steers from side to side as you press left and right. I’m in the process of making a character that walks from left to right and back when you press the left and right arrows. These things still don’t feel fluid to me, though, and only time and experience will change that.

What does this mean in terms of game development? Sadly, it means it’s going to take a little while to get things back off the ground and headed in the right direction. More importantly, however, it means that game development is still progressing. Those of you following the twitter feed will note that activity has started to pick back up as I run Pygame through its paces. Things will get moving again, but they may take a bit longer than any of us would like. I’m not out of the race, though. I can promise you that.

Punching Through

                I love bashing my head against a problem until I break through the barrier. The actual bashing part doesn’t always make for an exciting evening, but I would be lying if I said the intellectual challenge wasn’t enjoyable from time to time., The best part is when everything clicks into place, and you realize you’re learning something!

                Amidst all of the little challenges life in general has to offer, I’ve been working in my free time on how to make punches work better. As I wrote in an earlier post, I want to build in actual punches and boxing mechanics to make the game both more realistic and challenging. In order to do that I decided to go back to the drawing board and create one set of punches that would apply equally to both the player and the opponent. The hard part was: how could I write the code elegantly and simply enough that it won’t be a mess when I go back later to refactor it. How could I make, for example, code apply to either the player or the opponent without specifically checking whose throwing the punch, defending the punch, remembering the punch, and so on? As it turns out, the basis for the solution is incredibly simple, and I owe Aaron Cannon a huge debt of gratitude for bringing it to my attention.

                Basically, it goes like this: when you pass a complex object around in Python, you don’t actually pass around copies of the object; instead, you pass along a reference to that object. It’s like telling your co-workers, “Hey, I brought doughnuts for everyone. If you want them, they’re in the break room.” In this way, anyone who wants to modify your object—or steal all of the jelly or cream-filled doughnuts like that jerk Bob from accounting—can do so easily. This turns out to be an awesome thing, because it means I don’t have to keep track of lots of copies of my opponent and player. Instead, I create one player and one opponent, and then I just let all of the punches, stats, and everything else know where to find them.

Also I want doughnuts now.

                Figuring out how to make all of this work has been a thorn in my side for the past few days, and I’ve been pondering it in spare moments. When the solution finally came to me tonight while I was running on the treadmill, I couldn’t wait to write it down and make it work. And wouldn’t you know, it works like a charm!

                I’ve missed this kind of zeal—this excitement—in programming for a long time, and I’m glad it finally came home to roost. It’s like turning the corner and seeing a whole new vista spread out in front of you, and the view is breathtaking. I almost wish I could call in sick to work tomorrow so I could keep working. Almost.

                Oh hey! Did you guys know Christmas is coming up? You might have heard something or other about it. Well in addition to all of the awesome family and togetherness and good cheer and celebration that the Christmas season brings, it also gives me two weeks off of work while the students travel home to see their own families. And you know what that means …

                Two straight weeks of Swamp!

                …

                No wait. That’s not it. Is it?

Streamlining

                I made a fair bit of progress on the boxing game today and implemented a major change that should make for a better built program. In short: I switched opponent behavior from a threaded timer-based system over too one which uses the WX Timer object. In long:

                When I first started designing the game, I built a system which queued up all of a round’s behaviors at one time. Each of the punches, taunts, and unblocks basically received their own alarm, and when that alarm went off, the event attached to it was triggered. While the program ran smoothly  enough, it always gave me a huge number of trace backs—or errors—every time I prematurely shut it down. Each of the separate alarms was known as a thread, and when the program was closed, any threads that hadn’t yet been executed were cut, resulting in an error message for each one. I’m not certain if this really did anything bad, but it sure looked disconcerting when it happened.

                Partially because of this, I switched the program over to a new system today. Using a module called WX, I built in support for a single recurring timer that will handle all of my event management rather than placing the responsibility on dozens—sometimes hundreds—of separate timers. This single timer runs every tenth of a second, and when it runs it makes various checks to determine whether it should throw a punch, taunt the player, adjust fatigue and health, end the round, and a whole host of other functions.

                The second benefit to this new system is that it allows for on-the-fly changes to be made, including the aforementioned behavior system that people asked for. Because all behaviors aren’t laid out at the beginning of the round, they can be changed as needed.

                In order to really test things, though, I need to go back to the opponent creator and start building in support for the new system. In fact, I think I’ll start that now.

Pouring

                I guess I always knew somewhere deep down that there were going to be down sides to programming, but of late they’ve been cropping up in some very unexpected places. I expected to have to face some of the legendary heckling and complaining that almost all developers have encountered, but the community has been blessedly understanding and kind about the whole thing.

                Perhaps I’d better back up a bit here. A few weeks ago I received an email on the Audyssey list from a user who told me that Block Party wouldn’t run on his system and that he was getting error X. Having no idea what error X involved, I put out feelers, and I was told to put a specific line of code into the main module that would fix everything. I placed the line of code where I was told and uploaded the new executable to the site.

                I then went back to work on the boxing game, building in support for multiple punch types and perfecting existing sounds, only to discover that my current keyboard code didn’t support things like holding down keys. If I wanted to press up and A at the same time to throw a left hook, I could, but I couldn’t hold up and tap A at some future point and achieve the same result. Some people might argue that it makes no difference, but for some reason, the lack of being able to hold keys feels awkward to me, and I’d like to be able to fix it.

                So I started working on a solution. I went out and started researching Pygame, a Python library specifically designed for game development. (Some of you may recognize Pygame as the library used to code Sound RTS.) I figured if I imported the Pygame keyboard module, I could build in support for a lot of the keyboard-based stuff I really wanted. There’s also the added bonus that Pygame supports mice and joysticks as well. But just as I started my research, life started happening.

                First came the emails from the Audyssey list telling me that the new version of Block Party wouldn’t run on 64-bit Windows 7. I have to pause here to point out that the emails I have received thus far have been extremely cordial, and I cannot stress enough how much I appreciate that. After the emails, though, came a mountain of work at my job, and after that came some previously-made engagements which have taken up a significant chunk of my time.

                Today I finally had time to sit down and research the problem, and I came to the conclusion that I needed to roll back to the previous version and find another solution to the problem, only to receive more kind emails from people telling me that They—the emails’ authors—could now happily run Block Party’s latest version on their computers. Argh! Now I have to trouble-shoot Windows 7 64-bit!

                The most interesting and awesome thing about this whole ordeal is the response I have received from the blind gaming community. As I wrote earlier, I have received no negative emails about Block Party’s refusal to play nice with everyone’s computers. Especially given some of the epic flare-ups which have previously occurred on the Audyssey list, I was expecting to have to dawn my ceramic suit and dive for cover to escape the flaming. Instead, everyone has been very understanding and patient with me as I research and learn in an attempt to solve the problem.

                Which is probably why I feel so bad.

                You all have been waiting for months for the boxing game—almost as long as I have. I have been giving out teasers and snippets from time to time and writing about my progress in various forums, but real, tangible results of this project have not been forthcoming. I know deep down that there will be setbacks; I’ve written about them in a previous post or two, but I hate that they’re occurring at all. More than anything I want to finish this game and release it to the general public, but for some reason things just keep coming up. Maybe this is all a bit melodramatic, and maybe I’m just on edge after the whole Qwitter thing, but I keep feeling like there’s a clock hanging over my head, and when it strikes, there goes my credibility. The funny thing is: it’s not you; it’s me.

                Holy crap. I have to stop writing now before something even more cheesy comes out of my keyboard: “maybe we should just be friends.”

                Anyhow, thanks for letting me get that off my chest, and thanks for being so awesome about the whole thing. I promise I’ll make the end result worth it, and we’ll all have a lot of fun.

A Worthy Challenge

                When you start out programming, people tell you it’s a good idea to start with something small. It’s why almost all program tutorials start you out with printing “Hello world!” to the screen. In the case of games they tell you to produce Guess the Number or a Space Invaders clone or something equally unsatisfying from a gamer’s prospective. But in spite of this good advice, the starry-eyed gamers want to produce something exciting, something revolutionary, and they either wind up failing or producing something ugly. I’m a big believer that you only truly fail when you give up, so I don’t believe I have failed to produce a great game. I do think, though, that the current incarnation of boxing is pretty unattractive.

                A big part of the reason behind this ugliness is that I started with an extremely limited skillset. I could only conceptualize how to produce the kinds of things I wanted with some very limited tools, and my code and design reflect this fact. It’s why I’ve been writing on the Twitter feed recently about how I’ve been going back through all of my modules and stripping out/refactoring a lot of the detritus that has collected there.

                But as my knowledge has been evolving, so has my vision for the direction I’d like to take the boxing game in, spurred on in no small part thanks to some bona-fide geniuses on the Python tutor list. When I look at their code examples, their suggestions for different work-arounds, their ideas for alternative—and better implementation—I realize that I’ve only been scratching the surface of what this game is truly capable of. I don’t, for example, have to stop at four basic punches, especially when boxing offers a whole host of new ones. I don’t have to limit the game to blocking and not blocking when I can easily build in slipping, bobbing and weaving, stepping in, and so much more. Did you know that a classic boxing combination is to throw an uppercut with the power hand, then follow it up with a devastating hook with the other hand? Apparently the first punch lifts the jaw into prime position, and the follow-up punch lays the opponent out. I didn’t know that before yesterday, but now that I do, I want to build it in! Now that I have more tools at my disposal, I can do that—and what’s more, I can do it with relative ease.

                This probably comes as a bit of a disappointment to people who were hoping I would release the game yesterday, but I promise that the mechanic change will make the game a lot more fun for all involved. Instead of just mashing a particular button repeatedly and getting away with it, players will have to make strategic decisions and play off of their opponents. They’ll have to learn which punches to lead with and when to throw a proper combination, and the opponent will be learning right back. If they throw the old one-two too many times, the opponent will start to anticipate it.

                While I think future players will really appreciate these changes, I’m also making them for my own sake. Nothing is more frustrating than spending lots of time on a project that is no longer of interest, and I don’t want to become frustrated with the boxing game. I want this to be an exciting journey for all involved, but since I’m steering the ship right now, I need to make sure I don’t fall asleep at the wheel. Thankfully, we’re bound for Tahiti.

                And I’d better stop with the nautical metaphors.

                Oh hey—random thing: Did you know that coffee gives you super powers? No, really. I use it all the time when coding to help me stay strong. In fact, I might go have some right now!

Changing the Rules

                Years ago I used to run around the neighborhood with the local kids and play some variant of “guns:” cowboys and Indians (we weren’t racially sensitive), cops and robbers, spacemen versus other spacemen. Even though most of us were on board, there was always that one kid who just had to bend the rules a bit.

                “Hey,” you’d yell, blowing imaginary smoke off the barrel of your plastic revolver. “I shot you!”

                “Nuh-uh,” he would always return. “I was wearing a bullet proof vest.”

                I understand now, after a hasty Wikipedia search, that bulletproof armor did in fact exist during the 19th century—at least as far as Wikipedia claims. According to the article, it existed some 300 years before the Civil War. But as kids, we and the bulletproof wannabe thought of ballistic vests in the more widely recognized, modern sense. As far as we were concerned, he was cheating, arbitrarily changing the rules when the game was already in progress.

                I always look back on my body armor memories and smirk when something completely new and unexpected comes along to shake things up. (By the way, My Body Armor Memories would make a great band name. Feel free to use it.) In the case of programming that game-changer was decimal numbers, referred to in computer parlance as floating point numbers. As far as your computer is concerned, writing floating point numbers is hard. The mechanics of why this is the case are a bit obnoxious, but suffice it to say that when you see 0.1 on your computer screen, the computer isn’t thinking of the same number. If I assign the number 0.1 to the letter x, then tell Python to print x, I’ll get a nice, pretty 0.1. If I tell it to print 0.1 to 25 decimal places, though, I get 0.1000000000000000055511151. This difference of numbers can cause major trouble in coding if you’re not aware of it, and just like my cheating neighbor, it caught me completely off guard.

                In trying to program the opponent creator, I designed a system that checks the time an event is scheduled to occur against the user’s current time. If the two numbers match, a sound is played, and the user can edit events. When I tried to move a tenth of a second at a time, however, I found that my comparisons weren’t matching up. I tried to debug the code with print statements, and things looked like they should have worked.

position 2.8
position 2.9
position 3.0
position 3.1
Event placed!

Even when I pressed the right arrow, then pressed the left arrow to return to 3.1, things looked like they were working.

position 3.2
position 3.1

                But at 3.1, I should have received a message that said “sound method called.” I didn’t, and the reason, as I discovered after 8 days of struggling with the code and obtaining tips from experienced programmers, was those blasted floating point numbers. A simple print-out of the three punches I had entered shows why.

{3.1000000000000014: {‘punch’: {‘strength’: 0, ‘height’: ‘head’, ‘can_stun’: False, ‘can_break’: False, ‘speed’: 1, ‘side’: ‘left’}},
2.1000000000000005: {‘punch’: {‘strength’: 0, ‘height’: ‘head’, ‘can_stun’: False, ‘can_break’: False, ‘speed’: 1, ‘side’: ‘left’}},
1.0999999999999999: {‘punch’: {‘strength’: 0, ‘height ‘: ‘head’, ‘can_stun’: False, ‘can_break’: False, ‘speed’: 1, ‘side’: ‘left’}}}

                When I enter a check between the time of an event and the user’s current time, they will never match up, because in no world is 3.1 equal to 3.1000000000000014. But completely unaware of this oddity in computer programming, I scanned through my code perhaps a dozen times, grew incredibly frustrated, and even considered a complete re-write. As Christopher Toth later told me, “This is the kind of thing that makes perfectly sane programmers gibber in fear.” How right he is.

                The code is working properly now. I found I could overcome the problem by rounding the floating point numbers I encounter, but the solution was a long time in coming. I never realized when I started out that some of the hurdles I would face in learning to program would require a grappling hook and a spotter to overcome. (This situation also shows why I do not give release dates or accept pre-orders.) Even so, the trial is passed, and I have some talented programmers to thank for it.

Picking up the Slack

                When I wrote my alpha post this past Sunday, I was on cloud 9. (“alpha post” meaning my post about the alpha release, not the best, strongest, and most desirable to a mate post I’ve ever written) While I’m still on at least cloud 8.5, I also recognize the amount of work I have yet to do, and it starts with py2exe.

                Py2exe is a module written for Python that lets one compile code into an executable file for easier distribution. It means that I’ll be able to make a .exe file instead of having all potential testers download python along with all the associated libraries and code. Of course, using py2exe isn’t as simple as typing in a command. Instead, I am required to write a setup file so that the code can be properly compiled with this or that parameter. And that’s where the fun starts.

                Right off the bat, things get a little confusing:

  1. from setuptools import setup, find_packages

I know that we have a module here called setuptools we’re pulling a few things out of, but what’s that comma doing there, and why is it there? What is find_packages? How will I use it, and why am I importing it? The same goes for all of this:

  1. import py2exe, innosetup
  2. from glob import glob
  3. import os
  4. import shutil

And things don’t necessarily get easier from there. Now I have lines that I think I understand, but since I don’t know what the above code accomplishes, I don’t even know if I’m right. Lines like:

shutil.rmtree(‘dist’, ignore_errors=True)

I think that removes a certain directory from the installation, but I’m not entirely sure. I also don’t know why I would have errors I want to ignore.

This one is kind of confusing too:

return [ (”, [‘hope.html’, ‘settings.confspec’]), sound_lib_data()]

When Chris first started teaching me to code in Python, one of the biggest bad habits I had to overcome was cutting and pasting code, especially when I didn’t know what it was. Almost nothing, I have learned, is worse than putting a bunch of code into a program when I don’t know what it does. First, it screws up my ability to troubleshoot problems if something goes wrong with that code. Second, it prevents me from learning valuable lessons about how various Python libraries work.

There are tons of Python libraries out there that can perform metric tons of different functions. While I know that I don’t need to learn each one of them in order to be successful with programming, I understand it will be important for me to learn the most commonly-used ones so that I can work them into my existing code. I won’t say this isn’t frustrating at times. I love learning new things, but right now I just want to get back to programming the game. Still, if I want to be able to churn out product faster and more efficiently in the future, I had better go through all the steps now.

One more Tool

It’s days like today that remind me how much I have yet to learn. Such days are frustrating because they keep me from making tangible progress on the game, but they usually teach me something valuable that will come into play later. Today, it was distutils.

About a month ago I started developing a menu object that I’ll be able to carry with me from game to game. It’s a sweet little piece—if I do say so myself—with the ability to set wrapping or not, pick custom music, use either text to speech or sounds, and a lot of other things. When Chris looked it over, though, he pointed out some of its immediately apparent errors. One of the most glaring was the fact that the menu code lacks any kind of support for sub-menus.

Chris incorporated my existing code into a package that we will be able to install directly into our respective python libraries, and we have since started working to improve it. However, upon downloading the package to start debugging it today, I realized that I have no idea how to read a package. Why is there a dist folder? Why is there a build folder? Why is there a lib folder? Why are there two versions of the code, and which one should I be modifying?

To answer these questions I went on a Google hunt, and I eventually came across the distutils manual, a detailed document explaining more than I ever could have hoped to learn about packaging and installing Python modules. The technical nature of the document, however, forced me to run a bunch of secondary Google searches to figure out what the heck I was reading about. It’s like being stuck inside a giant see-also loop in the dictionary.

The end result is that I’m a bit smarter than I was before, and I have a better idea of what is required to put together reusable code, but it also means my development was on hold for a bit today. On the bright side, I won’t have to learn this again, and I now have one more tool in my toolbox.