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

Pathfind with camera

Get Adobe Flash player
by NewKrok 08 Mar 2012
/**
 * Copyright NewKrok ( http://wonderfl.net/user/NewKrok )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/oJM8
 */

package  {
    import flash.display.Shape;
    import flash.display.SpreadMethod;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.Point;
    import caurina.transitions.Tweener;

    public class PathFinder extends Sprite {
        private const degree60:Number = Math.PI / 6;
        private const SQRT3:Number = Math.sqrt(3);
        
        static private const numCols:Number = 50;
        static private const numRows:Number = 50;
        
        private var cellSize:int = 10;
        private var _grid:Grid;
        private var _player:Sprite;
        private var _floor:Sprite;
        private var _path:Array;
        private var _index:Number;
        private var cells:Array;
        
        public function PathFinder() {
            
            makeGrid();
            makePlayer();
            addEventListener(MouseEvent.CLICK, onGridClick);
            addEventListener(Event.ENTER_FRAME, onEnterFrame);        
        }

        private function makePlayer():void {
            _player = new Sprite();
            _player.graphics.lineStyle(1,0,1)
            _player.graphics.beginFill(0x00FF00);
            _player.graphics.drawCircle(0, 0, 7);
            _player.graphics.endFill();
            _player.graphics.moveTo( 0, 0 )
            _player.graphics.lineTo( 7, 0 )
            
            var i:int = Math.floor(Math.random() * numCols);
            var j:int =    Math.floor(Math.random() * numRows);
            _player.x = dx * i + dx * j / 2 + cellSize;
            _player.y = dy * j + radius;
            addChild(_player);
        }
        
        private function makeGrid():void {
            _floor = new Sprite();
            //_floor.addChild ( new GrassBack )
            addChild(_floor);
            _grid = new Grid(numCols, numRows);
            var n:int = numCols * numRows * 2 / 9;
            for (var i:int = 0; i < n; i++) {
                _grid.setWalkable(Math.floor(Math.random() * numCols),
                                  Math.floor(Math.random() * numRows),
                                  false);
            }
            drawGrid();
        }
        
        private function drawGrid():void {
            
            cells = new Array();
                        
            var white:Shape = makeHex(radius, 0xffffff);
            var black:Shape = makeHex(radius, 0x000000);
            
            for (var i:int = 0; i < _grid.numCols; i++) {
                cells[i] = new Array();
                for (var j:int = 0; j < _grid.numRows; j++) {
                    var node:Node = _grid.getNode(i, j);
                    var hex:Shape = new Shape();
                    if (!node.walkable) {
                        hex.graphics.copyFrom(black.graphics);
                    }else{
                        hex.graphics.copyFrom(white.graphics);
                    }                    
                    _floor.addChild(hex);
                    cells[i][j] = hex;
                    hex.x = dx * i + dx * j / 2 + cellSize;
                    hex.y = dy * j + radius;
                }
            }
        }

        private function onGridClick(event:MouseEvent):void {
            var mouse:Point = localToGlobal(new Point(mouseX - x, mouseY - y));
            
            for (var i:int = 0; i < _grid.numCols; i++) {
                for (var j:int = 0; j < _grid.numRows; j++) {
                    var hex:Shape = cells[i][j];
                    if (hex.hitTestPoint(mouse.x, mouse.y, true)) _grid.setEndNode(i, j);
                    if (hex.hitTestPoint(_player.x, _player.y, true)) _grid.setStartNode(i, j);
                }
            }
            findPath();
        }
        
        private function findPath():void {
            var astar:AStar = new AStar();
            if (astar.findPath(_grid)) {
                _path = astar.path;
                _index = 1;
                _player.rotation = Math.atan2 ( _path[_index].y - _path[_index - 1].y, _path[_index].x - _path[_index - 1].x ) / ( Math.PI / 180 )
                if ( _player.rotation == 90 )
                    _player.rotation = 60
                if ( _player.rotation == -90 )
                    _player.rotation = -120
                ttt ()
            }
        }        
        
        private function ttt ():void {
            
            var i:int = _path[_index].x;
            var j:int = _path[_index].y;
            Tweener.addTween ( _player, { x: cells[i][j].x, y: cells[i][j].y, time: .3, transition: "linear", onComplete: function ():void { 
                _index++;
                if ( _index < _path.length ) {
                    _player.rotation = Math.atan2 ( _path[_index].y - _path[_index - 1].y, _path[_index].x - _path[_index - 1].x ) / ( Math.PI / 180 )
                    if ( _player.rotation == 90 )
                        _player.rotation = 60
                    if ( _player.rotation == -90 )
                        _player.rotation = -120
                    ttt()
                }
            } } )
                
        }
        
        import caurina.transitions.Tweener
        public var camP:Point = new Point ( 0, 0 ) 
        private function onEnterFrame(event:Event):void {
            
            this.x += ( ( -_player.x + _player.width / 2 + stage.stageWidth / 2 ) - camP.x ) / 20
            this.y += ( ( -_player.y + _player.height / 2 + stage.stageHeight / 2 ) - camP.y ) / 20
            camP.x = this.x
            camP.y = this.y
            
        }
        
        private function xyToAxis(x:int, y:int):Object{
            var axis:Object = new Object();
            if (x * y >= 0) {
                axis.a = 0;
                axis.b = x;
                axis.c = y;
            }else {
                if (Math.abs(x) > Math.abs(y)) {
                    axis.a = x + y;
                    axis.b = 0;
                    axis.c = -y;
                } else {
                    axis.a = 0;
                    axis.b = x + y;
                    axis.c = 2 * x + y;
                }
            }
            return axis;
        }
        
        private function axisToXY(a:int, b:int, c:int):Object {
            var xy:Object = new Object();
            xy.x = a + c;
            xy.c = -a + c;
            return xy;
        }
        
        private function makeHex(radius:Number,color:uint = 0xffffff):Shape {            
            var hex:Shape = new Shape();
            hex.graphics.lineStyle(0);
            hex.graphics.beginFill(color);
            hex.graphics.moveTo(radius * Math.cos(degree60), radius * Math.sin(degree60));
            for (var i:int = 1; i <= 6; i++) {
                var x:Number = radius * Math.cos((2 * i + 1) * degree60);
                var y:Number = radius * Math.sin((2 * i + 1) * degree60);
                hex.graphics.lineTo(x, y);
            }
            hex.graphics.endFill();
            return hex;
        }

        private function get dx():Number{
            return 2 * cellSize;
        }
        
        private function get dy():Number {
            return SQRT3 * cellSize;
        }
        
        private function get radius():Number {
            return dy * 2 / 3;
        }            
    }
}

