Upcoming Events
Engage! Expo NYC
2/16 - 2/17 @ New York, NY

GDC 2010
3/9 - 3/13 @ San Francisco, CA

SXSW Interactive Festival
3/12 - 3/16 @ Austin, TX

IEEE Virtual Reality 2010
3/20 - 3/26 @ Waltham, MA

More events...


Quick Stats
6651 people currently visiting GDNet.
2365 articles in the reference section.

Help us fight cancer!
Join SETI Team GDNet!



Link to us

Events 4 Gamers

Home » Features » Product Reviews » Software » Zinc 2.5
  Intel sponsors gamedev.net search:   

Product Reviews
Jump to:
Software
All product reviews

Product: Zinc 2.5
Developer: Multidmedia Limited
Reviewer: John Hattan
Posted: November 27, 2006
Rating:
Discuss this review

Multidmedia Zinc 2.5
by John Hattan

Flash has also become a dominant platform for web-based games. Flash's combination tools for drawing, animation, and scripting makes prototyping and deploying games easy. But can Flash be used as an environment for standalone games? In this review, we'll be exploring that as well as working with Multidmedia Zinc, a tool that facilitates the process of making first-class Flash-based games.

Why Flash?

Flash's biggest strong-suit is browser penetration. Looking at the stats for my own web site, I find the following numbers (as of 8/7/2006)

So at least 97.5% of my site's visitors are running at least Flash 6, and about 84% are running version of Flash that's less than a year old. If you're worried about having some kind of deployment nightmare (like I've personally had in the past with Java), you're in luck.

And there are three reasons you're in luck. . .

First off, The Flash development environment can target any Flash player all the way back to Flash Player version 1, circa 1996. Making an applet that treads the balance between player-penetration and capability is as simple as choosing a target version and compiling. If you're using a language or graphical feature that's unavailable in the player you're targeting, you'll get compiler warnings that tell you what you're doing as well as the version of player that started supporting that feature.


The Flash "Publish Settings" box, showing the versions of Flash player with which you're backward-compatible.
(Note that I'm using a Vista-lookalike skin for my screenshots, in case you're wondering why the chrome doesn't look quite like Windows standard).

Next, Flash players maintain very good backwards compatibility. If you target the Flash 6 player, you'll have no problem with people being unable to run your games under Flash Players 7, 8, and 9.

Finally, if you have no choice but to require a late-breaking player version, you can actually set up your Flash applet so it will, after prompting the user, automatically update his player.

Now, let's talk just a bit about Flash itself.

ActionScript

The Flash language, ActionScript, is also quite powerful despite its simplicity. It's based on ECMAScript, and it's basically the same language as JavaScript (or JScript). Despite the "Java" and "J" in the names of its contemporaries, though, ECMAScript bears little resemblance to Java. If you start off by realizing that it's basically Lisp with a C++ish syntax, you'll have an easier time understanding why things work the way they do.

If you're a Java or C++ programmer, the program control statements (for, while, if, do, etc) will look instantly familiar to you. Variable declarations, being much more Lispish, will drive you up the wall. While later versions of ActionScript have become much more like C++ in that you can assign types to variables (and reasonably expect for 'em to stay that type), and you can define classes and constructors and such, it's still Lisp under the hood. And that means that you can do stuff like the following block of code, which would make a C++ compiler look completely crosseyed at you.

Here's a complete program in ActionScript. . .

var i = new Object;
i.x = 10;
i.x += "zippy";
trace(i.x);
trace(i.y);

i.myarray = new Array();
i.myarray["squicky"] = 2;
trace(i.myarray["squicky"]);
In the ActionScript code above, I instantiated an Object named i. Objects don't need classes in ActionScript. You can just instantiate 'em and start sticking members to 'em like clay.

In the next line, I created a member of Object i called x and assigned it a value of 10.

On the line after that, I added the string "zippy" to x. Most compilers at this point would complain about a type mismatch, but the ActionScript interpreter will dutifully concatenate the string right to the end of the number.

