/** * Neave Imagination ...big wobbly elephants * * Copyright (C) 2008 Paul Neave * http://www.neave.com/ * * @author Paul Neave * @version 1.0.0 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation at http://www.gnu.org/licenses/gpl.html */ package // com.neave.imagination { import flash.display.*; import flash.events.*; import flash.filters.*; import flash.geom.*; // import com.neave.link.*; public class lib_present_graphic_imagination_com_neave_imagination_NeaveImagination { // Main constants private const RED_STEP:Number = 0.02; private const GREEN_STEP:Number = 0.015; private const BLUE_STEP:Number = 0.025; private const MAX_LENGTH:int = 80; private const SPREAD_MIN:int = 1; private const SPREAD_MAX:int = 40; // Main variables private var container:DisplayObjectContainer; private var stage:Stage; private var canvasWidth:int; private var canvasHeight:int; private var list:Array; private var px:Number; private var py:Number; private var size:Number; private var spread:int; private var paused:Boolean; private var red:Number; private var green:Number; private var blue:Number; private var lines:Shape; private var bmp:Bitmap; private var blackBitmap:BitmapData; private var m:Matrix; private var p:Point; private var blur:BlurFilter; private var link:lib_present_graphic_imagination_com_neave_link_NeaveLink; /** * Creates a new instance of Neave Imagination on the stage * * @param container The display object (sprite or movieclip) to contain Neave Imagination */ public function lib_present_graphic_imagination_com_neave_imagination_NeaveImagination(container:DisplayObjectContainer, width:int = 770, height:int = 400) { this.container = container; stage = container.stage; canvasWidth = width; canvasHeight = height; initStage(); initLines(); initBitmap(); initLink(); setFullScreenQuality(); } /** * Sets up stage listeners */ private function initStage():void { stage.scaleMode = StageScaleMode.NO_SCALE; stage.addEventListener(Event.RESIZE, stageResizeListener); stage.addEventListener(Event.MOUSE_LEAVE, mouseLeaveListener); stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveListener); stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownListener); stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpListener); stage.addEventListener(FullScreenEvent.FULL_SCREEN, setFullScreenQuality); stage.addEventListener(Event.ENTER_FRAME, update); } /** * Sets up line variables */ private function initLines():void { list = new Array(); px = py = size = 0; spread = SPREAD_MAX; paused = false; // Start using red red = 0; green = 255; blue = 255; // The main lines shape lines = new Shape(); } /** * Creates a link to Neave.com above the bitmap */ private function initLink():void { if (link) link.destroy(); link = new lib_present_graphic_imagination_com_neave_link_NeaveLink(container, canvasWidth, canvasHeight); } /** * Sets up the main bitmap */ private function initBitmap():void { // Stage sizes var sw:int = stage.stageWidth; var sh:int = stage.stageHeight; var sw2:int = Math.ceil(sw / 2); var sh2:int = Math.ceil(sh / 2); // Create the main bitmap to draw into (and half the size to run faster) bmp = new Bitmap(new BitmapData(sw2, sh2, false, 0xFF000000)); bmp.smoothing = true; bmp.scaleX = bmp.scaleY = 2; bmp.x = (canvasWidth - sw) / 2; bmp.y = (canvasHeight - sh) / 2; container.addChild(bmp); // Create bitmap data for fading into black blackBitmap = new BitmapData(sw2, sh2, false, 0xFF000000); // Bitmap is moved over into position then halved in size to run faster m = new Matrix(); m.translate(-bmp.x, -bmp.y); m.scale(0.5, 0.5); // Origin and blur filter p = new Point(0, 0); blur = new BlurFilter(4, 4, 1); } /** * Draws the line animation */ private function drawLines():void { // Clear the graphics before we draw the lines var g:Graphics = lines.graphics; g.clear(); g.moveTo(px, py); // Draw a curve through all points in the list for (var i:int = list.length - 1; i > 0; i--) { // Animate the lines outwards list[i].x += list[i].dx; list[i].y += list[i].dy; // Draw the curve, fading out the last 8 points with alpha g.lineStyle(list[i].size, list[i].color, (list.length > (MAX_LENGTH - 8) && i < 8) ? i / 8 : 1); g.curveTo(list[i].x, list[i].y, (list[i].x + list[i - 1].x) / 2, (list[i].y + list[i - 1].y) / 2); // Remove the last point from the list if we've reached the maximum length if (list.length > MAX_LENGTH) list.splice(0, 1); } } /** * Draws the lines into the bitmap with a fade effect */ private function drawBitmap():void { // Repeatedly fade out and blur the lines then draw in the new ones var b:BitmapData = bmp.bitmapData; b.lock(); b.merge(blackBitmap, b.rect, p, 4, 4, 4, 0); b.applyFilter(b, b.rect, p, blur); b.draw(lines, m, null, BlendMode.ADD); b.unlock(); } /** * Listens for when the mouse leaves the stage */ private function mouseLeaveListener(e:Event):void { paused = true; } /** * Listens for when the mouse re-enters the stage */ private function mouseMoveListener(e:MouseEvent):void { paused = false; } /** * Listens for mouse press */ private function mouseDownListener(e:MouseEvent):void { // Allow a kind of drawing-mode when mouse is pressed spread = SPREAD_MIN; } /** * Listens for mouse press */ private function mouseUpListener(e:MouseEvent):void { // Spread lines out when mouse is released spread = SPREAD_MAX; } /** * Frees up memory by disposing all bitmap data */ private function disposeBitmaps():void { bmp.bitmapData.dispose(); bmp.bitmapData = null; blackBitmap.dispose(); blackBitmap = null; } /** * Removes Neave Imagination and all other objects */ public function destroy():void { stage.removeEventListener(Event.RESIZE, stageResizeListener); stage.removeEventListener(Event.MOUSE_LEAVE, mouseLeaveListener); stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveListener); stage.removeEventListener(MouseEvent.MOUSE_DOWN, mouseDownListener); stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpListener); stage.removeEventListener(FullScreenEvent.FULL_SCREEN, setFullScreenQuality); stage.removeEventListener(Event.ENTER_FRAME, update); container.removeChild(bmp); disposeBitmaps(); link.destroy(); } /** * Listens for stage resize */ private function stageResizeListener(e:Event):void { // Start again with the bitmap if the stage is resized container.removeChild(bmp); disposeBitmaps(); initBitmap(); initLink(); } /** * Use low quality for full-screen mode otherwise Flash Player crashes after a few seconds! */ private function setFullScreenQuality(e:FullScreenEvent = null):void { stage.quality = stage.displayState == StageDisplayState.FULL_SCREEN ? StageQuality.LOW : StageQuality.HIGH; } /** * Updates the animation */ private function update(e:Event):void { if (paused) return; // Line movement is set by how much the mouse has moved since its previous position and a random value var dx:Number = (container.mouseX - px + Math.random() * 4 - 2) / 2; var dy:Number = (container.mouseY - py + Math.random() * 4 - 2) / 2; // Limit the amount of movement if (dx < -spread) dx = -spread; if (dx > spread) dx = spread; if (dy < -spread) dy = -spread; if (dy > spread) dy = spread; // Store the mouse position px = container.mouseX; py = container.mouseY; // Line thickness varies up and down with sine var s:Number = Math.sin(size += 0.2) * 8 + 4; // Put the red, green and blue values together into a single hexadecimal value var c:uint = (Math.sin(red += RED_STEP) * 128 + 127) << 16 | (Math.sin(green += GREEN_STEP) * 128 + 127) << 8 | (Math.sin(blue += BLUE_STEP) * 128 + 127); // Create a new point on the line list.push(new lib_present_graphic_imagination_com_neave_imagination_ImaginationPoint(px, py, dx, dy, s, c)); // Draw! drawLines(); drawBitmap(); } } }