class AStar
{
    private var _grid:Grid;
    private var _open:Array;
    private var _closed:Array;
    private var _startNode:Node;
    private var _endNode:Node;
    private var _path:Array;
    
    private var _heuristic:Function = diagonal;
    private var _straightCost:Number = 1.0;
    
    public function AStar()
    {
    
    }
    
    public function findPath(grid:Grid):Boolean
    {
        _grid = grid;
        _open = new Array();
        _closed = new Array();
        
        _startNode = _grid.startNode;
        _endNode = _grid.endNode;
        
        _startNode.g = 0;
        _startNode.h = _heuristic(_startNode);
        _startNode.f = _startNode.g + _startNode.h;
        
        return search();
    }
    
    private function search():Boolean
    {
        var node:Node = _startNode;
        while (node != _endNode)
        {
            var startX:int = Math.max(0, node.x - 1);
            var endX:int = Math.min(_grid.numCols - 1, node.x + 1);
            var startY:int = Math.max(0, node.y - 1);
            var endY:int = Math.min(_grid.numRows - 1, node.y + 1);
            
            for (var i:int = startX; i <= endX; i++)
            {
                for (var j:int = startY; j <= endY; j++)
                {
                    var test:Node = _grid.getNode(i, j);
                    if ((i - node.x) * (j - node.y) > 0)
                        continue;
                    if (test == node || !test.walkable)
                        continue;
                    
                    var cost:Number = _straightCost;
                    
                    var g:Number = node.g + cost;
                    var h:Number = _heuristic(test);
                    var f:Number = g + h;
                    if (isOpen(test) || isClosed(test))
                    {
                        if (test.f > f)
                        {
                            test.f = f;
                            test.g = g;
                            test.h = h;
                            test.parent = node;
                        }
                    }
                    else
                    {
                        test.f = f;
                        test.g = g;
                        test.h = h;
                        test.parent = node;
                        _open.push(test);
                    }
                }
            }
            _closed.push(node);
            
            if (_open.length == 0)
            {
                trace("no path found");
                return false;
            }
            _open.sortOn("f", Array.NUMERIC);
            node = _open.shift() as Node;
        }
        buildPath();
        return true;
    }
    
