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

PathfindingHex

HexでのA*。
Get Adobe Flash player
by medadotter 07 Mar 2012
    Embed
/**
 * Copyright medadotter ( http://wonderfl.net/user/medadotter )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/9ML0
 */

package
{
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    /**
     * ...
     * @author
     */
    [SWF(backgroundColor=0xffffff)]    
    public class Pathfinding2 extends Sprite
    {
        private var _grid:Grid;
        private var _gridView:HexGridView;
        
        public function Pathfinding2()
        {
            stage.align = StageAlign.TOP_LEFT;
            stage.scaleMode = StageScaleMode.NO_SCALE;
            
            _grid = new Grid(10, 10);
            _grid.setStartNode(2, 1);
            _grid.setEndNode(8, 8);
            
            _gridView = new HexGridView(_grid);
            _gridView.x = 20;
            _gridView.y = 20;
            addChild(_gridView);
        }
    
    }

}

import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.geom.Point;

class HexGridView extends Sprite
{
    
    private var distance:Number = 15;
    private const degree60:Number = Math.PI / 6;
    private const SQRT3:Number = Math.sqrt(3);
    private var cells:Array;
    private var _grid:Grid;
    
    public function HexGridView(grid:Grid)
    {
        _grid = grid;
        
        drawGrid();
        findPath();
        addEventListener(MouseEvent.CLICK, onGridClick);
    }
    
    private function drawGrid():void
    {
        graphics.clear();
        
        cells = new Array();
        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:Sprite = makeHex(getColor(node));
                addChild(hex);
                cells[i][j] = hex;
                hex.x = dx * i + dx * j / 2 + distance;
                hex.y = dy * j + radius;
                    //if (j % 2 != 0) hex.x += distance;
            }
        }
    }
    
    private function getColor(node:Node):uint
    {
        if (!node.walkable)
            return 0x000000;
        if (node == _grid.startNode)
            return 0x666666;
        if (node == _grid.endNode)
            return 0x666666;
        return 0xffffff;
    }
    
    private function onGridClick(event:MouseEvent):void
    {
        var mouse:Point = localToGlobal(new Point(mouseX, mouseY));
        
        for (var x:int = 0; x < _grid.numCols; x++)
        {
            for (var y:int = 0; y < _grid.numRows; y++)
            {
                var hex:Sprite = cells[x][y];
                if (hex.hitTestPoint(mouse.x, mouse.y, true))
                {
                    _grid.setWalkable(x, y, !_grid.getNode(x, y).walkable);
                    drawGrid();
                    findPath();
                    return;
                }
            }
        }
    }
    
    private function findPath():void
    {
        var astar:AStar = new AStar();
        if (astar.findPath(_grid))
        {
            showVisited(astar);
            showPath(astar);
        }
    }
    
    private function showVisited(astar:AStar):void
    {
        var visited:Array = astar.visited;
        for (var i:int = 0; i < visited.length; i++)
        {
            var node:Node = visited[i];
            var hex:Sprite = cells[node.x][node.y];
            hex.graphics.beginFill(0xcccccc);
            hex.graphics.drawCircle(0, 0, radius / 3);
            hex.graphics.endFill();
        }
    }
    
    private function showPath(astar:AStar):void
    {
        var path:Array = astar.path;
        for (var i:int = 0; i < path.length; i++)
        {
            var node:Node = path[i];
            var hex:Sprite = cells[node.x][node.y];
            hex.graphics.beginFill(0xff0000);
            hex.graphics.drawCircle(0, 0, radius / 3);
            hex.graphics.endFill();
        }
    }
    
    private function makeHex(color:uint = 0xffffff):Sprite
    {
        var hex:Sprite = new Sprite();
        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 * distance;
    }
    
    private function get dy():Number
    {
        return SQRT3 * distance;
    }
    
    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);
            trace(startX, endX, startY, endY);
            
            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;
    }

}