In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

Recursive Digital Clock

Watch it in Fullscreen!! (フルスクリーンで見てね!)
Get Adobe Flash player
by o8que 03 Nov 2010
/**
 * Copyright o8que ( http://wonderfl.net/user/o8que )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/7mCu
 */

/* ------------------------------------------------------------------------------------
 * [inspired by]
 * 
 * GEB
 * http://en.wikipedia.org/wiki/G%C3%B6del,_Escher,_Bach
 * http://ja.wikipedia.org/wiki/ゲーデル、エッシャー、バッハ
 * 
 * Eternal Clock
 * http://www.flickr.com/photos/robbie73/3387189144/
 * 
 * ------------------------------------------------------------------------------------
 */
package {
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.geom.Point;
    
    [SWF(width="465",height="465",frameRate="30")]
    public class Main extends Sprite {
        private var _screen:BitmapData;
        private var _seconds:Digits;
        private var _minutes:Digits;
        private var _hours:Digits;
        
        public function Main() {
            graphics.beginFill(0x000000);
            graphics.drawRect(0, 0, 648, 465);
            graphics.endFill();
            
            x = -91;
            addChild(new Bitmap(_screen = new BitmapData(648, 465, true, 0x00FFFFFF)));
            _seconds = new Digits(9, 12, new Segment(5, 2));
            _minutes = new Digits(54, 72, new Segment(30, 12, _seconds));
            _hours = new Digits(324, 432, new Segment(180, 72, _minutes));
            
            addEventListener(Event.ENTER_FRAME, update);
        }
        
        private static const UPPER_POS:Point = new Point(0, int((465 - 432) / 2));
        private static const LOWER_POS:Point = new Point(324, int((465 - 432) / 2));
        
        private function update(event:Event):void {
            var date:Date = new Date();
            _seconds.redraw(date.seconds);
            _minutes.redraw(date.minutes);
            _hours.redraw(date.hours);
            
            _screen.lock();
            _screen.fillRect(_screen.rect, 0x00FFFFFF);
            _screen.copyPixels(_hours.upperImage, _hours.upperImage.rect, UPPER_POS);
            _screen.copyPixels(_hours.lowerImage, _hours.lowerImage.rect, LOWER_POS);
            _screen.unlock();
        }
    }
}
/* ------------------------------------------------------------------------------------
 * Digits
 * ------------------------------------------------------------------------------------
 */
//package {
    import flash.display.BitmapData;
    import flash.geom.ColorTransform;
    import flash.geom.Matrix;
    import flash.geom.Point;
    
    //public
    class Digits {
        private var _upperImage:BitmapData;
        private var _lowerImage:BitmapData;
        private var _segment:Segment;
        
        private var _matrices:Vector.<Matrix>;
        
        public function Digits(width:int, height:int, segment:Segment) {
            _upperImage = new BitmapData(width, height, true, 0x00FFFFFF);
            _lowerImage = _upperImage.clone();
            _segment = segment;
            initializeMatrices(width, height);
        }
        
        private function initializeMatrices(width:int, height:int):void {
            _matrices = new Vector.<Matrix>();
            
            var offsetX:Number = _segment.image.width / 2;
            var offsetY:Number = _segment.image.height / 2;
            var middleX:Number = width / 2;
            var leftX:Number = middleX - offsetX;
            var rightX:Number = middleX + offsetX;
            var middleY:Number = height / 2;
            var topY:Number = offsetY;
            var upperMiddleY:Number = middleY - offsetX;
            var lowerMiddleY:Number = middleY + offsetX;
            var bottomY:Number = height - offsetY;
            
            var angles:Array = [Math.PI / 2, Math.PI / 2, -(Math.PI / 2), -(Math.PI / 2), 0, 0, 0];
            var positions:Array = [
                new Point(rightX, upperMiddleY), new Point(rightX, lowerMiddleY),
                new Point(leftX, upperMiddleY), new Point(leftX, lowerMiddleY),
                new Point(middleX, topY), new Point(middleX, middleY), new Point(middleX, bottomY)
            ];
            
            for (var i:int = 0; i < 7; i++) {
                var matrix:Matrix = new Matrix();
                matrix.translate( -offsetX, -offsetY);
                matrix.rotate(angles[i]);
                matrix.translate(positions[i].x, positions[i].y);
                _matrices.push(matrix);
            }
        }
        
        public function redraw(value:int):void {
            var upper:int = (value / 10) % 10;
            var lower:int = value % 10;
            
            _segment.redraw();
            drawDigit(upper, _upperImage);
            drawDigit(lower, _lowerImage);
        }
        
        private function drawDigit(value:int, image:BitmapData):void {
            image.fillRect(image.rect, 0x00FFFFFF);
            for (var i:int = 0; i < 7; i++) {
                image.draw(_segment.image, _matrices[i], SEGMENT_SWITCHES[value][i]);
            }
        }
        
        public function get upperImage():BitmapData { return _upperImage; }
        public function get lowerImage():BitmapData { return _lowerImage; }
        
        private static const ON:ColorTransform = new ColorTransform(1);
        private static const OFF:ColorTransform = new ColorTransform(0.3);
        private static const SEGMENT_SWITCHES:Array = [
            [ON, ON, ON, ON, ON, OFF, ON], [ON, ON, OFF, OFF, OFF, OFF, OFF],
            [ON, OFF, OFF, ON, ON, ON, ON], [ON, ON, OFF, OFF, ON, ON, ON],
            [ON, ON, ON, OFF, OFF, ON, OFF], [OFF, ON, ON, OFF, ON, ON, ON],
            [OFF, ON, ON, ON, ON, ON, ON], [ON, ON, OFF, OFF, ON, OFF, OFF],
            [ON, ON, ON, ON, ON, ON, ON], [ON, ON, ON, OFF, ON, ON, ON]
        ];
    }
