flash on 2011-6-29
...
Testing Flash Application - Interpolation, Timeline Playing/ReversePlaying
/**
* Copyright wei2lee86 ( http://wonderfl.net/user/wei2lee86 )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/rEfb
*/
package
{
import flash.display.ActionScriptVersion;
import flash.display.Sprite;
import flash.display.Graphics;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.geom.Matrix;
import flash.geom.PerspectiveProjection;
import flash.geom.Point;
import flash.geom.Transform;
import flash.display.Shape;
import flash.ui.Keyboard;
import flash.utils.Timer;
import net.hires.debug.Stats;
/**
* ...
* Testing Flash Application - Interpolation, Timeline Playing/ReversePlaying
*/
public class Main extends Sprite
{
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
stage.addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheel);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
}
private function onKeyDown(e:KeyboardEvent):void {
if (e.keyCode == 66) {
backgroundVisible = !backgroundVisible;
}
}
private var _backgroundVisible:Boolean;
public function set backgroundVisible(backgroundVisible:Boolean):void {
this._backgroundVisible = backgroundVisible;
for (var i:int = 0; i < background.length; i++)
{
var s:Sprite = background[i];
s.visible = backgroundVisible;
}
}
public function get backgroundVisible():Boolean {
return this._backgroundVisible;
}
private function onMouseWheel(e:MouseEvent):void {
var m:Matrix = transform.matrix.clone();
var f:Number = range(e.delta > 0 ? Math.pow(0.95, e.delta) : Math.pow(1.05, -e.delta), 0.001, 1000);
m.translate(-e.stageX, -e.stageY);
m.scale(f, f);
m.translate(e.stageX, e.stageY);
transform.matrix = m;
}
private function onMouseDrag(e:MouseEvent):void {
var curDragLocation:Point = new Point(e.stageX, e.stageY);
var m:Matrix = transform.matrix.clone();
m.translate(curDragLocation.x - preDragLocation.x, curDragLocation.y - preDragLocation.y);
transform.matrix = m;
preDragLocation = curDragLocation;
}
private function onMouseMove(e:MouseEvent):void {
if (dragging) {
onMouseDrag(e);
} else {
}
//trace(e);
}
private var dragging:Boolean = false;
private var preDragLocation:Point;
private function onMouseUp(e:MouseEvent):void {
dragging = false;
}
private function onMouseDown(e:MouseEvent):void {
dragging = true;
preDragLocation = new Point(e.stageX, e.stageY);
}
private function onEnterFrame(e:Event):void {
if (!initUpdated) {
initUpdate();
initUpdated = true;
}
update();
}
private function onCircleMouseOver(e:MouseEvent):void
{
}
private function onCircleMouseOut(e:MouseEvent):void
{
}
private var initUpdated:Boolean;
private var shapes:Vector.<Sprite> = new Vector.<Sprite>();
private var background:Vector.<Sprite> = new Vector.<Sprite>();
private var ps:PulseSource;
private var tl:Timeline;
private var circles:Vector.<Sprite> = new Vector.<Sprite>();
private function initUpdate():void {
var i:int, j:int, k:int;
var s:Sprite;
var stats:net.hires.debug.Stats = new net.hires.debug.Stats();
stats.x += 10;
stats.y += 10;
stage.addChild(stats);
//var m:Matrix = transform.matrix.clone();
//m.rotate(Math.PI / 10 * 2);
//transform.matrix = m;
var grid:Grid = new Grid();
addChild(grid);
background.push(grid);
backgroundVisible = false;
for (k = 0; k < 10; k++) {
s = new Circle(Math.random() * stage.stageWidth, Math.random() * stage.stageHeight, 50 + 100 * Math.random(), 20, 0xffffff * Math.random(), true);
s.addEventListener(MouseEvent.MOUSE_OVER, onCircleMouseOver);
//circles.push(s);
//addChild(s);
}
for (i = 0; i < 10; i++) {
s = new Circle(Math.random() * stage.stageWidth, Math.random() * stage.stageHeight, 50 + 50 * Math.random(), 20, 0xffffff * Math.random());
shapes.push(s);
addChild(s);
}
ps = new EnterFramePulseSource(stage);
tl = new Timeline(ps);
for (k = 0; k < shapes.length; k++) {
var duration:Number = duration = (2500 + 7500 * Math.random()) ;
var offset:Number = 5000 * Math.random() / 1;
tl.add(new PropertyInterpolator(shapes[k], "radius", duration, shapes[k]["radius"], 50 + 100 * Math.random()), offset);
tl.add(new PropertyInterpolator(shapes[k], "color", duration, shapes[k]["color"], 0xffffff, Interpolate.COLOR), offset);
tl.add(new PropertyInterpolator(shapes[k], "alpha", duration, 1, 0), offset);
}
tl._onStateChange = function(o:uint, n:uint):void {
if (n == Timeline.ENDED) {
if (tl.repeat) {
tl.reverseRunning = !tl.reverseRunning;
tl._state = Timeline.READY;
}
}
};
tl._easeTimeline = Ease.SQUARE;
tl.start();
}
public function update():void {
}
public static function range(value:Number, min:Number, max:Number):Number {
return value < min ? min : (value > max ? max : value);
}
}
}
import flash.display.DisplayObject;
import flash.display.Graphics;
import flash.events.Event;
import flash.events.TimerEvent;
class PulseSource {
public var timelines:Vector.<Timeline> = new Vector.<Timeline>();
public function PulseSource() {
}
public function add(itp:Timeline):void {
timelines.push(itp);
itp.source = this;
}
public function remove(itp:Timeline):void {
timelines.splice(timelines.indexOf(itp, 0), 1);
itp.source = null;
}
private var preNow:Number = 0;
protected function onPulse():void {
if (preNow == 0)
preNow = new Date().getTime();
var now:Number = new Date().getTime();
for (var i:int = 0; i < timelines.length; i++)
{
var itp:Timeline = timelines[i];
itp.onPulse(now - preNow);
}
preNow = now;
}
}
import flash.utils.Timer;
class TimerPulseSource extends PulseSource {
public var timer:flash.utils.Timer;
public function TimerPulseSource(pulseDuration:uint = 33) {
timer = new Timer(pulseDuration, 0);
timer.addEventListener(TimerEvent.TIMER, onTimer);
timer.start();
}
private function onTimer(e:TimerEvent):void {
onPulse();
}
}
class EnterFramePulseSource extends PulseSource {
public var stage:DisplayObject;
public var acc:uint = 1;
public function EnterFramePulseSource(stage:DisplayObject, acc:uint = 1) {
stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
this.acc = acc;
}
private var enterFrameCount:uint = 0;
private function onEnterFrame(e:Event):void {
if(enterFrameCount == 0)
onPulse();
enterFrameCount = (enterFrameCount + 1) % acc;
}
}
class Ease {
public static function LINEAR(t:Number):Number {
return t;
}
public static function SQUARE(t:Number):Number {
return t * t;
}
public static function SQRT(t:Number):Number {
return Math.sqrt(t);
}
}
class Interpolate {
public static function COLOR(v1:uint, v2:uint, t:Number):uint {
var r1:uint = (v1 >> 16) & 0xff;
var g1:uint = (v1 >> 8) & 0xff;
var b1:uint = (v1 >> 0) & 0xff;
var r2:uint = (v2 >> 16) & 0xff;
var g2:uint = (v2 >> 8) & 0xff;
var b2:uint = (v2 >> 0) & 0xff;
var r3:uint = uint(r1 + (r2 - r1) * t);
var g3:uint = uint(g1 + (g2 - g1) * t);
var b3:uint = uint(b1 + (b2 - b1) * t);
return r3 << 16 | g3 << 8 | b3;
}
public static function NUMBER(v1:Number, v2:Number, t:Number):Number {
return v1 + (v2 - v1) * t;
};
}
class TimelineListener {
public var startTimeline:Number;
public var duration:Number;
public var _easeTimeline:Function;
public var _onTimeline:Function;
public var _callback:Function;
public function TimelineListener(duration:Number = 500, callbackFunction:Function = null) {
this._callback = callbackFunction;
}
public function onTimeline(timeline:Number):void {
if (_onTimeline != null) {
_onTimeline(timeline);
}else{
callback(easeTimeline(timeline));
}
}
public function callback(t:Number):void {
if (_callback != null) {
_callback(t);
}else{
}
}
public function easeTimeline(t:Number):Number {
if (_easeTimeline != null) {
return Main.range(_easeTimeline(t), 0, 1);
}else{
return Ease.LINEAR(t);
}
}
}
class PropertyInterpolator extends TimelineListener{
public var object:Object;
public var property:String;
public var from:Object;
public var to:Object;
public var interpolate:Function;
public function PropertyInterpolator(object:Object = null, property:String = "", duration:Number = 500, from:Object = 0, to:Object = 1, interpolateFunction:Function = null) {
this.object = object;
this.property = property;
this.duration = duration;
this.from = from;
this.to = to;
this.interpolate = interpolateFunction == null ? Interpolate.NUMBER : interpolateFunction;
}
public override function onTimeline(timeline:Number):void {
if (_onTimeline != null) {
_onTimeline(timeline);
}else{
if (interpolate != null) {
object[property] = interpolate(from, to, easeTimeline(timeline));
}
}
}
}
class Timeline {
public static var IDLE:uint = 0;
public static var READY:uint = 1;
public static var RUNNING:uint = 2;
public var reverseRunning:Boolean = false;
public static var ENDED:uint = 4;
public static var STOPPED:uint = 5;
public var tlls:Vector.<TimelineListener> = new Vector.<TimelineListener>();
public var source:PulseSource;
private var _duration:Number;
public var _onStateChange:Function;
public var _state:uint;
private var _timelineLocation:Number = 0;
private var _repeat:Boolean = true;
public var _easeTimeline:Function;
public function Timeline(source:PulseSource, repeat:Boolean = true) {
this.source = source;
this.source.add(this);
this._duration = -1;
this._repeat = repeat;
}
public function start(): void {
reverseRunning = false;
if (state == IDLE) {
state = READY;
} else if (state == STOPPED) {
state = RUNNING;
} else if (state == ENDED) {
state = READY;
}
}
public function reverse(): void {
reverseRunning = true;
if (state == IDLE) {
state = READY;
} else if (state == STOPPED) {
state = RUNNING;
} else if (state == ENDED) {
state = READY;
}
}
public function stop(): void {
if (state == RUNNING) {
state = STOPPED
}
}
public function set timelineLocation(timelineLocation:Number):void {
this._timelineLocation = timelineLocation;
}
public function get timelineLocation():Number {
return _timelineLocation;
}
public function add(tll:TimelineListener, startTimeline:Number = 0):TimelineListener {
tll.startTimeline = startTimeline;
tlls.push(tll);
return tll;
}
public function remove(tll:TimelineListener):void {
tlls.slice(tlls.indexOf(tll, 0), 1);
}
public function onPulse(elapsedTime:Number):void {
if (state == IDLE) {
} else if (state == READY) {
if(!reverseRunning)
timelineLocation = 0;
else
timelineLocation = duration;
state = RUNNING;
} else if (state == RUNNING) {
if(!reverseRunning) {
_timelineLocation += elapsedTime;
if (_timelineLocation > duration) {
state = ENDED;
return;
}
} else {
_timelineLocation -= elapsedTime;
if (_timelineLocation < 0) {
state = ENDED;
return;
}
}
var i:int = 0;
var timelineFraction:Number = 0;
var timeline:Number = 0;
for (i = 0; i < tlls.length; i++) {
try
{
var tll:TimelineListener = tlls[i];
if (tll.startTimeline <= timelineLocation && timelineLocation < tll.duration + tll.startTimeline) {
timelineFraction = (timelineLocation - tll.startTimeline) / tll.duration;
timeline = timelineFraction - int(timelineFraction);
tll.onTimeline(timeline);
}
}catch (err:Error)
{
}
}
} else if (state == ENDED) {
} else if (state == STOPPED) {
}
}
public function get repeat():Boolean {
return _repeat;
}
public function set repeat(repeat:Boolean):void {
this._repeat = repeat;
}
public function get state():uint {
return _state;
}
public function set state(state:uint):void {
var o:uint = this._state;
var n:uint = state;
this._state = state;
if(o != n)
onStateChange(o, n);
}
public function set duration(duration:Number):void {
this._duration = duration;
}
public function get duration():Number {
if (this._duration >= 0)
return this._duration;
else {
var j:Number = 0, k:Number = 0;
var i:int = 0;
for (i = 0; i < tlls.length; i++) {
var tll:TimelineListener = tlls[i];
k = tll.startTimeline + tll.duration;
if (k > j)
j = k;
}
return j;
}
}
public function onStateChange(o:uint, n:uint):void {
if (_onStateChange != null) {
_onStateChange(o, n);
} else {
if (n == ENDED) {
if(repeat) {
this._state = READY;
}
}
}
}
public function easeTimeline(t:Number):Number {
if (_easeTimeline != null) {
return Main.range(_easeTimeline(t), 0, 1);
}else{
return Ease.LINEAR(t);
}
}
}
import flash.display.Sprite;
class Circle extends Sprite {
private var _fill:Boolean;
private var _color:int;
private var _radius:Number;
public var ox:Number;
public var oy:Number;
public var thickness:Number;
public static var count:uint;
public function Circle(ox:Number = 50, oy:Number = 50, radius:Number = 50, thickness:Number = 3, color:int = 0x000000, fill:Boolean = false) {
this.ox = ox;
this.oy = oy;
this.radius = radius;
this.color = color;
this.thickness = thickness;
this.fill = fill;
this.name = "" + count++;
update();
}
public function set fill(fill:Boolean):void {
this._fill = fill;
update();
}
public function get fill():Boolean {
return this._fill;
}
public function set color(color:int):void {
this._color = color;
update();
}
public function get color():int {
return this._color;
}
public function set radius(radius:Number):void {
this._radius = radius;
update();
}
public function get radius():Number {
return this._radius;
}
public function update():void {
graphics.clear();
if(!fill) {
graphics.lineStyle(thickness, color);
graphics.drawCircle(ox, oy, radius);
} else {
graphics.beginFill(color);
graphics.drawCircle(ox, oy, radius);
graphics.endFill();
}
}
public override function toString():String {
return "[ object Circle@name=" + name + ", radius=" + radius + ", color=" + color + "]";
}
}
class Grid extends Sprite {
public function Grid() {
update();
}
public function update():void {
var i:int;
var j:int;
graphics.clear();
for (i = 0, j = 0 ; i <= 800 ; i += 10, j++) {
if ((j % 5) == 0)
graphics.lineStyle(1, 0x2222ff, 0.5);
else
graphics.lineStyle(1, 0x9999ff, 0.25);
graphics.moveTo(i, 0);
graphics.lineTo(i, 600);
}
for (i = 0, j = 0 ; i <= 600 ; i += 10, j++) {
if ((j % 5) == 0)
graphics.lineStyle(1, 0x2222ff, 0.5);
else
graphics.lineStyle(1, 0x9999ff, 0.1);
graphics.moveTo(0, i);
graphics.lineTo(800, i);
}
}
}
class Star extends Sprite {
private var _outerSpan:Number;
private var _color:int;
private static var POINTS:int = 5;
public function Star(x:Number = 0, y:Number = 0, outerSpan:Number = 10, color:int = 0xff0000) {
this.x = x;
this.y = y;
this.outerSpan = outerSpan;
this.color = color;
}
public function set outerSpan(outerSpan:Number):void {
this._outerSpan = outerSpan;
update();
}
public function get outerSpan():Number {
return this._outerSpan;
}
public function set color(color:int):void {
this._color = color;
update();
}
public function get color():int {
return this._color;
}
public function get innerSpan():Number {
return outerSpan * (0.1 + 0.1 * outerSpan / 20);
}
public function update():void {
graphics.clear();
graphics.beginFill(color);
var sina:Number;
var cosa:Number;
for (var i:int = 0; i < POINTS; i++)
{
sina = Math.sin(i * 2 * Math.PI / POINTS);
cosa = Math.cos(i * 2 * Math.PI / POINTS);
if (i == 0) {
graphics.moveTo(outerSpan * cosa, outerSpan * sina);
} else {
graphics.lineTo(outerSpan * cosa, outerSpan * sina);
}
sina = Math.sin((i * 2 + 1) * Math.PI / POINTS);
cosa = Math.cos((i * 2 + 1) * Math.PI / POINTS);
graphics.lineTo(innerSpan * cosa, innerSpan * sina);
}
graphics.endFill();
}
}