actionjson 1.1

November 11th, 2010

There’s only one real change — support for whitespace. I was under the wrong impression strict JSON didn’t allow whitespace. Considering how much time I spent ensuring 100% compatibility, I feel pretty silly.

Download actionjson 1.1 here

Adobe’s as3corelib has a JSON parser. It’s quite stable, and widely used. It’s also dirt slow, and has a hard time getting through large amounts of data. Other libraries are either slower, or prohibitively licensed.

So, I set out to write the best AS3 JSON library I possibly could. I’m calling it actionjson.

encodeJson and decodeJson

Using pretty much every trick I could think of, I wrote a new blocking JSON encoder and decoder, much like the as3corelib version, but only capable of processing much faster. They’re also single, isolated functions, keeping them light and unbound from any extra dependencies.

On large objects the blocking decoder performs up to 5-6x faster. The JSON encoder has more modest improvements, since the as3corelib version is already reasonably optimized, but it’s still significantly faster at handling strings and objects. It’s 2-3x faster at them them in my tests.

ason was another JSON library that looked promising (if not for its license) that I wanted to compare actionjson against, but in my tests it seemed to have some severe performance problems. The decoder was around 10-20x slower than as3corelib’s decoder. The encoder was much better, even performing better than encodeJson in a few tests, but still performing 2-3x worse on objects, arrays, and long strings.

JsonDecoderAsync

I also wrote an asynchronous JSON decoder that can parse data incrementally, either as the data comes in, or in specified chunks. It has it’s own stack, which adds a lot of overhead, but still ends up around 2x faster than the one in as3corelib.

There is no asynchronous JSON encoder included, mostly because I don’t think it’s paticularly needed at this point, but I think it would be a good addition to the library in the future.

Wasted cycles

The advantages largely come from avoiding overhead from classes, constants (yes, constants), switch and if statements, and by analyzing using ByteArrays instead of Strings.

I actually tried using Apparat in my project, specifically tdsi so i could use Flash’s direct memory access opcodes. Unfortunately it performed at about half the speed, although I’m not sure why.

Download

actionjson is available on github here. It’s licensed under the Apache License 2.0, so it’s usable in proprietary and open-source projects. The library includes the (simple) unit tests I used to verify my code, as well as the speed tests.

Feedback and contributions are very welcome. Leave comments here, email me, or fork me on github.

The Flash 10 standalone debug player used to dump trace messages to standard output like any good program, and for a time, it was good. Somewhere along the line it seems to have stopped doing this and it’s annoying me. Here’s an (obvious) trick to produce the same result (on Linux, more on OS X below). Run tail -F in the background on flashlog.txt:

$ tail -F ~/.macromedia/Flash_Player/Logs/flashlog.txt &
$ <build command> && flashplayer something.swf

After running that first command once, it’s back to normal. I can Ctrl+C to kill the player (the close button is so far away..) and I get nice formatted debug output.

You’ll have to get mm.cfg set up to get Flash to dump to that file. Read up on it, or if you’re feeling tl;dr, just run this command:

$ echo "ErrorReportingEnable=1nrTraceOutputFileEnable=1" > ~/mm.cfg

I haven’t tried this on OS X, but it should probably work the same, just change the path to flashlog.txt:

$ tail -F ~/Library/Preferences/Macromedia/Flash Player/Logs/flashlog.txt &

Finally, if you’r not familiar with background jobs and want to be rid of trace output, run “fg” to take control of the tail process and then Ctrl+C to kill it.

I spent a large portion of yesterday caught up in a bug. Basically, Flash would make a call to Javascript, and a while later, get a call back. It worked something like this:

ExternalInterface.addCallback("callback", function ():void { ... });
ExternalInterface.call("doSomething");

Unfortunately it didn’t work. I thought I did everything right, I set allowScriptAccess to “always”, and since the swf and html page were hosted on different domains, I grant access to the swf via Security.allowDomain. But, whenever Javascript tried to call the “callback” function I would be stuck with this Javascript error:

Error in Actionscript. Use a try/catch block to find error.

So I tried putting it all in a try/catch of course, but that had no effect. Setting ExternalInterface.marshallExceptions to true changed the error message, but was no more helpful. I changed the function, but the error message didn’t go away. I had a hunch Flash itself was throwing the error, and I managed to figure it out.

