Feeds:
Posts
Comments

Flash security is, in a word, whack. I won’t even attempt to summarize the full schebang right now, but one trick I just learned: compile with the “-use-network=false” flag if you want to load a local resource from disk, such as when testing with SAFlashPlayer.exe. (So far as I can tell, “-use-network=true” does absolutely nothing as it still doesn’t let me access the network when I run from inside SAFlashPlayer.exe.)

Tip: If you ever want a complete list of all compiler options, just run “mxmlc.exe -help list advanced details"

MXML for Fun and Profit

So Flash is pretty sweet for low-level graphics coding. But it’s a bit, er, low-level for full UI development. Enter MXML, what HTML would look like if Adobe designed it. Luckily, compiling it doesn’t appear to be any more difficult than with ActionScript. Simply dump this into a HelloWorld.mxml file:

<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Panel title="Hello world!" width="100%" height="100%">
</mx:Panel>
</mx:Application>

And then compile it as so:

\flex\bin\mxmlc.exe HelloWorld.mxml

And it’ll spit out HelloWorld.swf. Drop that into a webpage or run it as normal:

\flex\player\debug\SAFlashPlayer.exe HelloWorld.swf

And voila — your first MXML application:

Hello World in MXML

No Block Scoping

Ah, this is a fun lesson: unlike C, C++, or any “real” programming language, variables defined inside a block (ie, surrounded by curly braces) are not defined in their own scope. Or, another way of saying it is a function only has a single scope, and any variable defined in any block in that function is considered to be in the same scope. Or perhaps an even better way of describing it is with an example. in C++, the following code would fail to compile:

{ int a = 0; }
++a; // 'a' isn't defined here

However, in ActionScript, this code compiles just fine:

{ var a:int = 0; }
++a; // 'a' is defined in the parent scope

Madness!

Creating a Package

It seems like it should be extremely easy to group classes into packages, but I’ve had a hell of a time trying to derive any meaning from the documentation. After much trial and error, I’ve figured out the following minimal example to show how to create and compile a basic package. This example shows two classes, ClassA and ClassB, where the latter instantiates one of the former.

First, create a directory named testpackage, and two files: testpackage/ClassA.as, and testpackage/ClassB.as. In ClassA.as, put the following:

package testpackage {
    public class ClassA { }
}

In ClassB.as, put:

package testpackage {
    import testpackage.ClassB;
    public class ClassB {
        private var a:ClassA;
        public function ClassB( ) { a = new ClassA( ); }
    }
}

Now, to compile, run the following command in the parent of /testproject:

mxmlc -compiler.source-path=. testpackage/ClassB.as

(Without the -compiler.source-path=. command-line parameter, it won’t search children of the current directory for package source files.) Whew, wasn’t that easy?

Update: Just in case you’re still having trouble, take note that it’s “-compiler.source-path” and not “-compiler.source.path”. The extra dash makes all the difference, as I found out after staring at my own instructions for a considerable amount of time.

So you might be embedding you SWF into an HTML page and then you discover that stageWidth/stageHeight are almost but not entirely unrelated to the actual dimensions of the embedded component. Or, rather, it’s more complex than that: they equate exactly to the dimensions you provide, but drawing a box from (0,0)->(stageWidth,stageHeight) doesn’t actually bound the embedded component as you’d expect. For example, assume you embed a simple 800×200 component into a page that tries to simply outline itself in red. You’ll get something crazy like:

Crazy Green/red boxes

Basically, the red box you draw outlining the stage seems almost entirely unlike the component outline. However, there’s this other box that does look suspicious: if you draw a green box from (0,0)->(500,350) it’ll mysteriously be centered and scaled perfectly. The reason? mxmlc.exe has a “-default-size” parameter that — when not set — is apparently set to 500×350. Intead, add -default-size 800 200 (or whatever dimensions you want), and it’ll come out right:

Sane green and red boxes

So one of the first things you might wonder is “what’s my width?” Probably the first thing you’ll do is just test this.width (ie, the width of the current sprite). However, it’s zero. Then you might think to try stage.width, but it’s also zero. The correct answer is stage.stageWidth.

As for the others, they describe the current width of what has been drawn, not the canvas size. In other words, they will stay zero until you start drawing, and then they’ll describe the total width (in pixels, I think — or maybe in the parent coordinate system, which by default is pixels. I’m still working that out) of what has been drawn so far.

My First Animation

Ready for some animation? It’s quite easy: just listen for the ENTER_FRAME event sent by the “stage” (the object representing the canvas on which all graphics are drawn) as follows:

package {
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.display.Stage;
    public class HelloWorld extends Sprite {
        private var size:int = 40;
        public function HelloWorld( ) {
            stage.addEventListener( Event.ENTER_FRAME, onRender );
        }
        private function onRender( event:Event ):void {
            graphics.beginFill( 0xFFCC00 );
            graphics.drawCircle( 40, 40, size );
            size += 10;
        }
    }
}

Check out the Stage documentation for how to set the framerate and such.

Wow, that’s very strange.

HelloWorld.html

Generally you don’t want your component to take up the entire page. Rather, you want to embed it somewhere in another page. No trouble, just put this in a HelloWorld.html file and you’re good to go:

<html>
    <body>
      <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
              id="HelloWorld" width="500" height="375"
              codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab">
          <param name="movie" value="HelloWorld.swf" />
          <param name="quality" value="high" />
          <param name="bgcolor" value="#869ca7" />
          <param name="allowScriptAccess" value="always" />
          <embed src="HelloWorld.swf" quality="high" bgcolor="#869ca7"
                 width="500" height="375" name="HelloWorld" align="middle"
                 play="true" loop="false" quality="high" allowScriptAccess="always"
                 type="application/x-shockwave-flash"
                 pluginspage="http://www.macromedia.com/go/getflashplayer">
          </embed>
      </object>
    </body>
</html>

HelloWorld.swf

One thing I was surprised to learn is how easy it is to program in ActionScript. It’s pretty much just like a compiled version of JavaScript, with a few slight improvements. One thing to keep in mind, however, is the output is a SWF file rather than an EXE, and the “application” is very graphically oriented: I’m not even sure if you can make an ActionScript application that has no GUI. So, our basic HelloWorld application is as follows:

package {
    import flash.display.Sprite;
    public class HelloWorld extends Sprite {
        public function HelloWorld( ) {
            graphics.beginFill( 0xFFCC00 );
            graphics.drawCircle( 40, 40, 40 );
        }
    }
}

Save that into a file named “HelloWorld.as”, and then run “mxmlc.exe HelloWorld.as”. It’ll spit out HelloWorld.swf. Drag that into a FireFox window (or run SAFlashPlayer.exe HelloWorld.as — it’s supplied with the Flex SDK) and Tah Dah! Your very first Flash component, compiled from scratch.

« Newer Posts - Older Posts »