/** $Id: FuncMovie3.as 85 2008-04-28 22:13:05Z gijsbert $ */ package { import flash.display.MovieClip; import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.geom.Matrix; import flash.geom.Point; import flash.geom.Transform; import flash.events.*; import flash.ui.Keyboard; import com.hexagonstar.util.debug.Debug; [SWF(width="600", height="400", frameRate="20", backgroundColor="#FFFFFF")] public class FuncMovie3 extends MovieClip { private var ls:Number; private var t :Number; private var ts:Number; private var ms:Number; private var maxpts:Number; private var nbEvals:Number; private var maxeval:Number; private var pts:Array; private var m_w:Number; private var m_h:Number; private var a:Number; private var b:Number; private var func:Function; public function trace(arg0:* = undefined, arg1:* = null, arg2:int = -1):void { Debug.trace(arg0, arg1, arg2); } // FuncMovie: constructor. public function FuncMovie3() { Debug.setTrace(true); trace("FuncMovie.FuncMovie"); // Setup transform. // transform = new Transform(this); // FIXME: should get those initial values from somewhere? you can pass init // object into attachMovie, how to not override those? ts = 1; ls = 4; ms = 1; maxpts = 256; maxeval = 1024; trace("totalFrames=" + totalFrames); setupCircle(); setupMatrix(stage.stageWidth, stage.stageHeight); play(); // Do some stuff on key release. stage.addEventListener(KeyboardEvent.KEY_DOWN, onStageKeyDown); stage.addEventListener(KeyboardEvent.KEY_UP, onStageKeyUp); // Adjust to size changes. // Setup stage and callbacks stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; stage.addEventListener(Event.RESIZE, onResize); } // reset: reset vars to restart animation. private function reset():void { t = 0; pts = new Array; nbEvals = 0; } // onResize: Stage listener. private function onResize(event:Event):void { trace("FuncMovie.onResize"); setupMatrix(stage.stageWidth, stage.stageHeight); } // setupMatrix: sets up matrix and other viewport related values. private function setupMatrix(w:Number, h:Number):void { trace( "setupMatrix " + w + "," + h ); m_w = w; m_h = h; var m:Matrix = new Matrix(); m.identity(); m.translate(w / 2, h / 2); transform.matrix = m; ms = 0.55 * Math.min(w, h) / 2; } // redraw function. private function redraw():void { graphics.clear(); // To get some size. graphics.lineStyle(1, 0x000000, 0.01); var w:Number = m_w / 2; var h:Number = m_h / 2; graphics.drawRect(-w, -h, m_w, m_h); graphics.lineStyle(ls, 0xdddd00); if (pts.length > 0) { graphics.moveTo(pts[0].x, pts[0].y); for each (var p:Point in pts) { graphics.lineTo(p.x, p.y); } } } // play: not sure when this is called or why. override public function play():void { trace("FuncMovie.play"); reset(); addEventListener(Event.ENTER_FRAME, doStep); super.play(); } // stop: remove onEnterFrame override public function stop():void { trace( "FuncMovie.stop" ); removeEventListener(Event.ENTER_FRAME, doStep); super.stop(); } override public function gotoAndStop(frame:Object, scene:String = null):void { stop(); var frameNb:Number = parseInt(String(frame)); if (!isNaN(frameNb)) { reset(); var i:Number; for (i = 1; i < frame; ++i) { t += ts; pts.push(func(t, ms)); } redraw(); } } override public function gotoAndPlay(frame:Object, scene:String = null):void { gotoAndStop(frame, scene); play(); } // doStep: increments 't' and evaluates the function, adds the new point to the pts // array and if array to big removes one point as well. private function doStep(event:Event):void { t += ts; pts.push(func(t, ms )); if (pts.length > maxpts) { pts.shift(); } redraw(); ++nbEvals; // _currentframe = nbEvals; if (nbEvals > maxeval) { stop(); } } private function setupCircle():void { trace( "setupCircle" ); maxpts = 256; func = evalCircle; reset(); } private function setupEpicycloide(a:Number, b:Number):void { maxpts = 256 + 128; func = evalEpicycloide; this.a = a; this.b = b; reset(); } // eval: evaluate parametric function /* private function eval(t:Number, s:Number):Point { return new Point( 0, 0 ); } */ // evalCircle: evaluate parametric circle, getting smaller of t. private function evalCircle(t:Number, s:Number):Point { t *= Math.PI / 45.0; s *= Math.max(0.1, 1 - t / 50); return new Point( Math.cos( t ) * s, Math.sin( t ) * s ); } // evalEpicycloide: evaluate epicycloide. private function evalEpicycloide(t:Number, s:Number):Point { t *= Math.PI / 30.0; s *= 0.4; return new Point( s * ((a + b) * Math.cos(t) - b * Math.cos((a+b)/b*t)), s * ((a + b) * Math.sin(t) - b * Math.sin((a+b)/b*t))); } private function onStageKeyDown(event:KeyboardEvent):void { switch (event.keyCode) { case Keyboard.UP: { stage.frameRate += 1; } break; case Keyboard.DOWN: { stage.frameRate -= 1; } break; } trace("stage.frameRate " + stage.frameRate); } private function onStageKeyUp(event:KeyboardEvent):void { Debug.trace("onStageKeyUp " + event); switch (event.keyCode) { case 'C'.charCodeAt(0): { stop(); setupCircle(); play(); } break; case 'E'.charCodeAt(0): { stop(); setupEpicycloide(1, event.shiftKey ? 1.2 : 1.211); play(); } break; } } } }