//}
/* ------------------------------------------------------------------------------------
 * Segment
 * ------------------------------------------------------------------------------------
 */
//package {
    import flash.display.BitmapData;
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.geom.Matrix;
    
    //public
    class Segment {
        private var _image:BitmapData;
        private var _digits:Digits;
        
        private var _leftVertices:Vector.<Number>;
        private var _leftIndices:Vector.<int>;
        private var _leftUvtData:Vector.<Number>;
        
        private var _rightVertices:Vector.<Number>;
        private var _rightIndices:Vector.<int>;
        private var _rightUvtData:Vector.<Number>;
        
        private var _matrices:Vector.<Matrix>;
        
        public function Segment(width:int, height:int, digits:Digits = null) {
            _image = new BitmapData(width, height, true, 0x00FFFFFF);
            _digits = digits;
            
            if (_digits != null) {
                initializeLeftCornerParams(width, height);
                initializeRightCornerParams(width, height);
                initializeMatrices(width, _digits.upperImage.width);
            }else {
                drawMinSegmentImage(width, height);
            }
        }
        
        private function initializeLeftCornerParams(width:int, height:int):void {
            var rightX:int = width * 2 / 10;
            var middleX:int = width * 1 / 10;
            var middleY:int = height / 2;
            
            _leftVertices = new Vector.<Number>();
            _leftVertices.push(0, middleY); _leftVertices.push(rightX, 0);
            _leftVertices.push(middleX, middleY); _leftVertices.push(rightX, middleY);
            _leftVertices.push(0, middleY); _leftVertices.push(rightX, height);
            
            _leftIndices = new Vector.<int>();
            _leftIndices.push(0, 1, 2); _leftIndices.push(1, 2, 3);
            _leftIndices.push(2, 3, 5); _leftIndices.push(2, 4, 5);
            
            _leftUvtData = new Vector.<Number>();
            _leftUvtData.push(0, 0); _leftUvtData.push(1, 0);
            _leftUvtData.push(0, 0.5); _leftUvtData.push(1, 0.5);
            _leftUvtData.push(0, 1); _leftUvtData.push(1, 1);
        }
        
        private function initializeRightCornerParams(width:int, height:int):void {
            var rightX:int = width * 2 / 10;
            var middleX:int = width * 1 / 10;
            var middleY:int = height / 2;
            
            _rightVertices = new Vector.<Number>();
            _rightVertices.push(0, 0); _rightVertices.push(rightX, middleY);
            _rightVertices.push(0, middleY); _rightVertices.push(middleX, middleY);
            _rightVertices.push(0, height); _rightVertices.push(rightX, middleY);
            
            _rightIndices = new Vector.<int>();
            _rightIndices.push(0, 1, 3); _rightIndices.push(0, 2, 3);
            _rightIndices.push(2, 3, 4); _rightIndices.push(3, 4, 5);
            
            _rightUvtData = new Vector.<Number>();
            _rightUvtData.push(0, 0); _rightUvtData.push(1, 0);
            _rightUvtData.push(0, 0.5); _rightUvtData.push(1, 0.5);
            _rightUvtData.push(0, 1); _rightUvtData.push(1, 1);
        }
        
        private function initializeMatrices(width:int, digitWidth:int):void {
            var offsetX:int = ((width * 3 / 10) - digitWidth) / 2;
            
            _matrices = new Vector.<Matrix>();
            _matrices.push(new Matrix(1, 0, 0, 1, (width * 0 / 10), 0));
            _matrices.push(new Matrix(1, 0, 0, 1, (width * 2 / 10) + offsetX, 0));
            _matrices.push(new Matrix(1, 0, 0, 1, (width * 5 / 10) + offsetX, 0));
            _matrices.push(new Matrix(1, 0, 0, 1, (width * 8 / 10), 0));
        }
        
        private function drawMinSegmentImage(width:int, height:int):void {
            /*
            var leftX:int = width * 1 / 5;
            var rightX:int = width * 4 / 5;
            var middleY:int = height / 2;
            */
            var image:Sprite = new Sprite();
            image.graphics.beginFill(0xFF0000);
            image.graphics.drawRect(0, 0, width, height);
            /*
            image.graphics.moveTo(0, middleY);
            image.graphics.lineTo(leftX, 0);
            image.graphics.lineTo(rightX, 0);
            image.graphics.lineTo(width, middleY);
            image.graphics.lineTo(rightX, height);
            image.graphics.lineTo(leftX, height);
            image.graphics.lineTo(0, middleY);
            */
            image.graphics.endFill();
            _image.draw(image);
        }
        
        public function redraw():void {
            if (_digits == null) { return; }
            
            var leftCorner:Shape = new Shape();
            leftCorner.graphics.beginBitmapFill(_digits.lowerImage, null, false, true);
            leftCorner.graphics.drawTriangles(_leftVertices, _leftIndices, _leftUvtData);
            leftCorner.graphics.endFill();
            
            var rightCorner:Shape = new Shape();
            rightCorner.graphics.beginBitmapFill(_digits.upperImage, null, false, true);
            rightCorner.graphics.drawTriangles(_rightVertices, _rightIndices, _rightUvtData);
            rightCorner.graphics.endFill();
            
            _image.fillRect(_image.rect, 0x00FFFFFF);
            _image.draw(leftCorner, _matrices[0]);
            _image.draw(_digits.upperImage, _matrices[1]);
            _image.draw(_digits.lowerImage, _matrices[2]);
            _image.draw(rightCorner, _matrices[3]);
        }
        
        public function get image():BitmapData { return _image; }
    }
//}