So a month or two ago, indie developer Ivan Safrin released a game engine called Polycode. Ivan has been working on Polycode for several years and has been using it as the secret ingredient in some of his game releases, like TigSource Assemblee winner BitWorld. I took a look at the released version and was very impressed with it; it actually elegantly solves several problems I’ve been facing. I’m now developing a project against Polycode and also working on adding a few small features to it.
Following:
- Some thoughts on Polycode
- My efforts to port Polycode to MinGW (with code)
- A tiny “getting started with Polycode”
- What I’d like to do with Polycode next
Some thoughts on Polycode
Polycode is a top-to-bottom game library/engine/platform using C++ and LUA, like pixeltoaster. You can quickly develop a game just by writing game logic, and you can compile what you’ve got for Mac, Windows and Linux (and iPhone may work soon). Polycode differs from something like SDL or SFML in that it is a much more complete solution: instead of just sort of setting up a drawing surface and saying “have fun!”, Polycode can handle everything from asset loading to physics– you don’t need to know anything about making a game going in. At the other end, Polycode differs from Unity or GameMaker by being a little less complete– there is nothing like a level editor or integrated IDE yet, for example. (However, Polycode benefits in my view from having a good balanced view of “what you really need”– unlike Unity, Ogre or Panda, Polycode doesn’t either force you to learn some huge framework, or produce bloated executables full of functionality you’re not using.) Polycode also offers a step up from some of its more exact equivalencies, like Cocos or Löve, by supporting both 2D and 3D.
If you’ve been reading this blog, you may know I myself made a game engine called Jumpcore. Polycode does some things similarly; aside from some major features Polycode has and Jumpcore doesn’t even attempt (archive management, 3D physics), the main difference is that Jumpcore is much more minimal in its style. For example while Polycode and Jumpcore each bundle, say, TinyXML and a physics engine, Jumpcore just sort of leaves those libraries as exposed metal and expects you to use TinyXML directly. Polycode offers wrappers for things like physics, xml loading and graphics, and expects you to use these. This may be an advantage from Jumpcore’s perspective because it makes Jumpcore very easy to port, and because it means someone who wants to write “their own engine” can use Jumpcore just as a handy porting library while having complete freedom to design their own structures. However, I do not think this is much of an advantage because Polycode is already catching up with Jumpcore in terms of supported architectures (and doing so without using SDL as a crutch everywhere, as Jumpcore does) and meanwhile, although Polycode does make you do things “Polycode’s way”, it seems from my initial use of it to be extensible enough that you can take the wheel away from Polycode when appropriate. It probably makes more sense to, for example, use something like Polycode’s default display objects and make customized objects when you really need to, than to have to write your own OpenGL for everything from HUD display on up from the start (as Jumpcore makes you do).
The one big unique thing about Polycode is its ground-up LUA integration. When you use Polycode, you have a choice out of the box of which of two languages to use: C++ or LUA. LUA is a “scripting” language, like Python or Flash ActionScript. Polycode lets you write a whole game in LUA, and you get the exact same API C++ users do. (The one thing that interests me most about Polycode, and I’ll have more to say about this later, is the possibility of writing a game partially in LUA and partially in C++, something I think Polycode may make unusually easy).
My efforts to port Polycode to MinGW
So, how do you use Polycode? This bit is a bit trickier; Polycode is very new, and getting it working may be a bit fiddly.
When I made Jumpcore, I had a daydream: I should be able to write exactly one piece of software code, compile it three times from my same computer, and have Mac, Windows and Linux versions ready to upload– maybe mobile versions also. Polycode, in the form currently distributed, isn’t quite there yet: There are Windows, Mac, and Linux versions of the SDK, and each comes with a sample project, but there’s not a package on the Polycode site that combines all the platforms into one thing. Meanwhile, since each SDK uses native build systems (XCode on Mac, MSVC on Windows, make on Linux) you need to have a version of each operating system in order to build for all platforms. Ivan says he does his builds with Parallels, which probably does make things easy. I however don’t have a copy of Windows, so I decided to do things the difficult way. (This is the C++ version I’m talking about, of course; the LUA version as I understand requires no compiling at all to make an executable.)
The first problem– no combined sample project– is easy enough to fix. The second problem I had to do some work to get around. My solution was to just build the Linux version for Windows using MinGW. (MinGW is a GCC compiler that emits Windows .exe’s– and MinGW, conveniently, can be run on a Macintosh.) Since the Linux version is based on SDL, this approach works fine. However, it meant some setup in terms of rebuilding the Polycode libraries to work with MinGW. The MinGW-compatible version of Polycode I wound up with can be found at my fork on Github (Update 9-21-11: This URL moved, so I updated the URL.)– but that’s the source, which you probably don’t want, you want the libraries you can actually compile against. So if you want to use Polycode for MinGW, what you want to download is:
- This archive I made containing MinGW versions of everything you need to build a Polycode game
- This sample project (I’ll zlib license this at some point)
The #1 “archive” I mention above is a Linux-style directory hierarchy containing an include/, lib/ etc. In order to use it, you’ll have to set some environment variables.
A tiny “getting started with Polycode” (my way)
Here is what I do to compile my template project– on Mac, remember, although the MinGW process I describe below will actually work on Windows also if you’ve installed MinGW and MSYS.
Before doing anything, enter “Template/Xcode Template” in the example project and run dopack.sh. Then:
To compile a Mac version: Look under “Template/Xcode Template”, open PolycodeTemplate.xcodeproj. You should be able to just build from there.
To compile a Windows version:
- Download and install MinGW 4.3.0 from here.
- Download and unpack the “everything you need” archive above; take note of the path it unpacks to, it will be something like “/Users/mcc/Downloads/Winroot”.
- In the sample project, go into “Template/winbuild”. You’ll need to set the location of the Winroot directory into the $POLYROOT variable by saying something like:
export POLYROOT=/Users/mcc/Downloads/Winroot
- make
That’s it (and if anyone tries this and has problems, let me know). You should be able to make a linux makefile pretty easily from modifying the Makefile in the winbuild directory, but I have not done this yet.
What I’d like to do with Polycode next
There are a few things I’d like to see happen with Polycode, and may take a crack at myself if no one else gets to them first.
- I think the Mac version should be packaged as a framework. This would simplify project setup considerably.
- My MinGW version has some issues with file size. It requires way more DLLs than it seems like it should– ideally everything would be static, really.
- Similarly, my MinGW version shouldn’t depend on SDL, it should be possible to build the full-native Windows version using MinGW.
- With both the Polycode core libraries themselves and projects based on Polycode, it would be nice if the per-platform build systems were better integrated with one another. Bitshifter is working on a cmake based build system that may help with this.
- With Polycode in general, there seem (?) to be some issues on machines that don’t support shaders.
- At the moment, there’s no way in Polycode to use the current screen resolution when making a full screen window; cross-platform methods for getting screen height, screen width, and screen refresh rate are needed (Ivan says he’s planning to handle this himself)
- Vsync needed badly
- Lots more documentation is needed– there’s lots of features in Polycode I’ve yet to determine if they’re adequate for my needs because I haven’t yet worked out how they’re used. In particular, we need some docs on how to extend Polycode. (On that note, if I wrote a “how to build Polycore” document would anyone read it?)
- And here’s my big one:
As I mentioned, I want to be able to mix LUA and C++ in a single program. Some of this may be my personal preferences, but I’m increasingly frustrated by the fact that different stages of the game development process seem more suited for different languages, and so regardless of which language I pick I wind up frustrated at some point. If I’m implementing a complex graphical effect, or some sort of complex technical feature, then I really want to be writing C++; C++ is what I’m comfortable with, it lets me optimize and do low-level stuff easily. Parsing a PNG in LUA, say, sounds dreadfully unpleasant. On the other hand if I’m trying to lay out elements in an HUD, or design the AI behavior of some small enemy or object, C++ becomes an incredible burden; these kinds of things involve a lot of test, tweak, test, tweak, and with C++ this means an iteration cycle of maybe a minute because I have to restart the whole program and recompile just to change one thing. Meanwhile I’ve been experimenting with ActionScript lately, and with that I’ve had the opposite problem; rapidly prototyping “game logic” is an easy, lovely experience, but doing something like optimizing a display routine is a nightmare.
There are maybe ways around this problem, I could figure out this stupid “Fix and Continue” feature in XCode or shove lots more stuff into XML than I’m currently shoving but… to me, the simple solution would be to write basic engine stuff in C++, “game logic” in LUA (or some other LUA/Javascript/Python like language), and then on top of that maybe even have a LUA console while the program is running so I can mess with stuff and try out different things without having to restart the program at all. This is of course the sort of thing LUA is built for– it’s meant to be embedded– but there’s a good bit of work in getting it into your project, you have to set up bindings and all this stuff.
Polycode looks to me like a great shortcut on this– bindings for all the “API” stuff have already been created, so LUA code can act as a first-class citizen and not have to go through the C++ code to do everything– and it comes with a C++ auto-binding script (one of several that exist for LUA). The only problem is that although it’s doable in theory, Polycode is not set up to do this sort of thing yet. What’s currently being distributed is a “core” library that C++ stuff hooks into, and a separate project called “PolycodePlayer” which is used to run LUA-based Polycode games (the idea is that the player app loads in a Polycode “file” containing LUA scripts and resources); all the LUA integration lives in PolycodePlayer. Probably my biggest personal goal with Polycode is to try to see PolycodePlayer functionality migrated into a game project.