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

ShadowCast

面白そうだったので
ただ高速化は意識してないので重い
Get Adobe Flash player
by okoi 05 Oct 2010
    Embed
/**
 * Copyright okoi ( http://wonderfl.net/user/okoi )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/1dNB
 */

/**
 * ShadowCast
 */
package 
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.filters.BlurFilter;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    
    [SWF(width = "465", height = "465")]
    
    
    /**
     * ...
     * @author 
     */
    public class Main extends Sprite 
    {
        private var _canvas:BitmapData;
        private var _lightCanvas:BitmapData;
        private var _lightX:Number;
        private var _lightY:Number;
        
        private static const LIGHTLENGTH:int = 150;
        private static const BLOCKCOLOR:uint = 0xFF000000;
        
        private var _step:int;
        private var _walls:/*Wall*/Array;
        
        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
            graphics.beginFill(0);
            graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
            graphics.endFill();
            
            
            _canvas = new BitmapData(stage.stageWidth, stage.stageHeight, true, 0 );
            addChild( new Bitmap(_canvas) );
            
            _lightCanvas = new BitmapData(stage.stageWidth, stage.stageHeight, true, 0);
            addChild( new Bitmap(_lightCanvas) );
            
            _lightX = stage.stageWidth / 2;
            _lightY = stage.stageHeight / 2;
            
            _step = 0;
            _walls = new Array();
            
            addEventListener(Event.ENTER_FRAME, Update);
        }
        
        private function Update(e:Event):void
        {
            var i:int;
            
            _lightX = stage.mouseX;
            _lightY = stage.mouseY;
            
            
            //    DrawWall
            if ( _step % 10 == 0 )    GenerationWall();
            for ( i = _walls.length - 1; i >= 0; i-- )
            {
                _walls[i].x -= 5;
                if ( _walls[i].x < -_walls[i].width )    _walls.splice( i, 1 );
            }
            
            _canvas.fillRect(_canvas.rect, 0x0 );
            for ( i = 0; i < _walls.length; i++ )
            {
                _canvas.fillRect( new Rectangle( _walls[i].x, _walls[i].y, _walls[i].width, _walls[i].height ), 0xFF000000 );
            }
            
            
            //    ShadowCut
            _lightCanvas.fillRect(_lightCanvas.rect, 0x0);
            RecursiveCutOutNortheastNorth( 0, 1, 0 );
            RecursiveCutOutNortheastEast(0, 1, 0 );
            RecursiveCutOutSoutheastEast(0, 1, 0 );
            RecursiveCutOutSoutheastSouth(0, 1, 0);
            RecursiveCutOutSouthwestSouth(0, 1, 0);
            RecursiveCutOutSouthwestWest(0, 1, 0);
            RecursiveCutOutNorthwestWest(0, 1, 0);
            RecursiveCutOutNorthwestNorth(0, 1, 0 );
            _step++;
        }
        
        private function GenerationWall() : void
        {
            var wall:Wall = new Wall();
            wall.width = Math.random() * 20 + 10;
            wall.height = Math.random() * 20 + 10;
            wall.x = stage.stageWidth + wall.width;
            wall.y = Math.random() * stage.stageHeight;
            
            _walls[_walls.length] = wall;
        }
        
        
        private function calcSlope( x1:Number, y1:Number, x2:Number, y2:Number ) : Number
        {
            return    (x2 - x1) / (y2 - y1);
        }
        private function calcInverseSlope( x1:Number, y1:Number, x2:Number, y2:Number ) : Number
        {
            return    1 / ((x2 - x1) / (y2 - y1));
        }

        
        private function RecursiveCutOutNortheastNorth( depth:int, sSlope:Number, eSlope:Number ) : void
        {
            var sX:int = _lightX + Math.ceil(sSlope * depth);
            var eX:int = _lightX + Math.ceil(eSlope * depth);
            var currentY:int = _lightY - depth;
            
            if (currentY < 0) return;
            
            var isLastCellBlocked:Boolean = _canvas.getPixel32(sX, currentY) == BLOCKCOLOR;
            
            for (var currentX:int = Math.min(sX, _canvas.width); currentX >= eX; --currentX) 
            {
                
                if ( (currentX - _lightX) * (currentX - _lightX) + (currentY - _lightY) * (currentY - _lightY) > LIGHTLENGTH * LIGHTLENGTH )    continue;
                
                if (_canvas.getPixel32(currentX, currentY) == BLOCKCOLOR) {
                    
                    if (!isLastCellBlocked) {
                        var newESlope:Number = -calcSlope(_lightX, _lightY, (currentX + 0.5), (currentY + 0.5));
                        RecursiveCutOutNortheastNorth(depth + 1, sSlope, newESlope);
                    }
                    isLastCellBlocked = true;
                } else {
                    if (isLastCellBlocked) {
                        sSlope = -calcSlope(_lightX, _lightY, (currentX - 0.5), (currentY - 0.5));
                    }
                    _lightCanvas.setPixel32(currentX, currentY, 0xFFFFFFFF);
                    isLastCellBlocked = false;
                }
            }
            
            if (!isLastCellBlocked) {
                depth++;
                RecursiveCutOutNortheastNorth(depth, sSlope, eSlope);
            }
        }
        
        private function RecursiveCutOutNortheastEast( depth:int, sSlope:Number, eSlope:Number ) : void
        {
            var sY:int = _lightY - Math.ceil(sSlope * depth);
            var eY:int = _lightY - Math.ceil(eSlope * depth);
            var currentX:int = _lightX + depth;
            
            if (currentX > 465) return;
            
            var isLastCellBlocked:Boolean = _canvas.getPixel32(currentX, sY) == BLOCKCOLOR;
            
            for (var currentY:int = Math.max(sY, 0); currentY <= eY; ++currentY) {
                
                if ( (currentX - _lightX) * (currentX - _lightX) + (currentY - _lightY) * (currentY - _lightY) > LIGHTLENGTH * LIGHTLENGTH )    continue;
                
                if (_canvas.getPixel32(currentX, currentY) == BLOCKCOLOR) {
                    if (!isLastCellBlocked) {
                        var newESlope:Number = -calcInverseSlope((currentX - 0.5), (currentY - 0.5), _lightX, _lightY);
                        RecursiveCutOutNortheastEast(depth + 1, sSlope, newESlope);
                    }
                    isLastCellBlocked = true;
                } else {
                    if (isLastCellBlocked) {
                        sSlope = -calcInverseSlope((currentX + 0.5), (currentY + 0.5), _lightX, _lightY);
                    }
                    _lightCanvas.setPixel32(currentX, currentY, 0xFFFFFFFF);
                    isLastCellBlocked = false;
                }
            }
            if (!isLastCellBlocked) {
                depth++;
                RecursiveCutOutNortheastEast(depth, sSlope, eSlope);
            }
        }
        
        private function RecursiveCutOutSoutheastEast( depth:int, sSlope:Number, eSlope:Number ) : void
        {
            var sY:int = _lightY + Math.ceil(sSlope * depth);
            var eY:int = _lightY + Math.ceil(eSlope * depth);
            var currentX:int = _lightX + depth;
            
            if (currentX > _canvas.width) return;
            
            var isLastCellBlocked:Boolean = _canvas.getPixel32(currentX, sY) == BLOCKCOLOR;
            
            for (var currentY:int = Math.min(sY, _canvas.height); currentY >= eY; --currentY) {
                
                if ( (currentX - _lightX) * (currentX - _lightX) + (currentY - _lightY) * (currentY - _lightY) > LIGHTLENGTH * LIGHTLENGTH )    continue;
                
                
                if (_canvas.getPixel32(currentX, currentY) == BLOCKCOLOR) {
                    if (!isLastCellBlocked) {
                        var newESlope:Number = calcInverseSlope((currentX - 0.5), (currentY + 0.5), _lightX, _lightY);
                        RecursiveCutOutSoutheastEast(depth + 1, sSlope, newESlope);
                    }
                    isLastCellBlocked = true;
                } else {
                    if (isLastCellBlocked) {
                        sSlope = calcInverseSlope((currentX + 0.5), (currentY - 0.5), _lightX, _lightY);
                    }
                    _lightCanvas.setPixel32(currentX, currentY, 0xFFFFFFFF);
                    isLastCellBlocked = false;
                }
            }
            if (!isLastCellBlocked) {
                depth++;
                RecursiveCutOutSoutheastEast(depth, sSlope, eSlope);
            }            
            
        }
        
        private function RecursiveCutOutSoutheastSouth( depth:int, sSlope:Number, eSlope:Number ) : void
        {
            var sX:int = _lightX + Math.ceil(sSlope * depth);
            var eX:int = _lightX + Math.ceil(eSlope * depth);
            var currentY:int = _lightY + depth;
            
            if (currentY > _canvas.height) return;
            
            var isLastCellBlocked:Boolean = _canvas.getPixel32(sX, currentY) == BLOCKCOLOR;
            for (var currentX:int = Math.min(sX, _canvas.width); currentX >= eX; --currentX) {
                if ( (currentX - _lightX) * (currentX - _lightX) + (currentY - _lightY) * (currentY - _lightY) > LIGHTLENGTH * LIGHTLENGTH )    continue;
                if (_canvas.getPixel32(currentX, currentY) == BLOCKCOLOR) {
                    if (!isLastCellBlocked) {
                        var newESlope:Number = calcSlope(_lightX, _lightY, (currentX + 0.5), (currentY - 0.5));
                        RecursiveCutOutSoutheastSouth(depth + 1, sSlope, newESlope);
                    }
                    isLastCellBlocked = true;
                } else {
                    if (isLastCellBlocked) {
                        sSlope = calcSlope(_lightX, _lightY, (currentX - 0.5), (currentY + 0.5));
                    }
                    _lightCanvas.setPixel32(currentX, currentY, 0xFFFFFFFF);
                    isLastCellBlocked = false;
                }
            }
            if (!isLastCellBlocked) {
                depth++;
                RecursiveCutOutSoutheastSouth(depth, sSlope, eSlope);
            }
        }
        
        private function RecursiveCutOutSouthwestSouth( depth:int, sSlope:Number, eSlope:Number ) : void
        {
            var sX:int = _lightX - Math.ceil(sSlope * depth);
            var eX:int = _lightX - Math.ceil(eSlope * depth);
            var currentY:int = _lightY + depth;
            
            if (currentY > _canvas.height) return;
            
            var isLastCellBlocked:Boolean = _canvas.getPixel32(sX, currentY) == BLOCKCOLOR;
            for (var currentX:int = Math.max(sX, 0); currentX <= eX; ++currentX) {
                if ( (currentX - _lightX) * (currentX - _lightX) + (currentY - _lightY) * (currentY - _lightY) > LIGHTLENGTH * LIGHTLENGTH )    continue;                
                if (_canvas.getPixel32(currentX, currentY) == BLOCKCOLOR) {
                    if (!isLastCellBlocked) {
                        var newESlope:Number = -calcSlope(_lightX, _lightY, (currentX - 0.5), (currentY - 0.5));
                        RecursiveCutOutSouthwestSouth(depth + 1, sSlope, newESlope);
                    }
                    isLastCellBlocked = true;
                } else {
                    if (isLastCellBlocked) {
                        sSlope = -calcSlope(_lightX, _lightY, (currentX + 0.5), (currentY + 0.5));
                    }
                    _lightCanvas.setPixel32(currentX, currentY, 0xFFFFFFFF);
                    isLastCellBlocked = false;
                }
            }
            if (!isLastCellBlocked) {
                depth++;
                RecursiveCutOutSouthwestSouth(depth, sSlope, eSlope);
            }
        }
        
        private function RecursiveCutOutSouthwestWest( depth:int, sSlope:Number, eSlope:Number ) : void
        {
            var sY:int = _lightY + Math.ceil(sSlope * depth);
            var eY:int = _lightY + Math.ceil(eSlope * depth);
            var currentX:int = _lightX - depth;
            
            if (currentX < 0) return;
            
            var isLastCellBlocked:Boolean = _canvas.getPixel32(currentX, sY) == BLOCKCOLOR;
            
            for (var currentY:int = Math.min(sY, _canvas.height); currentY >= eY; --currentY) {
                if ( (currentX - _lightX) * (currentX - _lightX) + (currentY - _lightY) * (currentY - _lightY) > LIGHTLENGTH * LIGHTLENGTH )    continue;                
                
                if (_canvas.getPixel32(currentX, currentY) == BLOCKCOLOR) {
                    if (!isLastCellBlocked) {
                        var newESlope:Number = -calcInverseSlope((currentX + 0.5), (currentY + 0.5), _lightX, _lightY);
                        RecursiveCutOutSouthwestWest(depth + 1, sSlope, newESlope);
                    }
                    isLastCellBlocked = true;
                } else {
                    if (isLastCellBlocked) {
                        sSlope = -calcInverseSlope((currentX - 0.5), (currentY - 0.5), _lightX, _lightY);
                    }
                    _lightCanvas.setPixel32(currentX, currentY, 0xFFFFFFFF);
                    isLastCellBlocked = false;
                }
            }
            if (!isLastCellBlocked) {
                depth++;
                RecursiveCutOutSouthwestWest(depth, sSlope, eSlope);
            }
            
        }
        
        private function RecursiveCutOutNorthwestWest( depth:int, sSlope:Number, eSlope:Number ) : void
        {
            var sY:int = _lightY - Math.ceil(sSlope * depth);
            var eY:int = _lightY - Math.ceil(eSlope * depth);
            var currentX:int = _lightX - depth;
            
            if (currentX < 0) return;
            
            var isLastCellBlocked:Boolean = _canvas.getPixel32(currentX, sY) == BLOCKCOLOR;
            for (var currentY:int = Math.max(sY, 0); currentY <= eY; ++currentY) {
                if ( (currentX - _lightX) * (currentX - _lightX) + (currentY - _lightY) * (currentY - _lightY) > LIGHTLENGTH * LIGHTLENGTH )    continue;                

                if (_canvas.getPixel32(currentX, currentY) == BLOCKCOLOR) {
                    if (!isLastCellBlocked) {
                        var newESlope:Number = calcInverseSlope((currentX + 0.5), (currentY - 0.5), _lightX, _lightY);
                        RecursiveCutOutNorthwestWest(depth + 1, sSlope, newESlope);
                    }
                    isLastCellBlocked = true;
                } else {
                    if (isLastCellBlocked) {
                        sSlope = calcInverseSlope((currentX - 0.5), (currentY + 0.5), _lightX, _lightY);
                    }
                    _lightCanvas.setPixel32(currentX, currentY, 0xFFFFFFFF);
                    isLastCellBlocked = false;
                }
            }
            if (!isLastCellBlocked) {
                depth++;
                RecursiveCutOutNorthwestWest(depth, sSlope, eSlope);
            }        
        }
        
        private function RecursiveCutOutNorthwestNorth( depth:int, sSlope:Number, eSlope:Number ) : void
        {
            var sX:int = _lightX - Math.ceil(sSlope * depth);
            var eX:int = _lightX - Math.ceil(eSlope * depth);
            var currentY:int = _lightY - depth;
            
            if (currentY < 0) return;
            
            var isLastCellBlocked:Boolean = _canvas.getPixel32(sX, currentY) == BLOCKCOLOR;
            for (var currentX:int = Math.max(sX, 0); currentX <= eX; ++currentX) {
                if ( (currentX - _lightX) * (currentX - _lightX) + (currentY - _lightY) * (currentY - _lightY) > LIGHTLENGTH * LIGHTLENGTH )    continue;                
                
                if (_canvas.getPixel32(currentX, currentY) == BLOCKCOLOR) {
                    
                    if (!isLastCellBlocked) {
                        var newESlope:Number = calcSlope(_lightX, _lightY, (currentX - 0.5), (currentY + 0.5));
                        // start recursion for the next depth
                        RecursiveCutOutNorthwestNorth(depth + 1, sSlope, newESlope);
                    }
                    
                    isLastCellBlocked = true;
                } else {
                    
                    if (isLastCellBlocked) {
                       sSlope = calcSlope(_lightX, _lightY, (currentX + 0.5), (currentY - 0.5));
                    }
                    _lightCanvas.setPixel32(currentX, currentY, 0xFFFFFFFF);
                    isLastCellBlocked = false;
                    
                }
            }
            if (!isLastCellBlocked) {
                depth++;
                RecursiveCutOutNorthwestNorth(depth, sSlope, eSlope);
            }

        }
        
    }
    
}

class Wall {
    public var x:Number;
    public var y:Number;
    public var width:Number;
    public var height:Number;
    
    public function Wall() {
        
    }
}