How to use images in ActionScript 3 with FlashDevelop (and some other AS3 tips)

update: I’ve created a new and updated tutorial on embedding images in FlashDevelop. I suggest you check out that tutorial instead of the one below. The new tutorial is cleaner, clearer and more up-to-date.

One of the main bumps you will run into when coding Sandy3D, or basically any kind of graphical applet is loading resources, such as images. If you are working inside Adobe’s Flash environment, this all comes pretty naturally. But open source tools such as FlashDevelop do not have a graphical component, so you have to create your multimedia assets in other applications (Paint.NET is nice).

Before you get started, have a look at this MovieClip vs Sprite comparison and this tutorial on starting with AS3 to understand why our base class extends Sprite and how events are handled. And if you want to know where all this is going, the idea is to recreate something similar to this in ActionScript 3 and FlashDevelop and then afterwards add some 3D goodness to it (3D objects, maybe 3D camera).

One important thing to know about event handlers is: don’t attach them to your main Sprite. This won’t work:

1
2
3
4
5
6
7
8
9
10
11
public class Test extends Sprite {
  public function Test() {
    graphics.lineStyle(1);
    graphics.beginFill(0xFF8000);
    graphics.drawCircle(50, 50, 10);
    addEventListener(MouseEvent.MOUSE_DOWN, down);
  }
  private function down(evt:MouseEvent):void {
    trace("down");
  }
}

My intuition was that it would attach mouse down events to the circle. But it does not. In most cases you would want to capture the whole sprite anyway. The solution is to add your listeners to the “stage” object. See the the examples below for a demonstration of this.

In Flash, images come in 2 types. Vector drawings or bitmaps. Pretty much all graphics you see on the Internet are bitmaps, every pixel in the bitmap is defined. A program such as Paint.NET will create those for you. Vector images are a different beast. Those images define the lines and forms that are used. In the example above, a circle is drawn, not a collection of points. The advantage is that the image quality will be a lot higher and it is possible to zoom in on the Flash applet without loosing quality. But (there always is a but) you can only draw those in the Adobe Flash editor. You can use existing .fla files with vector drawings in them, but you can’t make your own, unless you pay for the program. Either that or you would have to handcode everything. A future post will probably deal with that.

But this post deals with bitmaps. We will start from the following simple mouse-follow applet and replace the circle with a bitmap:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package  {
  import flash.display.Sprite;
  import flash.events.Event;
  import flash.ui.Mouse;
 
  public class Test extends Sprite {
 
    private var circle:Sprite = new Sprite();
 
    public function Test() {
      Mouse.hide();
 
      circle.graphics.lineStyle(1);
      circle.graphics.beginFill(0xFF8000);
      circle.graphics.drawCircle(0, 0, 10);
      addChild(circle);
 
      stage.addEventListener(Event.ENTER_FRAME, mouseMove);
    }
    private function mouseMove(evt:Event):void {
      circle.x = mouseX;
      circle.y = mouseY;
    }
  }
}

This is the result:

(Either JavaScript is not active or you are using an old version of Adobe Flash Player. Please install the newest Flash Player.)

I like to store all my resources in a separate directory, called “library“. It’s not a the “real” library that you have in the Flash IDE, but it’s close enough. I’m using this crosshair bitmap:

Once we have an image, it’s time to embed it. ActionScript 3 has an “Embed” tag that will allow you to put images in an applet. See this link for the complete explanation. Basically, you define a private Class variable, put the cursor just above it and double click on your image. FlashDevelop will automatically insert the correct “Embed” tag in your code. A little tweaking to get the correct size and there you are:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package  {
 
	import flash.display.Bitmap;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.ui.Mouse;
 
	public class Test extends Sprite {
 
		[Embed(source='library/crosshair.png')]
		private var crosshairClass:Class;
		private var crosshair:Bitmap = new crosshairClass ();
 
		public function Test() {
			Mouse.hide();
 
			crosshair.height = 30;
			crosshair.width = 30;
			addChild(crosshair);
 
			stage.addEventListener(Event.ENTER_FRAME, mouseMove);
		}
 
		private function mouseMove(evt:Event):void {
			crosshair.x = mouseX - 15;
			crosshair.y = mouseY - 15;
		}
 
	}
 
}

