forked from: ShadowCast
using code from here: http://nemonon.de/blog/
But how can I load an image, another than this??
/**
* Copyright Albert ( http://wonderfl.net/user/Albert )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/2j33
*/
// forked from Albert's ShadowCast
//using code from here: http://nemonon.de/blog/
//But how can I load an image, another than this??
package {
import flash.display.Sprite;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.events.*;
import flash.net.*;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.system.LoaderContext;
import flash.geom.Rectangle;
public class FlashTest extends Sprite {
private var loader:Loader = new Loader( );
private var bd: BitmapData;
private var bm2:Bitmap;
public function FlashTest() {
// write as3 code here..
init();
}
// private static const URL:String = "http://farm4.static.flickr.com/3078/2328337281_ee32463b4e.jpg";
private static const URL:String = "http://www.ujakropolisz.hu/files/ua_images/STATIKUS/Kultura/CIK_labirintus_m_3.jpg"
private function init():void
{
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE , complete);
loader.load(new URLRequest(URL), new LoaderContext(true));
}
private function complete(e:Event):void
{
var loaderInfo:LoaderInfo = e.target as LoaderInfo;
loaderInfo.removeEventListener(Event.COMPLETE , complete);
var bm:Bitmap = loaderInfo.content as Bitmap;
var bmd:BitmapData = bm.bitmapData;
ShadowCaster(bmd, true);
var bmd2:BitmapData;
fovData=null;
bmd2=fovData;
blockedColor = 0xc0c0c0;
bm2 = new Bitmap(bmd2);
this.addChild(loaderInfo.content);
this.addChild(bm2);
bm2.alpha=0.1;
getFOV(30,120);
stage.addEventListener(MouseEvent.CLICK , onClick);
}
private function onClick(e:Event):void
{
bm2.alpha=0.8;
clearFOV();
getFOV(stage.mouseX, stage.mouseY);
}
/**
* Generates the FOV (field of view) of a pixel based map.
* Imlements the shadow cast algorithm
* Created by: Jörg Mehnert
* Created at: 2010/01/07
*/
// members
// *******************************************************************************
// the base data
private var _worldMap:BitmapData;
// the output data, containing the field of view
private var _fovData:BitmapData;
// specifies, whether the output data should be preserved or not
private var _updateOutput:Boolean;
// the color in the output data for the visible pixels
private var _visibleColor:uint = 0xFFFFFF;
// the color in the output data for the invisible pixels
private var _invisibleColor:int = 0x000000;
// the threshold color for the scan, pixel colors beneath this color will be invisible
private var _blockedColor:uint = 0xAAAAAA;
// rounded point of view coordinates to improve performance
private var _ceiledPovX:int;
private var _ceiledPovY:int;
// constructor
// *******************************************************************************
/**
* Constructor
* @param givenWorldMap
* @param preserveOutputData - default = false
*/
public function ShadowCaster(givenWorldMap:BitmapData, preserveOutputData:Boolean = false):void {
worldMap = givenWorldMap;
_updateOutput = !preserveOutputData;
}
// getter/setter
// *******************************************************************************
/**
* Gets the world map
* @return BitmapData
*/
public function get worldMap():BitmapData {
return _worldMap;
}
/**
* Sets the world map
* @param newWorldMap
*/
public function set worldMap(newWorldMap:BitmapData):void {
if (newWorldMap == null) {
throw new Error("World map (flash.display.BitmapData) cannot be null.");
}
_worldMap = newWorldMap;
fovData = _fovData;
}
/**
* Indicates, whether the output data should be preserved or not
* @return Boolean
*/
public function get isOutputUpdated():Boolean {
return _updateOutput;
}
/**
* Preserve the output data or not
* @param value
*/
public function set isOutputUpdated(value:Boolean):void {
_updateOutput = value;
}
/**
* Gets the output data
* @return BitmapData
*/
public function get fovData():BitmapData {
return _fovData;
}
/**
* Sets the output data
* @param newFovData
*/
public function set fovData(newFovData:BitmapData):void {
if (newFovData == null) {
_fovData = new BitmapData(_worldMap.width, _worldMap.height, false, _invisibleColor);
} else {
_fovData = newFovData;
}
}
/**
* Gets the visible color
* @return uint
*/
public function get visibleColor():uint {
return _visibleColor;
}
/**
* Sets the visible color. The default value is 0xFFFFFF
* @param newColor
*/
public function set visibleColor(newColor:uint):void {
_visibleColor = newColor;
}
/**
* Gets the invisible color
* @return uint
*/
public function get invisibleColor():uint {
return _invisibleColor;
}
/**
* Sets the invisible color. The default value is 0x000000
* @param newColor
*/
public function set invisibleColor(newColor:uint):void {
_invisibleColor = newColor;
}
/**
* Gets the blocked color
* @return uint
*/
public function get blockedColor():uint {
return _blockedColor;
}
/**
* Sets the blocked color. All pixel colors beneath this value will be interpreted as blocked.
* The default value is 0xAAAAAA
* @param newColor
*/
public function set blockedColor(newColor:uint):void {
_blockedColor = newColor;
}
// public methods
// *******************************************************************************
/**
* Computes the field of view, based on the current world data and the given coordinates of the view point
* @param viewPointX - the x coordinate of the view point
* @param viewPointY - the y coordinate of the view point
* @return BitmapData
*/
public function getFOV(viewPointX:Number, viewPointY:Number):BitmapData {
if (_updateOutput) {
_fovData = new BitmapData(_worldMap.width, _worldMap.height, false, _invisibleColor);
}
if (viewPointX < 0 || viewPointX > _worldMap.width
|| viewPointY < 0 || viewPointY > _worldMap.height) {
trace("ShadowCaster: The view point is out of bounds. The midpoint of the world map is used instead.");
_ceiledPovX = Math.ceil(_worldMap.width / 2);
_ceiledPovY = Math.ceil(_worldMap.height / 2);
} else {
_ceiledPovX = Math.ceil(viewPointX);
_ceiledPovY = Math.ceil(viewPointY);
}
// call all octants
inspectNorthwestNorth(0, 1, 0);
inspectNorthwestWest(0, 1, 0);
inspectSouthwestWest(0, 1, 0);
inspectSouthwestSouth(0, 1, 0);
inspectSoutheastSouth(0, 1, 0);
inspectSoutheastEast(0, 1, 0);
inspectNortheastEast(0, 1, 0);
inspectNortheastNorth(0, 1, 0);
return _fovData;
}
public function clearFOV( ):void {
_fovData.fillRect(new Rectangle(0,0,_worldMap.width, _worldMap.height), 0x000000);
}
// private methods
// *******************************************************************************
private function inspectNorthwestNorth(depth:int, startSlope:Number, endSlope:Number):void {
var startX:int = _ceiledPovX - Math.ceil(startSlope * depth);
var endX:int = _ceiledPovX - Math.ceil(endSlope * depth);
var currentY:int = _ceiledPovY - depth;
if (currentY < 0) return;
var isLastCellBlocked:Boolean = _worldMap.getPixel(startX, currentY) < _blockedColor;
for (var currentX:int = Math.max(startX, 0); currentX <= endX; ++currentX) {
if (_worldMap.getPixel(currentX, currentY) < _blockedColor) {
if (!isLastCellBlocked) {
var newScanEndSlope:Number = computeSlope(_ceiledPovX, _ceiledPovY, (currentX - 0.5), (currentY + 0.5));
// start recursion for the next depth
inspectNorthwestNorth(depth + 1, startSlope, newScanEndSlope);
}
isLastCellBlocked = true;
} else {
if (isLastCellBlocked) {
startSlope = computeSlope(_ceiledPovX, _ceiledPovY, (currentX + 0.5), (currentY - 0.5));
}
_fovData.setPixel(currentX, currentY, _visibleColor);
isLastCellBlocked = false;
}
}
if (!isLastCellBlocked) {
depth++;
inspectNorthwestNorth(depth, startSlope, endSlope);
}
}
private function inspectSouthwestWest(depth:int, startSlope:Number, endSlope:Number):void {
var startY:int = Math.ceil(startSlope * depth) + _ceiledPovY;
var endY:int = Math.ceil(endSlope * depth) + _ceiledPovY;
var currentX:int = _ceiledPovX - depth;
if (currentX < 0) return;
var isLastCellBlocked:Boolean = _worldMap.getPixel(currentX, startY) < _blockedColor;
for (var currentY:int = Math.min(startY, _worldMap.height); currentY >= endY; --currentY) {
if (_worldMap.getPixel(currentX, currentY) < _blockedColor) {
if (!isLastCellBlocked) {
var newScanEndSlope:Number = -computeInverseSlope((currentX + 0.5), (currentY + 0.5), _ceiledPovX, _ceiledPovY);
inspectSouthwestWest(depth + 1, startSlope, newScanEndSlope);
}
isLastCellBlocked = true;
} else {
if (isLastCellBlocked) {
startSlope = -computeInverseSlope((currentX - 0.5), (currentY - 0.5), _ceiledPovX, _ceiledPovY);
}
_fovData.setPixel(currentX, currentY, _visibleColor);
isLastCellBlocked = false;
}
}
if (!isLastCellBlocked) {
depth++;
inspectSouthwestWest(depth, startSlope, endSlope);
}
}
private function inspectNorthwestWest(depth:int, startSlope:Number, endSlope:Number):void {
var startY:int = _ceiledPovY - Math.ceil(startSlope * depth);
var endY:int = _ceiledPovY - Math.ceil(endSlope * depth);
var currentX:int = _ceiledPovX - depth;
if (currentX < 0) return;
var isLastCellBlocked:Boolean = _worldMap.getPixel(currentX, startY) < _blockedColor;
for (var currentY:int = Math.max(startY, 0); currentY <= endY; ++currentY) {
if (_worldMap.getPixel(currentX, currentY) < _blockedColor) {
if (!isLastCellBlocked) {
var newScanEndSlope:Number = computeInverseSlope((currentX + 0.5), (currentY - 0.5), _ceiledPovX, _ceiledPovY);
inspectNorthwestWest(depth + 1, startSlope, newScanEndSlope);
}
isLastCellBlocked = true;
} else {
if (isLastCellBlocked) {
startSlope = computeInverseSlope((currentX - 0.5), (currentY + 0.5), _ceiledPovX, _ceiledPovY);
}
_fovData.setPixel(currentX, currentY, _visibleColor);
isLastCellBlocked = false;
}
}
if (!isLastCellBlocked) {
depth++;
inspectNorthwestWest(depth, startSlope, endSlope);
}
}
private function inspectSouthwestSouth(depth:int, startSlope:Number, endSlope:Number):void {
var startX:int = _ceiledPovX - Math.ceil(startSlope * depth);
var endX:int = _ceiledPovX - Math.ceil(endSlope * depth);
var currentY:int = _ceiledPovY + depth;
if (currentY > _worldMap.height) return;
var isLastCellBlocked:Boolean = _worldMap.getPixel(startX, currentY) < _blockedColor;
for (var currentX:int = Math.max(startX, 0); currentX <= endX; ++currentX) {
if (_worldMap.getPixel(currentX, currentY) < _blockedColor) {
if (!isLastCellBlocked) {
var newScanEndSlope:Number = -computeSlope(_ceiledPovX, _ceiledPovY, (currentX - 0.5), (currentY - 0.5));
inspectSouthwestSouth(depth + 1, startSlope, newScanEndSlope);
}
isLastCellBlocked = true;
} else {
if (isLastCellBlocked) {
startSlope = -computeSlope(_ceiledPovX, _ceiledPovY, (currentX + 0.5), (currentY + 0.5));
}
_fovData.setPixel(currentX, currentY, _visibleColor);
isLastCellBlocked = false;
}
}
if (!isLastCellBlocked) {
depth++;
inspectSouthwestSouth(depth, startSlope, endSlope);
}
}
private function inspectSoutheastSouth(depth:int, startSlope:Number, endSlope:Number):void {
var startX:int = Math.ceil(startSlope * depth) + _ceiledPovX;
var endX:int = Math.ceil(endSlope * depth) + _ceiledPovX;
var currentY:int = _ceiledPovY + depth;
if (currentY > _worldMap.height) return;
var isLastCellBlocked:Boolean = _worldMap.getPixel(startX, currentY) < _blockedColor;
for (var currentX:int = Math.min(startX, _worldMap.width); currentX >= endX; --currentX) {
if (_worldMap.getPixel(currentX, currentY) < _blockedColor) {
if (!isLastCellBlocked) {
var newScanEndSlope:Number = computeSlope(_ceiledPovX, _ceiledPovY, (currentX + 0.5), (currentY - 0.5));
inspectSoutheastSouth(depth + 1, startSlope, newScanEndSlope);
}
isLastCellBlocked = true;
} else {
if (isLastCellBlocked) {
startSlope = computeSlope(_ceiledPovX, _ceiledPovY, (currentX - 0.5), (currentY + 0.5));
}
_fovData.setPixel(currentX, currentY, _visibleColor);
isLastCellBlocked = false;
}
}
if (!isLastCellBlocked) {
depth++;
inspectSoutheastSouth(depth, startSlope, endSlope);
}
}
private function inspectSoutheastEast(depth:int, startSlope:Number, endSlope:Number):void {
var startY:int = _ceiledPovY + Math.ceil(startSlope * depth);
var endY:int = _ceiledPovY + Math.ceil(endSlope * depth);
var currentX:int = _ceiledPovX + depth;
if (currentX > _worldMap.width) return;
var isLastCellBlocked:Boolean = _worldMap.getPixel(currentX, startY) < _blockedColor;
for (var currentY:int = Math.min(startY, _worldMap.height); currentY >= endY; --currentY) {
if (_worldMap.getPixel(currentX, currentY) < _blockedColor) {
if (!isLastCellBlocked) {
var newScanEndSlope:Number = computeInverseSlope((currentX - 0.5), (currentY + 0.5), _ceiledPovX, _ceiledPovY);
inspectSoutheastEast(depth + 1, startSlope, newScanEndSlope);
}
isLastCellBlocked = true;
} else {
if (isLastCellBlocked) {
startSlope = computeInverseSlope((currentX + 0.5), (currentY - 0.5), _ceiledPovX, _ceiledPovY);
}
_fovData.setPixel(currentX, currentY, _visibleColor);
isLastCellBlocked = false;
}
}
if (!isLastCellBlocked) {
depth++;
inspectSoutheastEast(depth, startSlope, endSlope);
}
}
private function inspectNortheastEast(depth:int, startSlope:Number, endSlope:Number):void {
var startY:int = _ceiledPovY - Math.ceil(startSlope * depth);
var endY:int = _ceiledPovY - Math.ceil(endSlope * depth);
var currentX:int = _ceiledPovX + depth;
if (currentX > _worldMap.width) return;
var isLastCellBlocked:Boolean = _worldMap.getPixel(currentX, startY) < _blockedColor;
for (var currentY:int = Math.max(startY, 0); currentY <= endY; ++currentY) {
if (_worldMap.getPixel(currentX, currentY) < _blockedColor) {
if (!isLastCellBlocked) {
var newScanEndSlope:Number = -computeInverseSlope((currentX - 0.5), (currentY - 0.5), _ceiledPovX, _ceiledPovY);
inspectNortheastEast(depth + 1, startSlope, newScanEndSlope);
}
isLastCellBlocked = true;
} else {
if (isLastCellBlocked) {
startSlope = -computeInverseSlope((currentX + 0.5), (currentY + 0.5), _ceiledPovX, _ceiledPovY);
}
_fovData.setPixel(currentX, currentY, _visibleColor);
isLastCellBlocked = false;
}
}
if (!isLastCellBlocked) {
depth++;
inspectNortheastEast(depth, startSlope, endSlope);
}
}
private function inspectNortheastNorth(depth:int, startSlope:Number, endSlope:Number):void {
var startX:int = _ceiledPovX + Math.ceil(startSlope * depth);
var endX:int = _ceiledPovX + Math.ceil(endSlope * depth);
var currentY:int = _ceiledPovY - depth;
if (currentY < 0) return;
var isLastCellBlocked:Boolean = _worldMap.getPixel(startX, currentY) < _blockedColor;
for (var currentX:int = Math.min(startX, _worldMap.width); currentX >= endX; --currentX) {
if (_worldMap.getPixel(currentX, currentY) < _blockedColor) {
if (!isLastCellBlocked) {
var newScanEndSlope:Number = -computeSlope(_ceiledPovX, _ceiledPovY, (currentX + 0.5), (currentY + 0.5));
inspectNortheastNorth(depth + 1, startSlope, newScanEndSlope);
}
isLastCellBlocked = true;
} else {
if (isLastCellBlocked) {
startSlope = -computeSlope(_ceiledPovX, _ceiledPovY, (currentX - 0.5), (currentY - 0.5));
}
_fovData.setPixel(currentX, currentY, _visibleColor);
isLastCellBlocked = false;
}
}
if (!isLastCellBlocked) {
depth++;
inspectNortheastNorth(depth, startSlope, endSlope);
}
}
private function computeSlope(x1:Number, y1:Number, x2:Number, y2:Number):Number {
return ((x1 - x2) / (y1 - y2));
}
private function computeInverseSlope(x1:Number, y1:Number, x2:Number, y2:Number):Number {
return (1 / ((x1 - x2) / (y1 - y2)));
}
}
}