/**
* Copyright noonat ( http://wonderfl.net/user/noonat )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/s06c
*/
// There are three classes in this file:
// - LightDemo (the actual "application")
// - LightPool
// - Light
package {
import flash.display.*;
import flash.events.*;
import flash.geom.*;
import flash.text.*;
import flash.utils.getTimer;
public class LightDemo extends Sprite {
private var _bitmap:Bitmap;
private var _light:Light;
private var _pixels:BitmapData;
private var _pixelsBg:BitmapData;
private var _pool:LightPool;
private var _p:Point, _r:Rectangle;
function LightDemo():void {
// basic setup for rendering
stage.scaleMode = StageScaleMode.NO_SCALE;
_p = new Point(0, 0);
_r = new Rectangle(0, 0, stage.stageWidth, stage.stageHeight);
_pixels = new BitmapData(_r.width, _r.height, true, 0xffffffff);
_pixelsBg = _pixels.clone();
_pixelsBg.perlinNoise(_r.width, _r.height, 32, 32982, false, false, 5);
_pixelsBg.colorTransform(_r, new ColorTransform(1, 1, 1, 1, 100, 100, 100));
_bitmap = addChild(new Bitmap(_pixels)) as Bitmap;
addEventListener(Event.ENTER_FRAME, _onEnterFrame);
stage.addEventListener(MouseEvent.MOUSE_DOWN, _onMouseDown);
stage.addEventListener(MouseEvent.MOUSE_UP, _onMouseUp);
// create the light pool and add some lights
_pool = new LightPool(_r.width, _r.height, 1/2, 0.9);
_pool.add(new Light(_r.width/2, _r.height/2-41, 64, 0.3));
_pool.add(new Light(_r.width/2-32, _r.height/2+32, 64, 0.3));
_pool.add(new Light(_r.width/2+32, _r.height/2+32, 64, 0.3));
}
internal function _onEnterFrame(event:Event):void {
_updateFps();
_updateLight();
_render();
}
internal function _onMouseDown(event:MouseEvent):void {
if (_light) return;
_light = _pool.add(new Light(mouseX, mouseY, 16, 0.3));
}
internal function _onMouseUp(event:MouseEvent):void {
if (!_light) return;
_updateLight();
_light = null;
}
internal function _render():void {
_pixels.lock();
_pixels.copyPixels(_pixelsBg, _r, _p); // draw the unlit background
_pool.render(_pixels); // draw the lights on top of it
_pixels.unlock();
}
private var _fps:int=0, _fpsText:TextField=null, _fpsTime:Number=1000;
private var _frameTime:int=0, _lastFrameTime:int=0;
internal function _updateFps():void {
++_fps;
if (_fpsText === null) {
_fpsText = addChild(new TextField()) as TextField;
_fpsText.defaultTextFormat = new TextFormat('Arial', null, 0xffffff, true);
_fpsText.selectable = false;
_frameTime = _lastFrameTime = getTimer();
}
else {
_lastFrameTime = _frameTime;
_frameTime = getTimer();
_fpsTime += _frameTime - _lastFrameTime;
}
if (_fpsTime > 1000) {
_fpsText.text = _fps + ' fps\ndrag to add lights';
_fps = _fpsTime = 0;
}
}
internal function _updateLight():void {
if (!_light) return;
var dx:Number = mouseX - _light.x;
var dy:Number = mouseY - _light.y;
_light.scale = Math.max(16, Math.sqrt(dx*dx+dy*dy));
}
}
}
import flash.display.*;
import flash.filters.*;
import flash.geom.*;
class LightPool {
public var alpha:Number;
public var scale:Number;
private var _filter:BlurFilter;
private var _lights:Array;
private var _matrix:Matrix, _inverseMatrix:Matrix;
private var _p:Point, _r:Rectangle;
private var _pixels:BitmapData, _alphaPixels:BitmapData;
function LightPool(width:uint, height:uint, scale:Number=1, alpha:Number=1.0,
blurX:Number=8, blurY:Number=8):void {
this.alpha = alpha;
this.scale = scale;
_filter = new BlurFilter(blurX, blurY);
_lights = [];
_matrix = new Matrix();
_matrix.scale(Math.floor(1/scale), Math.floor(1/scale));
_inverseMatrix = new Matrix();
_inverseMatrix.scale(scale, scale);
_p = new Point(0, 0);
_r = new Rectangle(0, 0, Math.floor(width*scale), Math.floor(height*scale));
_pixels = new BitmapData(_r.width, _r.height, true);
_alphaPixels = new BitmapData(_r.width, _r.height);
}
public function add(light:Light):Light {
for (var i:uint=0; i < _lights.length; ++i) {
if (_lights[i] === null) {
_lights[i] = light;
return light;
}
}
_lights.push(light);
return light;
}
public function remove(light:Light):void {
var index:int = _lights.indexOf(light);
if (index !== -1) _lights[index] = null;
}
public function render(dest:BitmapData):void {
_alphaPixels.fillRect(_r, Math.floor(0xff * alpha) | 0xff000000);
for (var i:uint=0; i < _lights.length; ++i) {
if (_lights[i]) _lights[i].render(_alphaPixels, _inverseMatrix);
}
_alphaPixels.applyFilter(_alphaPixels, _r, _p, _filter);
_pixels.fillRect(_r, 0x00000000);
_pixels.copyChannel(_alphaPixels, _r, _p, BitmapDataChannel.BLUE,
BitmapDataChannel.ALPHA);
dest.draw(_pixels, _matrix);
}
}
class Light {
private static var _circleShape:Shape;
private static var _colorTransform:ColorTransform;
public var active:Boolean;
public var alpha:Number;
public var shape:Shape;
private var _angle:Number;
private var _matrix:Matrix;
private var _radians:Number;
private var _scale:Number;
private var _transform:Boolean;
private var _x:Number, _y:Number;
public function Light(x:Number=0, y:Number=0, scale:Number=1, alpha:Number=1.0,
angle:Number=0.0, shape:Shape=null) {
if (_circleShape === null) {
_circleShape = new Shape();
_circleShape.graphics.beginFill(0x000000, 1.0);
_circleShape.graphics.drawCircle(0, 0, 1);
_circleShape.graphics.endFill();
_colorTransform = new ColorTransform();
}
_matrix = new Matrix();
this.active = true;
this.angle = angle;
this.shape = shape || _circleShape;
this.x = x;
this.y = y;
this.alpha = alpha;
this.scale = scale;
}
public function render(dest:BitmapData, matrix:Matrix=null):void {
_matrix.createBox(_scale, _scale, _radians, _x, _y);
if (matrix) {
_matrix.concat(matrix);
}
if (alpha != 1.0) {
_colorTransform.alphaMultiplier = alpha;
dest.draw(shape, _matrix, _colorTransform)
}
else {
dest.draw(shape, _matrix);
}
}
public function get angle():Number { return _angle; }
public function set angle(value:Number):void {
_angle = value;
_radians = _angle * (Math.PI / 180);
_transform = true;
}
public function get radians():Number { return _radians; }
public function set radians(value:Number):void {
_radians = value;
_angle = _radians * (180 / Math.PI);
}
public function get scale():Number { return _scale; }
public function set scale(value:Number):void { _scale = value; _transform = true; }
public function get x():Number { return _x; }
public function set x(value:Number):void { _x = value; _transform = true; }
public function get y():Number { return _y; }
public function set y(value:Number):void { _y = value; _transform = true; }
}