(Either JavaScript is not active or you are using an old version of Adobe Flash Player. Please install the newest Flash Player.)

As you will notice, the quality of the scaled down image is not that good, but using a larger sprite allows you to zoom in with little quality loss. Next time, I’ll show you how to fix this.

15 thoughts on “How to use images in ActionScript 3 with FlashDevelop (and some other AS3 tips)”

  1. I couldn’t figure out how to get FD to add the embed code for me. I wrote the private class just like in the example, and double clicked on the file I had added to the project via the Project Manager in FD. It just tries to open the file in a tab, which results in a mess since it’s not a text file (it’s an mp3).

    Typing the embed code manually worked fine though. This tutorial was extremely helpful to me. Thank you!

  2. I couldn’t figure out how to get FD to add the embed code for me. I wrote the private class just like in the example, and double clicked on the file I had added to the project via the Project Manager in FD. It just tries to open the file in a tab, which results in a mess since it’s not a text file (it’s an mp3).

    Typing the embed code manually worked fine though. This tutorial was extremely helpful to me. Thank you!

  3. I haven’t seen that happen to me. It might be a setting hidden somewhere in the config, though I couldn’t really find something applicable.

    What you could always do in that case, is right-click on the file you want to embed and select “Insert Into Document”. If that choice is not available, make sure “Add to Library” is selected (this option is also in the right-click context menu).

  4. I haven’t seen that happen to me. It might be a setting hidden somewhere in the config, though I couldn’t really find something applicable.

    What you could always do in that case, is right-click on the file you want to embed and select “Insert Into Document”. If that choice is not available, make sure “Add to Library” is selected (this option is also in the right-click context menu).

  5. Ah, finally a tutorial with source code that works ‘out-of-the-box’ for me. Thanks for teaching me how to display images using only actionscript!!

  6. Ah, finally a tutorial with source code that works ‘out-of-the-box’ for me. Thanks for teaching me how to display images using only actionscript!!

  7. Do you know why it doesnt work with an embedded image and and ambedded ASE model together.
    I got it working with an image only. great. And i got it working with an ASE model only. great. But when I try to coat an embedded model with a jpg it doesnt work. Can you please help? Code is hereunder:

    package
    {
    import flash.display.Bitmap;
    import flash.display.Sprite;
    import flash.display.BitmapData;
    import flash.display.Bitmap;

    import flash.events.*;
    import flash.ui.*;
    import sandy.core.Scene3D;
    import sandy.core.data.*;
    import sandy.core.scenegraph.*;
    import sandy.materials.*;
    import sandy.materials.attributes.*;
    import sandy.primitive.*;
    import sandy.parser.*;
    import sandy.util.*;
    import sandy.events.*;

    public class Example009 extends Sprite
    {
    private var scene:Scene3D;
    private var camera:Camera3D;
    private var box:Box;
    private var sphere:Sphere;
    private var app01:Appearance;
    private var app02:Appearance;
    //private var img:MyPalm = new MyPalm();
    //USE ANY IMAGE:
    [Embed(source='/PHOTOMODELLER/photomo1.jpg')] ///assets/palm.jpg’)]
    private var imgClass:Class;
    private var img:Bitmap = new imgClass ();
    private var bitmap:Bitmap = new Bitmap(img.bitmapData);

    [Embed( source="assets/teieraASE.ASE", mimeType="application/octet-stream" )]
    private var aseClass:Class;

    public function Example009()
    {
    var parser1:IParser = Parser.create( new imgClass(), Parser.ASE, 1 ); //eksempel fRa 0.1 til 1 – størrelsen!
    //parser1.standardAppearance = createAppearance( NONE );
    //parser.addEventListener( ParserEvent.FAIL, onError );
    parser1.addEventListener( ParserEvent.INIT, init );
    parser1.parse();
    }

    // Create the scene graph based on the root Group of the scene
    private function init(p_eEvent:ParserEvent ):void
    {

    // We create the camera
    camera = new Camera3D( 300, 300 );
    camera.z = -400;

    // We create the “group” that is the tree of all the visible objects
    var root:Group = createScene(p_eEvent);

    // We create a Scene and we add the camera and the objects tree
    scene = new Scene3D( “scene”, this, camera, root );

    // Listen to the heart beat and render the scene
    addEventListener( Event.ENTER_FRAME, enterFrameHandler );
    stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed);
    }

    // Create the scene graph based on the root Group of the scene
    private function createScene(p_eEvent):Group
    {
    // Create the root Group
    var g:Group = new Group(p_eEvent.group);

    // Create a cube so we have something to show
    box = new Box( “box”,80,80,80,”tri”);

    box.rotateX = 30;
    box.rotateY = 30;
    box.x = -80;

    ////////////////////////////////////////////
    //sphere = new Sphere(“sphere”, 50,10,10);
    //sphere.x = 80;

    //THE PROBLEM IS HERE:
    sphere = g.children[0];
    sphere.x = 0;
    /////////////////////////////////////////////

    // we define the bitmap Material
    var materialAttr01:MaterialAttributes = new MaterialAttributes( new LightAttributes( true, 0.1) );
    var material01:Material = new ColorMaterial( 0xFFCC33, 1, materialAttr01 );
    material01.lightingEnable = true;
    app01 = new Appearance( material01 );

    var material02:BitmapMaterial = new BitmapMaterial( bitmap.bitmapData );
    material02.lightingEnable = true;
    app02 = new Appearance( material02 );

    box.appearance = app02;
    sphere.appearance = app02;

    // We need to add the cube to the group
    g.addChild( box );
    g.addChild( sphere );

    return g;
    }

    // The Event.ENTER_FRAME event handler tells the Scene3D to render
    private function enterFrameHandler( event : Event ) : void
    {
    box.tilt += 1;
    box.pan += 1;
    sphere.pan += 1
    scene.render();
    }
    // The KeyboardEvent.KEY_DOWN event handler manage key pressed by user
    private function keyPressed(event:KeyboardEvent):void
    {
    switch(event.keyCode) {
    case Keyboard.UP:
    box.aPolygons[0].appearance = app02;
    box.aPolygons[1].appearance = app02;
    box.aPolygons[2].appearance = app02;
    box.aPolygons[3].appearance = app02;
    break;
    case Keyboard.DOWN:
    box.appearance = app01;
    break;
    case Keyboard.RIGHT:
    box.aPolygons[4].appearance = app02;
    box.aPolygons[5].appearance = app02;
    box.aPolygons[6].appearance = app02;
    box.aPolygons[7].appearance = app02;
    break;
    case Keyboard.LEFT:
    box.aPolygons[8].appearance = app02;
    box.aPolygons[9].appearance = app02;
    box.aPolygons[10].appearance = app02;
    box.aPolygons[11].appearance = app02;
    break;
    }
    }
    }
    }

  8. Do you know why it doesnt work with an embedded image and and ambedded ASE model together.
    I got it working with an image only. great. And i got it working with an ASE model only. great. But when I try to coat an embedded model with a jpg it doesnt work. Can you please help? Code is hereunder:

    package
    {
    import flash.display.Bitmap;
    import flash.display.Sprite;
    import flash.display.BitmapData;
    import flash.display.Bitmap;

    import flash.events.*;
    import flash.ui.*;
    import sandy.core.Scene3D;
    import sandy.core.data.*;
    import sandy.core.scenegraph.*;
    import sandy.materials.*;
    import sandy.materials.attributes.*;
    import sandy.primitive.*;
    import sandy.parser.*;
    import sandy.util.*;
    import sandy.events.*;

    public class Example009 extends Sprite
    {
    private var scene:Scene3D;
    private var camera:Camera3D;
    private var box:Box;
    private var sphere:Sphere;
    private var app01:Appearance;
    private var app02:Appearance;
    //private var img:MyPalm = new MyPalm();
    //USE ANY IMAGE:
    [Embed(source='/PHOTOMODELLER/photomo1.jpg')] ///assets/palm.jpg’)]
    private var imgClass:Class;
    private var img:Bitmap = new imgClass ();
    private var bitmap:Bitmap = new Bitmap(img.bitmapData);

    [Embed( source="assets/teieraASE.ASE", mimeType="application/octet-stream" )]
    private var aseClass:Class;

    public function Example009()
    {
    var parser1:IParser = Parser.create( new imgClass(), Parser.ASE, 1 ); //eksempel fRa 0.1 til 1 – størrelsen!
    //parser1.standardAppearance = createAppearance( NONE );
    //parser.addEventListener( ParserEvent.FAIL, onError );
    parser1.addEventListener( ParserEvent.INIT, init );
    parser1.parse();
    }

    // Create the scene graph based on the root Group of the scene
    private function init(p_eEvent:ParserEvent ):void
    {

    // We create the camera
    camera = new Camera3D( 300, 300 );
    camera.z = -400;

    // We create the “group” that is the tree of all the visible objects
    var root:Group = createScene(p_eEvent);

    // We create a Scene and we add the camera and the objects tree
    scene = new Scene3D( “scene”, this, camera, root );

    // Listen to the heart beat and render the scene
    addEventListener( Event.ENTER_FRAME, enterFrameHandler );
    stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed);
    }

    // Create the scene graph based on the root Group of the scene
    private function createScene(p_eEvent):Group
    {
    // Create the root Group
    var g:Group = new Group(p_eEvent.group);

    // Create a cube so we have something to show
    box = new Box( “box”,80,80,80,”tri”);

    box.rotateX = 30;
    box.rotateY = 30;
    box.x = -80;

    ////////////////////////////////////////////
    //sphere = new Sphere(“sphere”, 50,10,10);
    //sphere.x = 80;

    //THE PROBLEM IS HERE:
    sphere = g.children[0];
    sphere.x = 0;
    /////////////////////////////////////////////

    // we define the bitmap Material
    var materialAttr01:MaterialAttributes = new MaterialAttributes( new LightAttributes( true, 0.1) );
    var material01:Material = new ColorMaterial( 0xFFCC33, 1, materialAttr01 );
    material01.lightingEnable = true;
    app01 = new Appearance( material01 );

    var material02:BitmapMaterial = new BitmapMaterial( bitmap.bitmapData );
    material02.lightingEnable = true;
    app02 = new Appearance( material02 );

    box.appearance = app02;
    sphere.appearance = app02;

    // We need to add the cube to the group
    g.addChild( box );
    g.addChild( sphere );

    return g;
    }

    // The Event.ENTER_FRAME event handler tells the Scene3D to render
    private function enterFrameHandler( event : Event ) : void
    {
    box.tilt += 1;
    box.pan += 1;
    sphere.pan += 1
    scene.render();
    }
    // The KeyboardEvent.KEY_DOWN event handler manage key pressed by user
    private function keyPressed(event:KeyboardEvent):void
    {
    switch(event.keyCode) {
    case Keyboard.UP:
    box.aPolygons[0].appearance = app02;
    box.aPolygons[1].appearance = app02;
    box.aPolygons[2].appearance = app02;
    box.aPolygons[3].appearance = app02;
    break;
    case Keyboard.DOWN:
    box.appearance = app01;
    break;
    case Keyboard.RIGHT:
    box.aPolygons[4].appearance = app02;
    box.aPolygons[5].appearance = app02;
    box.aPolygons[6].appearance = app02;
    box.aPolygons[7].appearance = app02;
    break;
    case Keyboard.LEFT:
    box.aPolygons[8].appearance = app02;
    box.aPolygons[9].appearance = app02;
    box.aPolygons[10].appearance = app02;
    box.aPolygons[11].appearance = app02;
    break;
    }
    }
    }
    }

  9. [Embed(source='library/crosshair.png')]

    See that? It's 'library/crosshair.png'
    It's a single.. Flying thingy. It has to be double.

    [Embed(source="library/crosshair.png")]

  10. Hi.
    Im using such construction in MXML

    Thats copypasted from flexbuilder – now Im switching to FlashDevelop and I have a problem because using @Embed doesnt let build finish succesfully (and it even doesnt return any bug arrors – just informs me that “Build failed”).

    Do you have some idea on it?

Comments are closed.