Display object example: SpriteArranger

Flash Player 9 and later, Adobe AIR 1.0 and later

The SpriteArranger sample application builds upon the Geometric Shapes sample application described separately in Learning ActionScript 3.0.

The SpriteArranger sample application illustrates a number of concepts for dealing with display objects:

  • Extending display object classes

  • Adding objects to the display list

  • Layering display objects and working with display object containers

  • Responding to display object events

  • Using properties and methods of display objects

To get the application files for this sample, see www.adobe.com/go/learn_programmingAS3samples_flash. The SpriteArranger application files can be found in the folder Examples/SpriteArranger. The application consists of the following files:

File

Description

SpriteArranger.mxml

or

SpriteArranger.fla

The main application file in Flash (FLA) or Flex (MXML).

com/example/programmingas3/SpriteArranger/CircleSprite.as

A class defining a type of Sprite object that renders a circle on-screen.

com/example/programmingas3/SpriteArranger/DrawingCanvas.as

A class defining the canvas, which is a display object container that contains GeometricSprite objects.

com/example/programmingas3/SpriteArranger/SquareSprite.as

A class defining a type of Sprite object that renders a square on-screen.

com/example/programmingas3/SpriteArranger/TriangleSprite.as

A class defining a type of Sprite object that renders a triangle on-screen.

com/example/programmingas3/SpriteArranger/GeometricSprite.as

A class that extends the Sprite object, used to define an on-screen shape. The CircleSprite, SquareSprite, and TriangleSprite each extend this class.

com/example/programmingas3/geometricshapes/IGeometricShape.as

The base interface defining methods to be implemented by all geometric shape classes.

com/example/programmingas3/geometricshapes/IPolygon.as

An interface defining methods to be implemented by geometric shape classes that have multiple sides.

com/example/programmingas3/geometricshapes/RegularPolygon.as

A type of geometric shape that has sides of equal length positioned symmetrically around the shape’s center.

com/example/programmingas3/geometricshapes/Circle.as

A type of geometric shape that defines a circle.

com/example/programmingas3/geometricshapes/EquilateralTriangle.as

A subclass of RegularPolygon that defines a triangle with all sides the same length.

com/example/programmingas3/geometricshapes/Square.as

A subclass of RegularPolygon defining a rectangle with all four sides the same length.

com/example/programmingas3/geometricshapes/GeometricShapeFactory.as

A class containing a “factory method” for creating shapes given a shape type and size.

Defining the SpriteArranger classes

The SpriteArranger application lets the user add a variety of display objects to the on-screen “canvas.”

The DrawingCanvas class defines a drawing area, a type of display object container, to which the user can add on-screen shapes. These on-screen shapes are instances of one of the subclasses of the GeometricSprite class.

The DrawingCanvas class

In Flex, all child display objects added to a Container object must be of a class that descends from the mx.core.UIComponent class. This application adds an instance of the DrawingCanvas class as a child of an mx.containers.VBox object, as defined in MXML code in the SpriteArranger.mxml file. This inheritance is defined in the DrawingCanvas class declaration, as follows:

public class DrawingCanvas extends UIComponent

The UIComponent class inherits from the DisplayObject, DisplayObjectContainer, and Sprite classes, and the code in the DrawingCanvas class uses methods and properties of those classes.

The DrawingCanvas class extends the Sprite class, and this inheritance is defined in the DrawingCanvas class declaration, as follows:

public class DrawingCanvas extends Sprite

The Sprite class is a subclass of the DisplayObjectContainer and DisplayObject classes, and the DrawingCanvas class uses methods and properties of those classes.

The DrawingCanvas() constructor method sets up a Rectangle object, bounds, which is property that is later used in drawing the outline of the canvas. It then calls the initCanvas() method, as follows:

this.bounds = new Rectangle(0, 0, w, h); 
initCanvas(fillColor, lineColor);

AS the following example shows, the initCanvas() method defines various properties of the DrawingCanvas object, which were passed as arguments to the constructor function:

this.lineColor = lineColor; 
this.fillColor = fillColor; 
this.width = 500; 
this.height = 200;

The initCanvas() method then calls the drawBounds() method, which draws the canvas using the DrawingCanvas class’s graphics property. The graphics property is inherited from the Shape class.

this.graphics.clear();         
this.graphics.lineStyle(1.0, this.lineColor, 1.0); 
this.graphics.beginFill(this.fillColor, 1.0); 
this.graphics.drawRect(bounds.left - 1,  
                        bounds.top - 1,  
                        bounds.width + 2, 
                        bounds.height + 2); 
this.graphics.endFill();

The following additional methods of the DrawingCanvas class are invoked based on user interactions with the application:

The GeometricSprite class and its subclasses

Each display object the user can add to the canvas is an instance of one of the following subclasses of the GeometricSprite class:

  • CircleSprite

  • SquareSprite

  • TriangleSprite

The GeometricSprite class extends the flash.display.Sprite class:

public class GeometricSprite extends Sprite

The GeometricSprite class includes a number of properties common to all GeometricSprite objects. These are set in the constructor function based on parameters passed to the function. For example:

this.size = size; 
this.lineColor = lColor; 
this.fillColor = fColor;

The geometricShape property of the GeometricSprite class defines an IGeometricShape interface, which defines the mathematical properties, but not the visual properties, of the shape. The classes that implement the IGeometricShape interface are defined in the GeometricShapes sample application described in Learning ActionScript 3.0.

The GeometricSprite class defines the drawShape() method, which is further refined in the override definitions in each subclass of GeometricSprite. For more information, see the “Adding display objects to the canvas” section, which follows.

The GeometricSprite class also provides the following methods:

Adding display objects to the canvas

