Last week, I mentioned I'd be looking into creating a downloadable version of NEO Scavenger. It turns out that's a bit more complex than I expected.
After nearly two full days of research and experimentation, I think I've got a way forward, but it isn't as elegant as I had hoped.
Before I get into how, let me briefly speak about the why. Part of the reason I chose Flash as a platform was because a lot of people on the web have the Flash plugin. Adobe propaganda aside, it's probably one of the single largest install bases for game platforms in the world. People can just visit www.bluebottlegames.com and try the demo with little to no effort.
If I had chosen C++, C#, XNA, or any of the native application types, I'd have to present a "download" link, and people would have to:
- Trust me
- Download my game
- Install/Launch my game
It doesn't sound like much, but those three things cause an enormous drop-off in the number of people willing to try a game. Each of the above is a barrier to entry. The first is a trust barrier, the second a patience barrier, the third a laziness barrier.
As a rule of thumb, I estimate 50% of interested people just say "screw it" and move on to something else when presented with a barrier. There's some leeway, of course. Clicking a link is a smaller barrier than fishing out a wallet to pay for an app. But I assume I'm losing customers with each step along the way to trying my game (and selling my game). So minimizing that flow is important.
With Flash, the game just appears in the webpage. Players can pass a link to a friend, and all that friend has to do is click the link to see the game (and potentially wait for it to download).
Using Flash also means I can deploy the demo to Flash portals, to help spread the word. Plus, there's the unplanned bonus of people being able to play NEO Scavenger at their workplace, even in places that prohibit installing apps!
The down sides? It has a few, to be sure. This week, it's figuring out how to create downloadable versions for distribution on services like Desura and Steam.
Flash as a Native App
There's a way to make Flash into stand-alone executables. Several, in fact. However, as I'm discovering, each has it's own idiosyncrasies.
The simplest, most straightforward way to get a downloadable version of Flash games is to create a projector. Just fire up the stand alone Flash player, load your swf, and "save as projector." Easy! Or is it?
- Easy - As above, just load the swf in a stand-alone player, and click File->Save as Projector. Voila! Native app created.
- Cross-platform - The process works on PC, Mac, and Linux.
- Packaging - The process makes a single executable. Neat and tidy.
- Proven - Examples include Machinarium, VVVVVV, The Binding of Isaac.
- Hardware - You need a Mac and a Linux box to create those versions. I only have a PC at the moment. I can probably get Linux running on one of the machines in my house, but Mac is out of my reach for the time being.
- Sandbox - Save files must use the unintuitive (to a user) Flash SharedObject system, and can be deleted via browser cache/cookie clearing. (It's possible the fscommand() method offers a way around this, but I need to research it more.)
- Mods - Modding support may be hard to setup in the future, if the projector cannot access local files.
Adobe AIR Projector
I could also create Adobe AIR projectors. AIR is Adobe's solution to cross-platform software. It's designed to allow a developer to create a single .air file which can be presented as a link in a webpage. Clicking that link on any platform launches the appropriate processes to download and install a native executable for the user's platform (including installing AIR, if necessary).
It also provides a means of creating native apps for each platform, which can be downloaded and installed like most traditional software. This bypasses the need for AIR on the user's machine, but creates a somewhat messy install (see below).
- Fairly Easy - Making an AIR app isn't as easy as making a Flash projector, but it's not too hard, either. Using FlashDevelop, it's possible to setup an AS3 AIR Projector project, import your source code, and follow the auto-generated readme to tweak the batch files needed for publishing. Compile to swf, then run the "packager" batch file to make the app. Some research into the packager parameters is needed to make .air vs native .exe/.dmg/.deb files, however.
- Cross-platform - Output works on PC, Mac, and Linux*. In theory, it also supports Android and iOS, though I haven't looked into it much yet.
- Sandbox - Local file access means save games can be safe from browser flushing.
- Proven - Proven examples include Defender's Quest.
- Hardware - While generating an .air file can be done from any platform, and the output works on all destination platforms*, generating native apps still requires native hardware (Mac to generate .dmg, Linux to generate .deb, Windows to generate .exe).
- *Linux - As of 2011, Linux is no longer supported for the .air path. The native apps approach still works on Linux, but generating a working .air file for Linux involves some heavy tweaking using older AIR versions.
- Packaging - Both the .air and native app outputs generate an installer which must be executed, and this throws up all kinds of ugly prompts on most machines. Also, both paths will generate a messy collection of support files alongside the application.
- Licensing - You may need permission from Adobe to distribute AIR installer. Looking into this, it may only be the case when including AIR's installer on its own with your download, and the .air and native app approaches may sidestep this. Still, it's a consideration, and that kind of legal complication is an effective deterrent to adoption, if anyone at Adobe's reading this.
Port NEO Scavenger to HaXe
There's even a framework within HaXe, NME, which smooths the transition from Flash even further. It's a pretty impressive tool. However, it's a relatively young platform, meaning its community support pales by comparison to AS3. It's also just different enough from AS3 that it would mean a lot of rewriting of code.
- Packaging - Produces actual native apps. No virtual machines.
- Cross-platform - Works on PC, Mac, and Linux (and iOS, and Android, and Flash, and...)
- Sandbox - Local file access means save games can be safe from browsers, and mods are supported.
- Hardware - Need a Mac and Linux OS to generate native apps for those platforms.
- Effort - I would have to rewrite huge amounts of code to port to HaXe. As mentioned above, AS3 and HaXe (NME especially) are close, but not close enough.
- Support - As a young(ish) platform, community support is still pretty small. It can be harder to find answers to questions as compared to AS3/Flash.
3rd Party Wrappers
There are also some third party wrappers out there (e.g. Zinc, SWF2EXE, mProjector). However, their reputation appears to be mixed. Some claim support is poor, others say the performance is bad, some don't even support all platforms. And then there's the price tag. With many of them costing several hundred dollars, I might as well buy a used, Intel-based Macbook, which not only lets me develop for Mac, but iOS devices as well.
Is there a conclusion? Not yet. No silver bullet, anyway. My likely approach for now is to actually go with the simplest option: the Flash projector. It generates native .exe files that work right now, and I can probably get Linux running on one of my PCs to do a .deb version. If sales pick up, I can probably justify $500 for an old Macbook to compile Mac versions.
And since I'm still in beta mode, the downloadable file will be updating with each new version. It's not too hard to swap in an .exe generated via another means when I need to. It's just the easiest working path open right now.
If you're looking for more info, here are a few links to resources I used in my research:
- Making Flash EXEs (Terry Cavanagh's VVVVVV research)
- Flash to EXE Projector Help (Leans towards projector)
- Packaging a desktop native installer (Adobe AIR documentation)
- Lone Survivor Linux Woes
- Flash for Downloadable game. Some tips? (Projector vs. AIR vs. HaXe)
Hope this helps some Flash devs out there. If you have any additional info or corrections to add, post in the comments!