I’ve continued working on my prototype games using my overengineered game engine (ffld). In the last few weeks, I’ve started work on improving how I can build interfaces for games, as well as packaging the game into its final form. This post will discuss the latter.
My plan is as follows:
Code all of my project on Linux, using virtualenv and pip to install smaller dependencies
I’m a big fan of using virtualenv and pip to control my dependencies. One really nice thing is that I can keep my various projects and libraries in separate directories, then install them into eachother as necessary without having to move them around. If I install using “python setup.py develop”, then I can make changes to one library and have those changes instantly usable for another project (no need to reinstall the library). This means I don’t need to worry about moving directories around, or setting up symlinks, or anything like that. pip also makes it very easy to install a specific version of third-party software from pypi on a per-project basis.
Use two Windows virtualbox machines
To build to Windows, I’ll need one machine to actually perform the build. This machine needs to have all the software that is used to build the game. After the build is complete, it is packaged into a zip file, and I will transfer the zip file to a second Windows machine. This second windows machine has a “clean” build; it has nothing installed on it (no Python, no Pygame, no Microsoft Redistribution Package). Basically, if my build works on that computer, it should work on most computers of the same Windows Version.
I will once again use virtualenv and pip on Windows to handle all the dependencies. Of course, this will need to be a separate folder, but I don’t need to copy any code over since I can still access the code from a shared drive.
I’ve never had much luck with py2exe, so I tried out Pyinstaller, and it has worked pretty well. (Note: the name “pyinstaller” is actually a bit of a misnomer… it doesn’t actually build an installer; it just builds the exe and data structure needed for the exe to run standalone). I was able to use the default options of the tool to build an .exe with all the dependencies needed (including my custom dependencies like ffld, as well as dependencies that require DLLs like pygame). It even worked with virtualenv-installed dependencies.
The only issue that I had with it was that you needed to run the scripts inside of the pyinstaller directory. I really wanted to run the script from the directory where my virtualenv is. There was additionally a three-step process to create the exe, which I reduced to two (and hope to soon reduce to one). In the end, I wrote a script that wraps around pyinstaller. You can find that script (builder.py) on github. Now, I can do the following…
# Create a new 1942 directory. This sets up a new folder with a virtualenv.
# It saves the name of the main script (which pyinstaller needs)
# for later commands.
# This needs to be done once for a project.
python builder.py create 1942 E:\games\1942\1942\main.py
# Now I activate the 1942 virtualenv and install dependencies as I need to
# using the windows command line. This needs to be done once, although
# if I later add new dependencies, I need to install the dependencies
# to the virtualenv.
# Finally, build the game!
# This runs pyinstaller’s Configure.py, Makespec.py and Build.py
# scripts. When done, it adds the “data” directory that was found
# for the game to the distribution folder, then zips up the
# distribution folder and plops it out into the current directory.
python builder.py build 1942
I try to get any software I write close to a one step build. As Joel Spolsky writes in his post, your entire program should be able to be checked out of source control, compiled and packaged into the final format in exactly one step (typically, clicking or running a build script). Any more steps than that and you will waste time (both in running the steps and making user errors in the process). This is true of any software, but it would seem especially so of Ludum Dare. I don’t mind a few set up steps, so long as after I make that set up, I can rebuild the entire program later with just one command.
Feel free to use the script, although realize that it’s not going to work for you out of the box. I assume that pyinstaller is in a specific location, and that the script being used as the “main” script has a “data” directory next to it that will house all data.