When the user clicks the Add Shape button, the application calls the addShape() method of the DrawingCanvas class. It instantiates a new GeometricSprite by calling the appropriate constructor function of one of the GeometricSprite subclasses, as the following example shows:

public function addShape(shapeName:String, len:Number):void 
{ 
    var newShape:GeometricSprite; 
    switch (shapeName) 
    { 
        case "Triangle": 
            newShape = new TriangleSprite(len); 
            break; 
 
        case "Square": 
            newShape = new SquareSprite(len); 
            break; 
 
        case "Circle": 
            newShape = new CircleSprite(len); 
            break; 
    } 
    newShape.alpha = 0.8; 
    this.addChild(newShape); 
}

Each constructor method calls the drawShape() method, which uses the graphics property of the class (inherited from the Sprite class) to draw the appropriate vector graphic. For example, the drawShape() method of the CircleSprite class includes the following code:

this.graphics.clear(); 
this.graphics.lineStyle(1.0, this.lineColor, 1.0); 
this.graphics.beginFill(this.fillColor, 1.0); 
var radius:Number = this.size / 2; 
this.graphics.drawCircle(radius, radius, radius);

The second to last line of the addShape() function sets the alpha property of the display object (inherited from the DisplayObject class), so that each display object added to the canvas is slightly transparent, letting the user see the objects behind it.

The final line of the addChild() method adds the new display object to the child list of the instance of the DrawingCanvas class, which is already on the display list. This causes the new display object to appear on the Stage.

The interface for the application includes two text fields, selectedSpriteTxt and outputTxt. The text properties of these text fields are updated with information about the GeometricSprite objects that have been added to the canvas or selected by the user. The GeometricSprite class handles this information-reporting task by overriding the toString() method, as follows:

public override function toString():String 
{ 
    return this.shapeType + " of size " + this.size + " at " + this.x + ", " + this.y; 
}

The shapeType property is set to the appropriate value in the constructor method of each GeometricSprite subclass. For example, the toString() method might return the following value for a CircleSprite instance recently added to the DrawingCanvas instance:

Circle of size 50 at 0, 0

The describeChildren() method of the DrawingCanvas class loops through the canvas’s child list, using the numChildren property (inherited from the DisplayObjectContainer class) to set the limit of the for loop. It generates a string listing each child, as follows:

var desc:String = ""; 
var child:DisplayObject; 
for (var i:int=0; i < this.numChildren; i++) 
{ 
child = this.getChildAt(i); 
desc += i + ": " + child + '\n'; 
}

The resulting string is used to set the text property of the outputTxt text field.

Clicking and dragging display objects

When the user clicks on a GeometricSprite instance, the application calls the onMouseDown() event handler. As the following shows, this event handler is set to listen for mouse down events in the constructor function of the GeometricSprite class:

this.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);

The onMouseDown() method then calls the showSelected() method of the GeometricSprite object. If it is the first time this method has been called for the object, the method creates a new Shape object named selectionIndicator and it uses the graphics property of the Shape object to draw a red highlight rectangle, as follows:

this.selectionIndicator = new Shape(); 
this.selectionIndicator.graphics.lineStyle(1.0, 0xFF0000, 1.0); 
this.selectionIndicator.graphics.drawRect(-1, -1, this.size + 1, this.size + 1); 
this.addChild(this.selectionIndicator);

If this is not the first time the onMouseDown() method is called, the method simply sets the selectionIndicator shape’s visible property (inherited from the DisplayObject class), as follows:

this.selectionIndicator.visible = true;

The hideSelected() method hides the selectionIndicator shape of the previously selected object by setting its visible property to false.

The onMouseDown() event handler method also calls the startDrag() method (inherited from the Sprite class), which includes the following code:

var boundsRect:Rectangle = this.parent.getRect(this.parent); 
boundsRect.width -= this.size; 
boundsRect.height -= this.size; 
this.startDrag(false, boundsRect);

This lets the user drag the selected object around the canvas, within the boundaries set by the boundsRect rectangle.

When the user releases the mouse button, the mouseUp event is dispatched. The constructor method of the DrawingCanvas sets up the following event listener:

this.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);

This event listener is set for the DrawingCanvas object, rather than for the individual GeometricSprite objects. This is because when the GeometricSprite object is dragged, it could end up behind another display object (another GeometricSprite object) when the mouse is released. The display object in the foreground would receive the mouse up event but the display object the user is dragging would not. Adding the listener to the DrawingCanvas object ensures that the event is always handled.

The onMouseUp() method calls the onMouseUp() method of the GeometricSprite object, which in turn calls the stopDrag() method of the GeometricSprite object.

Rearranging display object layering

The user interface for the application includes buttons labeled Move Back, Move Down, Move Up, and Move to Front. When the user clicks one of these buttons, the application calls the corresponding method of the DrawingCanvas class: moveToBack(), moveDown(), moveUp(), or moveToFront(). For example, the moveToBack() method includes the following code:

public function moveToBack(shape:GeometricSprite):void 
{ 
    var index:int = this.getChildIndex(shape); 
    if (index > 0) 
    { 
        this.setChildIndex(shape, 0); 
    } 
}

The method uses the setChildIndex() method (inherited from the DisplayObjectContainer class) to position the display object in index position 0 in the child list of the DrawingCanvas instance (this).

The moveDown() method works similarly, except that it decrements the index position of the display object by 1 in the child list of the DrawingCanvas instance:

public function moveDown(shape:GeometricSprite):void 
{ 
    var index:int = this.getChildIndex(shape); 
    if (index > 0) 
    { 
        this.setChildIndex(shape, index - 1); 
    } 
}

The moveUp() and moveToFront() methods work similarly to the moveToBack() and moveDown() methods.