The callback function itself was located in another swf that was loaded by the swf that set Security.allowDomain. I loaded it in the same ApplicationDomain and SecurityDomain, so for all intents and purposes I thought there were all the same blob of code. That’s not true, at least where ExternalInterface is concerned. Once I set the same Security.allowDomain for both swfs, the error stopped occurring. Flash was throwing a SecurityError the whole time, but I had no way of knowing that was the problem without guessing.

Hope that helps anyone else who encounters this problem.

Autobuilds on Linux

May 19th, 2010

As a developer, I generally like very fast builds. I only managed to complete my recent port by using fcshctl to keep me from going insane waiting for the results of my work to show up. At my job however, fcshctl alone doesn’t seem good enough (although, not for lack of trying).

A clever coworker reproduced a cool feature of some recent web frameworks to make an autobuilder, a system that will automatically build projects when files related to the project change. But today I wondered if automatic Flash builds weren’t nearly fast enough! Turns out they were not.

Using some command line tools that make use of inotify (a Linux-only, file change notification system) I can have automatic builds that spend literally no time waiting to build when files are updated. Install inotify-tools and try this command:

inotifywait --monitor --recursive -e close_write -e moved_to -e create -e delete <watch folders> | while read line; do echo $line; <build>; done

Replace “<watch folders>” and “<build>” of course with the folders than need watching and the build command, respectively. inotifywait pipes changes to the files or folders you specify into the while loop, which then runs the “<build>” command upon each change. Combined with fcshctl, it creates blindingly fast Flash builds.

On a side note, I’ve been using vim lately.  I’m growing pretty fond of it, but it (and gedit too) create temporary files. You’ll either need to modify the inotify command to ignore these files, make sure they’re not placed in the same location, or disable them entirely as they will send unwarranted signals to inotify and trigger premature builds. This could apply to some version control software as well.

Super Mario Crossover

April 28th, 2010

I spotted this game today. Yeah, I got a huge kick out of it.

The world is moving to HTML 5

February 7th, 2010

I’ve always been annoyed by the hatred of Flash by the development world. I’d prefer to see it hated for real reasons (there are plenty) and replaced by genuinely better technologies, but the hatred comes from people who often don’t care to understand Flash and support poor solutions as the answer. Lately this hatred has been getting louder, and from a PR perspective Flash couldn’t be worse off.

I’ve tried to fully describe why this anti-Flash movement is, in so many ways, wasted energy, but I found another post instead. Here’s the best description of what role Flash plays on the Internet that I’ve read since the first Flash ad pissed off a JavaScript developer.

“The World is Moving to HTML 5” and Other Flights of Fancy by Richard Leggett

Mega Man vs Adobe AIR

January 6th, 2010

I’ve got downloadable versions of Mega Man vs Metroid and Mega Man vs Ghosts ‘n Goblins available here. They require Adobe AIR to be installed in order to work.

I couldn’t test them on OS X, so if anyone can try them and tell me if they work I would be grateful.

If you have any problems please email me or leave a comment. Be sure to include your OS.

Enjoy!

I have been using shared objects to share data between swf files, so that changes in one can affect the other. On a website it works great as long as they share the same localPath and name, but this model doesn’t quite apply to AIR applications. Despite the name “shared objects” when you’re using them with AIR they’re private to each application, making sharing data using shared objects impossible as far as I know.

I’m a little surprised each application gets its own shared objects folder. I’m guessing it’s because there’s no domain to keep things properly separated, but I’m disappointed with the alternative. The localPath of a local shared object could default to a path containing the id of the application instead. This would keep local shared objects separate by default while still allowing more freedom. Treating each application as it’s own domain instead of the computer itself is frustrating. The best solution I’ve found is to create a shared application storage directory, then save any files to that.

These are the usual application storage directories (I’m not sure about the Mac OS X one, since I can’t test it, but it appears to be correct):

Windows: %APPDATA%Local Store<application id>
Mac OS X: ~/Library/Preferences/Local Store/<application id>
Linux: ~/.appdata/Local Store/<application id>

So, if we resolve the directory up two levels (“../../”), we get the following directories:

Windows: %APPDATA%
Mac OS X: ~/Library/Preferences/
Linux: ~/.appdata/

Which is probably the best place to put the shared application storage directory. When creating this folder I would recommend using the same naming convention as your program id (which generally is similar to package names, e.g. “com.somewebsite.project”). It should not be the same id as another application.

Here’s the code in action…

var appStorageDir:File = new File(File.applicationStorageDirectory.nativePath);
var saveFolder:File = appStorageDir.resolvePath("../../com.somewebsite.shared");

saveFolder.createDirectory(); // ensure the save folder exists
var fileStream:FileStream = new FileStream();
fileStream.open(saveFolder.resolvePath("savedata.bin"), FileMode.WRITE);
fileStream.writeObject(obj);
fileStream.close();

I create a duplicate of File.applicationStorageDirectory because it doesn’t allow you to resolve paths beyond the root of the directory.

It’s important to realize that this is ultimately a hack. If the application directory changes it could save the file somewhere unexpected. Still, it’s unlikely to change in the current version of AIR and it’s the best way I’ve found to share data.

Mega Man vs BrokenFunction

December 29th, 2009

The ports of my first two games are complete. I’ve put both games here. If you play them let me know in the comments if you notice any bugs, or if something doesn’t unlock, or even if you just enjoyed them so I can know they’re working for people.

I was paranoid I would go all George Lucas on the game and so I swore to not change things, but I did end up doing that anyway, so I tried to only change stuff that few would notice. This doesn’t cover changes to the engine (of which there are many), except as it relates to gameplay.

NES style enemy regeneration for some enemies. When some enemies go offscreen, they’ll come back in their original position, rather than their last seen position. It was too hard to do this in the original version so I didn’t bother. Most enemies still keep the original behavior because they don’t work well when you change it.

New preloader. I believe I originally had Wily always running from Mega Man (I thought it was funny), than I started adding more robots, then I had everybody running from everybody else. I got a kick out of it, but whenever I see it now it looks tacky. I rationalized reasoned that a preloader isn’t really the game, so I could do as I like. Even though people’s Internet connections are a lot faster these days, the preloader is really there so the game doesn’t start without the user’s expressed input. Also, since it’s unlikely Flash itself will have focus, it’s also a trick to get the user to click on the game and give it focus. The new preloader also serves yet another purpose…

Controller instructions. I’ve always considered the audience for my games to be the type of people who, at the slightest indication of boredom, will vanish. Looking for the controls is soooo booooring. Now they’re in the preloader and you can even fool around a bit while the game is loading.

New weapon. I’ve replaced the unconscionably boring S.Missle weapon you get when you finish Mega Man vs Metroid with a new one. For the sake of surprise I won’t tell you here, but I love it and I hope it gives my games more replay value. I’ve also made the other unlockable weapon more powerful. In other words, neither unlockable weapons suck anymore.

Better collision detection. The old system was a bit sensitive, due to some sacrifices I made for image quality. In the old days a rendering bug gave images this annoying 1 pixel border thing. My solution to the problem was to give each image a transparent 1 pixel border so even if the rendering bug was there, you could not see it because it would only affect the transparent border. Since I used hitTest for collision detection, that meant it was a little easier to get hit than I intended, by 2 pixels. This always bugged me but not many people seemed to notice and I didn’t have any better ideas at the time.

Samus is a little smarter. I noticed some mistakes in Samus’s attack routine where she walks along the ground and shoots you. It’s hard to notice because she usually falls back on a bombing run instead.

Arthur is a little smarter. The way Arthur detected incoming projectiles was a little clunky, so I improved it a bit. I actually went too far and he became the one, so I had to introduce a little chaos to make him less superhuman.

AIR version (WIP). I always wanted to let people download the game, but I couldn’t find an easy/free way to do it. I’m actually stuck on a significant problem, which I’m trying to resolve, so this is still incomplete. When I do get it working you’ll also get…

Fullscreen. Not just bigger too, but the game actually formats to the size of the screen! Widescreen NES. I think it’s pretty cool. This only comes with the future AIR edition, since Flash doesn’t yet allow keyboard input in fullscreen to the degree that the game needs.

Enjoy!