    private function buildPath():void
    {
        _path = new Array();
        var node:Node = _endNode;
        _path.push(node);
        while (node != _startNode)
        {
            node = node.parent;
            _path.unshift(node);
        }
    }
    
    public function get path():Array
    {
        return _path;
    }
    
    private function isOpen(node:Node):Boolean
    {
        for (var i:int = 0; i < _open.length; i++)
        {
            if (_open[i] == node)
            {
                return true;
            }
        }
        return false;
    }
    
    private function isClosed(node:Node):Boolean
    {
        for (var i:int = 0; i < _closed.length; i++)
        {
            if (_closed[i] == node)
            {
                return true;
            }
        }
        return false;
    }
    
    private function diagonal(node:Node):Number
    {
        var dx:Number = node.x - _endNode.x;
        var dy:Number = node.y - _endNode.y;
        var distance:Number = Math.abs(dx + dy);
        var A_axis:Number = (Math.abs(dx - dy) - distance) / 2;
        if (A_axis > 0)
        {
            distance += A_axis;
        }
        return distance * _straightCost;
    }
    
    public function get visited():Array
    {
        return _closed.concat(_open);
    }
}

class Grid
{
    private var _startNode:Node;
    private var _endNode:Node;
    private var _nodes:Array;
    private var _numCols:int;
    private var _numRows:int;
    
    public function Grid(numCols:int, numRows:int)
    {
        _numCols = numCols;
        _numRows = numRows;
        _nodes = new Array();
        
        for (var i:int = 0; i < _numCols; i++)
        {
            _nodes[i] = new Array();
            for (var j:int = 0; j < _numRows; j++)
            {
                _nodes[i][j] = new Node(i, j);
            }
        }
    }
    
    public function getNode(x:int, y:int):Node
    {
        return _nodes[x][y] as Node;
    }
    
    public function setStartNode(x:int, y:int):void
    {
        _startNode = _nodes[x][y] as Node;
    }
    
    public function setEndNode(x:int, y:int):void
    {
        _endNode = _nodes[x][y] as Node;
    }
    
    public function setWalkable(x:int, y:int, value:Boolean):void
    {
        _nodes[x][y].walkable = value;
    }
    
    public function get numRows():int
    {
        return _numRows;
    }
    
    public function get numCols():int
    {
        return _numCols;
    }
    
    public function get endNode():Node
    {
        return _endNode;
    }
    
    public function get startNode():Node
    {
        return _startNode;
    }

}

class Node
{
    public var x:int;
    public var y:int;
    public var f:Number;
    public var g:Number;
    public var h:Number;
    public var walkable:Boolean = true;
    public var parent:Node;
    
    public function Node(x:int, y:int)
    {
        this.x = x;
        this.y = y;
    }

}