topical media & game development
actionscript-scribble-ScribbleAS3V2.ax
actionscript-scribble-ScribbleAS3V2.ax
[swf]
flex
package {
import flash.display.*;
import flash.events.*;
import flash.ui.*;
import flash.geom.*;
// A basic drawing application. This version draws a bitmap line
// in a BitmapData object every time MouseEvent.MOUSE_MOVE occurs.
// Line drawing is performed by a custom line drawing algorithm.
public class @ax-actionscript-scribble-ScribbleAS3V2 extends Sprite {
private var canvas:Bitmap;
private var canvasContainer:Sprite;
private var border:Shape;
private var isDrawing:Boolean = false;
private var lastX:int;
private var lastY:int;
public function @ax-actionscript-scribble-ScribbleAS3V2 () {
createCanvas();
registerForInputEvents();
// Prevent the app from resizing.
stage.scaleMode = StageScaleMode.NO_SCALE;
}
private function createCanvas (width:int = 200, height:int = 200):void {
// Define the data object that will store the actual pixel
// data for the user's drawing
var canvasData:BitmapData = new BitmapData(width,
height, false, 0xFFFFFFFF);
// Create a new displayable Bitmap, used to render the
// canvasData object created in the preceding line
canvas = new Bitmap(canvasData);
// Create a Sprite to contain the Bitmap. The Bitmap class
// doesn't broadcast input events, so put it in a Sprite so the
// user can interact with it.
canvasContainer = new Sprite();
canvasContainer.addChild(canvas);
// Add the canvasContainer Sprite (and the Bitmap it contains) to
// the display list so it appears on screen.
addChild(canvasContainer);
// Put a border around the drawing surface. Keep the border in a
// separate Sprite so that it doesn't trigger mouse interactivity.
border = new Shape();
border.graphics.lineStyle(1);
border.graphics.drawRect(0, 0, width, height);
addChild(border);
}
private function registerForInputEvents ():void {
// Register for mouse down and movement events broadcast
// by the canvasContainer.
canvasContainer.addEventListener(MouseEvent.MOUSE_DOWN,
mouseDownListener);
canvasContainer.addEventListener(MouseEvent.MOUSE_MOVE,
mouseMoveListener);
// Register for mouse up and key events broadcast by the Stage (i.e.,
// globally). Use the Stage because a mouse up event should always
// exit drawing mode, even if it occurs while the mouse pointer is not
// over the drawing. Likewise, the spacebar should always clear the
// drawing, even when canvasContainer isn't focussed.
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpListener);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownListener);
}
public function drawPoint (x:int, y:int, color:uint = 0xFF000000):void {
// Set the color of the specified pixel.
canvas.bitmapData.setPixel(x, y, color);
}
// Draws a non-antialiased line onto the BitmapData.
// Thanks to David Brackeen for the line-plotting algorithm.
// See: http://www.brackeen.com/home/vga/
public function drawLine (x1:int, y1:int, x2:int, y2:int,
color:uint = 0xFF000000):void {
var dx:int,dy:int,sdx:int,sdy:int,
px:int,py:int,dxabs:int,dyabs:int,i:int;
var slope:Number;
dx = x2-x1; // The horizontal distance of the line
dy = y2-y1; // The vertical distance of the line
dxabs = Math.abs(dx);
dyabs = Math.abs(dy);
sdx = signum(dx);
sdy = signum(dy);
// If the line is more horizontal than vertical
if (dxabs >= dyabs) {
slope = dy/dx;
for(i=0; i != dx; i += sdx) {
px = x1 + i; // Move along the line horizontally one pixel
py = y1 + slope*i; // Find the y for this x. The decimal is
// auto-truncated because py's datatype is int.
drawPoint(px, py, color);
}
// If the line is more vertical than horizontal
} else {
slope = dx/dy;
for(i=0; i != dy; i += sdy) {
py = y1 + i; // Move along the line vertically one pixel
px = x1 + slope*i; // Find the x for this y. The decimal is
// auto-truncated because py's datatype is int.
drawPoint(px, py, color);
}
}
}
public function signum (n:int):int {
if (n > 0) return 1;
if (n < 0) return -1;
return 0;
}
private function mouseDownListener (e:MouseEvent):void {
isDrawing = true;
lastX = int(e.localX);
lastY = int(e.localY);
// Draw a dot where the mouse was clicked
drawPoint(lastX, lastY);
}
private function mouseMoveListener (e:MouseEvent):void {
// Draw a line when the mouse moves over the drawing
// while the primary mouse button is depressed
if (isDrawing) {
// Use localX and localY to obtain pointer position relative to
// the canvasContainer. The coordinates would be coerced to ints
// without the cast, but we cast for clarity. In practice,
// these mouse coordinates are always integers.
var thisX:int = int(e.localX);
var thisY:int = int(e.localY);
// Draw a pixel-line to the new mouse location
drawLine(lastX, lastY, thisX, thisY);
// Remember the last mouse position for next time
lastX = thisX;
lastY = thisY;
// Update the screen immediately following the execution of
// this event listener function
e.updateAfterEvent();
}
}
private function mouseUpListener (e:MouseEvent):void {
isDrawing = false;
}
private function keyDownListener (e:KeyboardEvent):void {
// Clear the drawing when the spacebar is pressed
if (e.charCode == Keyboard.SPACE) {
canvas.bitmapData.fillRect(new Rectangle(0, 0,
canvas.width, canvas.height), 0xFFFFFFFF);
}
}
}
}
(C) Æliens
27/08/2009
You may not copy or print any of this material without explicit permission of the author or the publisher.
In case of other copyright issues, contact the author.