From c760ae758ded50c0d46476535a96be05b8df0caa Mon Sep 17 00:00:00 2001 From: Cory Hughart Date: Fri, 13 Apr 2012 14:27:34 -0300 Subject: [PATCH] Added rayHit() function to FlxTilemap that explicitly returns an FlxPoint if the ray hits anything, and returns null otherwise. Default ray() function relies on passing a variable as reference to receive the hit result, which does not seem to work. See http://stackoverflow.com/questions/3708371/actionscript-pass-by-reference --- org/flixel/FlxTilemap.as | 92 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/org/flixel/FlxTilemap.as b/org/flixel/FlxTilemap.as index 441fa28b..743f8e08 100644 --- a/org/flixel/FlxTilemap.as +++ b/org/flixel/FlxTilemap.as @@ -1305,6 +1305,98 @@ package org.flixel } return true; } + + /** + * Works exactly like ray() except it explicitly returns the hit result. + * Shoots a ray from the start point to the end point. + * If/when it passes through a tile, it returns that point. + * If it does not, it returns null. + * Usage: + * var hit:FlxPoint = tilemap.rayHit(startPoint, endPoint); + * if (hit != null) //code ; + * + * @param Start The world coordinates of the start of the ray. + * @param End The world coordinates of the end of the ray. + * @param Resolution Defaults to 1, meaning check every tile or so. Higher means more checks! + * @return Returns null if the ray made it from Start to End without hitting anything. Returns FlxPoint if a tile was hit. + */ + public function rayHit(Start:FlxPoint, End:FlxPoint, Resolution:Number=1):FlxPoint + { + var Result:FlxPoint = null; + var step:Number = _tileWidth; + if(_tileHeight < _tileWidth) + step = _tileHeight; + step /= Resolution; + var deltaX:Number = End.x - Start.x; + var deltaY:Number = End.y - Start.y; + var distance:Number = Math.sqrt(deltaX*deltaX + deltaY*deltaY); + var steps:uint = Math.ceil(distance/step); + var stepX:Number = deltaX/steps; + var stepY:Number = deltaY/steps; + var curX:Number = Start.x - stepX - x; + var curY:Number = Start.y - stepY - y; + var tileX:uint; + var tileY:uint; + var i:uint = 0; + while(i < steps) + { + curX += stepX; + curY += stepY; + + if((curX < 0) || (curX > width) || (curY < 0) || (curY > height)) + { + i++; + continue; + } + + tileX = curX/_tileWidth; + tileY = curY/_tileHeight; + if((_tileObjects[_data[tileY*widthInTiles+tileX]] as FlxTile).allowCollisions) + { + //Some basic helper stuff + tileX *= _tileWidth; + tileY *= _tileHeight; + var rx:Number = 0; + var ry:Number = 0; + var q:Number; + var lx:Number = curX-stepX; + var ly:Number = curY-stepY; + + //Figure out if it crosses the X boundary + q = tileX; + if(deltaX < 0) + q += _tileWidth; + rx = q; + ry = ly + stepY*((q-lx)/stepX); + if((ry > tileY) && (ry < tileY + _tileHeight)) + { + if(Result == null) + Result = new FlxPoint(); + Result.x = rx; + Result.y = ry; + return Result; + } + + //Else, figure out if it crosses the Y boundary + q = tileY; + if(deltaY < 0) + q += _tileHeight; + rx = lx + stepX*((q-ly)/stepY); + ry = q; + if((rx > tileX) && (rx < tileX + _tileWidth)) + { + if(Result == null) + Result = new FlxPoint(); + Result.x = rx; + Result.y = ry; + return Result; + } + return null; + } + i++; + } + return null; + } /** * Converts a one-dimensional array of tile data to a comma-separated string.