Then, just to see what I got, I traced for the x member. It displays "10zippy" to the debug output window.

Then, just for fun, I traced for the member y, which I never defined. Expectedly (for Flash anyway), it returns "undefined".

The concept of "undefined" is actually quite useful in Flash because it evaluates to false in any control-flow statements. For example, let's say we need to mark a sprite to show that it's doing its crash-sequence. I could simply say. . .

mySprites[3].isCrashing = true;
and it's now marked. If I'm doing an operation that loops through all the visible sprites, I could simply check for the "isCrashing" member. Since all of the other sprites don't have this member, checking their "isCrashing" member returns undefined.
if (mySprites[i].isCrashing)
  // do another frame of death-spiral

I don't need to define "isCrashing" anywhere in the other objects or in the class because if it's not defined it'll evaluate to false in the if() statement.

But I digress.

Next in my code, I add an array member called myarray. Nothing interesting there. On the following line I set a value to array index "squicky", then trace for its value (which is mildly interesting if you're still using one of those languages where array indices are numbers). Sure enough, the output window shows a 2.

As you can see, the ActionScript language is quite a dynamic thing. If you're used to more restrictive models in your languages, it'll requires a lot of un-learning to use (even more so than Java). It does get in the way sometimes, especially if you misspell a variable name somewhere, but you absolutely will not miss having to return to your class definition to add members whenever you find that your model doesn't have enough capability.

And if you really can't stand such latitude in your programming model, you can now, with later versions of ActionScript, define strict types and classes so that the compiler will complain if you try to add "zippy" to 10 like I did in my earlier code.

Performance

Performance in Flash is a topic for discussion. Some stuff in Flash is actually much faster and easier than the way you're likely doing things now, like rotations and scaling (more on that later). Performance from a development standpoint is extremely quick. For an arcade-type game, I can hack together a playable prototype in a few hours. With a little more polish, I can have something ready to put on the web in less than a day.

Performance from a speed-of-execution standpoint really depends on the kind of thing you're doing. If you're planning to do something nontrivial in 3D, for example, I'll have to gently deflate your bubble right now. While versions of Flash after version 8 did greatly improve the 3D situation by giving the user the ability to directly manipulate framebuffer pixels as well as increase code-execution speed quite a bit, there is simply no hardware-accelerated 3D in Flash. In fact, there's not really any software-accelerated 3D in Flash either. Any 3D looking stuff you'd like to do will have to be done either with a little bitmap fakery (i.e. shearing and squeezing bitmaps) or by drawing pixels with ActionScript code. In either case, if you're planning to do anything more significant than a clone of Wolfenstein 1 that runs in a really small Window, you should probably look elsewhere.

3D aside, performance in 2D is actually fairly good. If you see a lot of poor performance on those little web ad-games, that's generally because most specs for banner ads require that they be locked at 8-12 FPS just so that web page performance isn't hampered by banner ads that are taking up all the browser's timeslice. If you're running standalone, you can run 30, 40, 60, or even 100 FPS nowadays if you're clever.

And by "if you're clever", I mean that you'll have to work around the Flash heartbeat, and that's another programming concept around which you'll have to wrap your mind. Flash apps work on the concept of frames. One of the properties of a Flash applet is its framerate, and it doesn't change. Flash runs your frame's code N times a second, so you will have to make sure that your frame's code can finish before that, or things will start to bog down. Generally this isn't a problem, but if you have something that's really code-intensive and time-consuming (like generating a maze or a puzzle), you should probably try to break the code up over several frames. Flash won't pre-empt your code if you don't do this, but it will complain to the user if your app spends more than about five seconds in a single frame, under the assumption that it's stuck in an endless loop.

All that being said, if your games run in the same genre as most Flash stuff you see out there (puzzle games, 2D arcade games, shooters, platform-jumpers, etc), you'll probably be able to do it.

Cross-Platform

Platforms are where things in Flash get interesting. Flash works on loads of platforms, ranging from mobile phones to desktop computers. On everything but the mobile phones (which are quite different internally from desktop computers), Flash-coded applets can exist either as SWF files that are loaded by a browser plugin or as standalone executable files.

And, for the most part, things are compatible all the way across platforms. While a Nokia Series-60 phone is quite a bit more constricted platform than the machine you're using to read this article, you'll still be able to compile much of your code there. But put out of your mind any lofty thoughts of being able to make an applet that plays wonderfully everywhere. While it's theoretically possible to do so, the hoop-jumping that the mobile phone platform will require (no mouse, keypad input, slow speed, small screen) will ensure that your end-users' experience with your game will be less than satisfactory if you have the same version of applet running on mobile-phone and desktop computer.

So, as far as cross-platform coding goes, even though mobile phone Flash and Windows XP Flash are compatible, you should plan to make a lot of code-changes if you want something to run on both unless you really want to annoy your users on one platform or another.

While this five-minute overview of some Flash-for-games features may be interesting, this review is all about standalone games. So let's ask. . .

Why Develop Standalone Games In Flash?

That's an excellent question. And it's a question I had to ask myself. I worked as a professional C++ developer since 1991, and I have several commercial products under my belt, all of which were coded in C++. By all rights I should be the biggest C++ evangelist (read: snob) around, but I was converted to Flash development after some contract-programming jobs in Flash, immediately following a couple of contract programming jobs in Java (which turned me off on that platform forever, but that's another story).

After developing a number of C++ class libraries (oops, I mean game engines) for 2D games, I thought I had a great system where I could develop games that were quick and non-buggy and could be done in as few lines of code as possible. Then I wrote some similarly-scoped games in Flash only to discover that I was making games using half of the code. It wasn't just the dynamic garbage-collected pointerless typeless code that was making the stuff small -- it was the ability to do things like create and animate a sprite using no code at all.

I also found that Flash's vector-roots were giving me things for free that I once had to worry about. If, for example, I wanted a sprite to tumble to the ground and explode, I'd either have to rotate and scale the bitmap (which is ugly-looking and CPU intensive) or make a sequence of tumbling bitmaps (which takes up lots of memory and is a hassle to draw). In Flash, it's just a matter of changing the value of the _rotation member-variable in the sprite. If your sprite is a vector, the rotation looks great and is very CPU-friendly. Ditto for scaling, shearing, etc. I found myself adding cute little special-effects to my games that simply weren't available to me using traditional framebuffer-based animation simply because they were no longer computationally intensive and could be done with one or two lines of code.

While I did have to abandon some techniques as being too intensive for a little scripted vector-engine. As many techniques availed themselves to me. And I found that the Flash games I made looked as good as the old C++ ones.

Standalone Flash

I mentioned standalone Flash games earlier. Making your Flash game run as a standalone EXE from Flash is as simple as checking a couple of checkboxes. . .


Our publish options for Flash (Flash 8 to be specific)

If you look about six checkboxes down, you'll see that you have the option of compiling your Flash project to a standalone Windows or Mac executable. If you check those boxes, you'll make a standalone executable file, free of any runtime baggage and playable on anyone's machine. Simple, right?

WRONG!

Unfortunately, making a standalone executable right out of the Flash environment will ensure that your app is running as a second-class citizen. Let's compile an app right now (specifically a little TriPeaks card game I made) and see what happens. . .

Okay. That certainly looks playable, but there's some stuff missing.

Now then, there are a couple of third-party utilities that can get around some of these problems by patching the executable, replacing the generic Flash resources with ones of your own design, deleting the menubar resources, etc. But there's still something that your app still won't have, and that's due to the nature of the Flash browser plugin. Flash runs in a "sandbox" which prevents applets from doing anything potentially harmful. Flash applets don't have access to your files. Flash applets can't save settings to the registry. Flash applets can't access local databases. Flash applets can't talk to peripherals other than the keyboard and mouse. Flash applets can't even communicate over the internet except to the servers that spawned them. This is all done to keep someone from writing a Flash virus or a Flash worm or a Flash applet that sends threatening emails to the president. And that's certainly important in a browser, but it really hampers usability if you want to run as a standalone application.

For example, suppose I'd like to maintain a running high score for my game. If I was writing my game in C++ there are loads of ways I could do this. I could store a value in the registry. I could store the value in a little text file. I could even store the value in a database (although this would be overkill for this kind of app). With the Flash sandbox, though, the only place for persistent data to be stored is in a "Shared Object", which is Flash-ese for a cookie. This would work, provided the user isn't blocking cookies in his Flash settings. If I wanted to store my data on the user's drive or on a server, though, I'm pretty-much out of luck.

In addition, there are loads of other things that a Flash-compiled projector simply can't do. For example, I might want my game to work with a joystick. Or I might want my game to refuse to resize itself. Or I might want my game to run full-screen in 640x480 resolution. Or I might want my game to automatically download updates to itself via an FTP server. None of these things are available from within Flash.

That brings me to. . .

Third-Party Projector Tools

The robustness of Flash as a platform coupled with its complete inadequacy as a tool for making standalone products has sparked a cottage industry of third-party projector tools.

Oh, and since I didn't mention it before, "projector" is an archaic term that Flash uses to describe its standalone creations. Since the Flash folks liked movie metaphors, bundling the projector with the movie would be equivalent to making it work standalone. Think of it as compiling to an EXE file and you'll be fine.

These projector tools run the gamut in terms of flexibility, features, and price, but they all work similarly. You put some extra ActionScript code into your Flash applet to call functions that aren't built into Flash. Then, after compiling your project to a SWF file in Flash, you run a standalone postprocessor on that code. This postprocessor bundles the applet with the Flash runtime engine to make a standalone EXE file. It also adds hooks into Flash's ActionScript interpreter so that those extra function calls will now run "outside" code that lets you do things Flash was never intended to be able to do.

For the purposes of this article, we're going to be working with MDM's Zinc 2.5. We're going to be working with Zinc instead of the others for a few reasons. . .

  1. It's a robust product that's gone a long way to let Flash extend its tendrils into your system, adding about 800 different system-level calls.
  2. I have personal experience with the product, having made my standalone games with it.
  3. They contacted me to do a review, and it's easier to review products with which you're already familiar.

In order to Zinc-ify your Flash app, you need to do two things. First you must add some new code to your applet. Here's some code that'll save and load my running high score to the Windows registry.

mdminit();

mdm.Application.enableExitHandler();

var myKey = "SOFTWARE\\The Code Zone\\TriPeaks";
var TotalScore = 0;

if (mdm.System.Registry.keyExists(2, myKey))
{ // there's a key here. see if the score is here
    var valueNames = mdm.System.Registry.getValueNames(2, myKey);
    for (var i=0; i<valueNames.length; i++)
        if (valueNames[i] == "TotalScore")
            TotalScore = mdm.System.Registry.loadInteger(2, myKey, "TotalScore");
}
else // there's no key yet. Make one
    mdm.System.Registry.createKey(2, myKey, "")

mdm.Application.onAppExit = function()
{
    mdm.System.Registry.saveInteger(2, myKey, "TotalScore", TotalScore);
    mdm.Application.exit();
}

First thing this code does is initialize the mdm object. The mdm object is a big global static object that's loaded with all of the functions that normally you can't do with Flash. If you need to talk with Zinc, you do it through the mdm object.

Next thing it does is enable an exit handler. While you could add a "close" button somewhere in your app that explicitly closes your game, that won't be able to respond to the user who closes your game by clicking the red "x" titlebar. The enableExitHandler function allows you to overload an onAppExit() function so you can properly respond to all close requests no matter how they arrive.

Next thing I do is talk to the registry. There's no magic here. In fact, it's not that different from doing it via Win32 API commands. I just drill down to a particular "path" in the registry and get what's there. If there's no key yet, I create one.

That's really all the code necessary to save my game's running tally in the registry.

Now then, this is important. If I ran this applet right now (by pressing CTRL+ENTER in the Flash environment) or I made a standard Flash projector, none of this new code would work. Flash, not seeing a meaningful mdm object, would ignore it completely. That's because the Zinc runtime stuff isn't linked in yet.

So let's do that now.


The Zinc standalone projector-making application

This is the Zinc application. It's a standalone app, and it's made up of loads of panels and tabs and such. The most important ones are on the first tab, so let's check those out. As you can see, I already added a path to my SWF file in the "Input Source" box. Also, I set the "form caption", which is the name that'll appear up in the titlebar of the app.

Note that a lot of these options are changeable at runtime as well as from within the environment. For example, changing the value of mdm.Forms.MainForm.title will change the app's name in the titlebar. But we don't need to change any titlebar text for this little game, so we'll just set it once in the Zinc app.

And that's all that's required for a minimal app. While there are loads more options I can set, I can press the "Build" button right now and get a standalone game.

Well, that looks slightly more like a "real" game than the previous Flash version. I no longer have a generic menubar. I have an actual title rather than "Macromedia Flash Player". I still have a generic icon, but I could head over to another tab in Zinc and fix that. My executable's header now contains my own copyright rather than Adobe's. Right-clicking in the app's window no longer brings up Flash settings. I've disabled the maximize button and arbitrary resizing.

In short, I can now make my game look and act like a real application and not like a web applet running outside a browser.

Most importantly, though, is that this game now has "broken out of the sandbox" and can talk to Windows just like its big-brother games written in C++. It can now read and write to the registry via the code I showed earlier. If I wanted, my game could change the screen's resolution. It could talk to a joystick. It could do socket communications. It could launch a browser. It could read XML files on the hard drive or the internet. It could even embed the Windows Media Player for video instructions or the Acrobat Reader for help.

Runtime and Security Issues

Earlier I mentioned that you need to do a little thinking about your runtime needs when running Flash applets in a browser. But what of running Flash standalone? It would be a real can of worms if your game had to upgrade the Flash player on peoples' machines just for your game, so Zinc gives you the option of bundling the Flash runtime into the EXE file itself. Bundling the runtime engine into your EXE will add about 2 meg to its size, but in the end it's probably worth it.

Security is also an issue when it comes to projectors, mainly because EXE files compiled from Flash are notoriously insecure. They're basically just an EXE-file stub with your SWF file concatonated on the end. With a small amount of google-searching, you'll find a plethora of tools that can convert a Flash-compiled projector all the way back to ActionScript source code. Thankfully, Zinc for Windows thus-far does not have that problem.

Cross Platform Issues

Flash is a cross-platform animal, and it'd be a shame to lose that considerable advantage when making an EXE file. Not only does Zinc does exist in Mac form, but some work has been done to maintain some consistency between the two releases.

Actually there are two Mac versions, sold separately. One is a plug-in for the Windows version that allows you to generate an OS X executable as well as Windows. The other is a standalone native Mac version that looks much like the Windows version shown above. Best I can tell, which you should use is a matter of convenience.

One major limitation that MDM claims to be working on is Intel support. While MDM does tout compatibility with Intel Macs, Zinc-ified apps currently only run in "Rosetta" mode, which means that the Intel processor is emulating the old PowerPC processor. While it works, it's pretty slow. MDM promises Universal Binary support sometime in 2007, which should improve the performance of Intel Mac apps several-fold. For my own projects on my site, I eventually ended up abandoning the Mac version of Zinc in favor of a competing product that could produce better Mac executables.

Cross-platform issues do crop up between the two. While the Zinc folks have done some work to keep the API consistent between Mac and Windows, there are obvious problems that couldn't be solved by a simple "least common denominator" approach. For example, functions that send SQL statements to the MS JET database (which is built into Windows nowadays) are only available on Windows. Similarly, the functions to send AppleScript code to the system are only available on Mac. When objects or functions are only available on one system or another, the difference is noted in the online documentation.

Multidmedia also has a PocketPC version of the tool, but unfortunately it appears to be lagging quite a bit behind the Windows and Mac version.

Finally, there's talk of a Linux version in the MDM Forums, but I don't imagine anything will come of that at least until the new Flash 9 Player for Linux is finalized,

Pluses and Minuses

I've been working with Zinc for quite some time now, and I have a few standalone products on my web site to show for it. While Zinc is a great tool for making a first-class EXE from Flash, it has some quirks.

First off is that it's just a generally unruly process. Making a Zinc-ified EXE file from Flash source code is a two-step process. First, you compile your Flash app to a SWF file. While you can run and debug this SWF, any code that makes calls to the mdm object won't function. After that step, you then load the SWF into Zinc and perform a second compilation to make the EXE itself.

And that's really a bit of a hassle. If you're used to the old Visual Studio method of pressing the "build" button and watching your code go through a half-dozen smoothly-integrated steps of compiling, linking, resource-compiling, etc. to give you a fully-formed debuggable EXE file on the other end, you'll be disappointed in the clunkiness of the process as it's done in Flash/Zinc. Multidmedia (the Zinc folks) do have a command-line version of Zinc that could conceivably integrate into the Flash build process (especially now that the Flash environment itself is scriptable out the wazoo) , but they charge quite a bit extra for the command-line version of the tool under the auspices that it's only useful for a multi-user environment.

Next problem is debugging. While Flash has a reasonable debugger built-in that lets you do the standard debugger-doings, like setting breakpoints, watching variables, stepping through code, etc., it's only usable on SWF files. Once Zinc has made an EXE out of your code, it's out of reach of the Flash debugger. Zinc actually has its own debugger that can work on compiled projects, but it's much less capable than the one built into Flash, and it's not much good for anything other than looking at mdm-generated trace messages. If you find yourself with bugs that aren't showing up after compiling to SWF, you'd better enjoy debugging-via-print-statements.

Finally, Zinc always seems to be surrounded by a cloud of quirks. If you compare it feature-by-feature with some of the other projector tools out there, you'll find that it has many times the features of its competitors. Unfortunately, it appears that some of the features in the Zinc feature-mountain have been coded too hastily, and it's taken quite a while for enough bugs to be ironed out for the product to really be considered stable enough for mission-critical projects. The current version of Zinc has gone through 22 minor point-releases (on a 2-3-week cycle) killing bugs. While it is good news that bugs are being fixed at a good clip (mainly because a couple of the projector tools out there haven't had bugs fixed in years), some of the minor releases have introduced bugs that had to be fixed by later releases.

Thankfully, the current release (2.5.25 as of this writing) appears to be pretty stable and doesn't have any showstopping bugs, at least in the stuff I'm currently doing.

Conclusion

Can you make games in Flash?

Of course.

Can you make any kind of game in Flash?

No. You must know the limitations of the Flash engine.

Can Flash make standalone games right out of the box?

Yes.

Right out of the box can Flash make standalone games that behave like those written with more conventional programming tools?

Not really. The Flash-built projector has pretty significant limitations.

Are there ways around these limitations?

Yes. There are projector-building tools like Multidmedia Zinc that can make your Flash applet into a first-class executable.

Does this solve every problem?

No. There are quirks along the way, both in the process and in the projector-builder's environment.

Is it ultimately worth it?

Yes. Flash's engine coupled with its drawing/prototyping/coding environment is a great system for making good-looking games quickly. If you're willing to put up with the process, the results can be quite rewarding.

 

John Hattan is an independent computer game developer who develops puzzle games from deep within a Hobbit-Hole in Southlake, Texas. Samples of his work are always available at www.thecodezone.com