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=1\n\rTraceOutputFileEnable=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!

Mega Man vs Ghosts 'n Goblins 2.0

December 27th, 2009

So I’ve been pumping everything I know about 2D platformers into this game engine in my free time. Schoolwork and other distractions conspire against me to delay this effort, so I’ve been doing it for a while. I decided to use Mega Man vs Ghosts ‘n Goblin‘s content to make an incomplete game as a way to find bugs and further understand what the engine needed. Naturally this turned into a complete port.

I graduated from college a few weeks ago, and rather than look for a job like I should be doing, I used the time to finish it up. Since 95% of the work that’s been done also works for it’s prequel, I’m already planning on redoing that one too.

Even though I would normally leave well enough alone I’ve really got a soft spots for these two games, and some things about them really bother me. Namely the numerous framerate shenanigans I pulled in the past have made them inexplicably choppy today. That and I hate the unlockable weapons. A lot.

So, here it is. The new and improved Mega Man vs Ghosts ‘n Goblins. Once I finish the other one I’ll try and spread them out across the Internet. If you find any bugs let me know.

EDIT: Play both games here.

I like my shared host, it’s cheap, it’s great, and any problems are easily overcome through a little ingenuity. In this case it’s hotlinking, something that’s been a serious problem in the past without a clear solution. Time has proven blocking outside referers with an .htaccess file is both ineffective, and can cost honest users. Without access to the httpd.conf, I’m forced to do things a little differently.

The system I have works using an .htaccess file that requires all files accessed in its folder have a unique key in the URL (as part of the query, the stuff that comes after the ‘?’ symbol). This key is changed every once in a while, and the .htaccess file is simply rewritten with the new information.

The files are updated by a cron job that runs a bash file that updates all the files. It fails gracefully too, if any file is unwritable everything will be left in a working state, albeit one that doesn’t prevent hotlinking anymore. The .htaccess file also lets the previously used key to still be used as well, so that the URLs don’t expire immediately after a new key is introduced.

Here’s how to get it working.

1. Get the files.

Available here. The files in the protected folder should similarly go into the folder you want protected and “update-key” should go somewhere else where it can be executed by the cron job but have no chance of being visible to the outside world. Make sure the file permissions are kept intact, “.htaccess” and “.htkey” files must all be writable by the cron job and “update-key” must be executable.

2. Set up a cron job.

Add a cron job that executes update-key every so often with whatever method you’re allowed. The “update-key” script changes files in the current directory, so you need to execute it in the same folder as the .ht files. Here’s an example cron job that runs every 8 hours. Change the paths to the right locations.

0 0,8,16 * * * cd $HOME/path/to/protected && $HOME/path/to/update-key

3. Use it in your pages.

To generate the URLs, just dump the contents of “.htkey”  as your key at the end of the URL. Here’s some examples.

PHP

<? echo '<img src="http://www.brokenfunction.com/protected/awesome.jpg?key=' . trim(array_pop(file("/path/to/protected/.htkey"))) . '">' ?>

Python

keyfile = open("/path/to/protected/.htkey", "r")
key = keyfile.readline().strip()
keyfile.close()
print("<a href='http://www.brokenfunction.com/protected/awesome.jpg?key=%s' />" % key)

If anybody can offer some other examples in the comments I’ll add them here.

This isn’t a perfect solution of course, anybody could check with your site and update their links accordingly whenever the key changes, but it’s good for lightweight protection and a lot more reliable than referer blocking.