Recursive Digital Clock
Watch it in Fullscreen!! (フルスクリーンで見てね!)
/**
* 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; }
}
//}