GameHex 障害物が固定されている場合。 medadotter forked:1favorite:1lines:366license : MIT License modified : 2012-03-07 17:31:24 Embed Tweet 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; /** * ... * @author */ public class GameHex extends Sprite { private const degree60:Number = Math.PI / 6; private const SQRT3:Number = Math.sqrt(3); static private const numCols:Number = 20; static private const numRows:Number = 20; 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 GameHex() { makeGrid(); makePlayer(); stage.addEventListener(MouseEvent.CLICK, onGridClick); //addEventListener(MouseEvent.CLICK, onGridClick); } private function makePlayer():void { _player = new Sprite(); _player.graphics.beginFill(0xff0000); _player.graphics.drawCircle(0, 0, 5); _player.graphics.endFill(); var i:int = Math.floor(Math.random() * numCols); var j:int = Math.floor(Math.random() * numRows); trace(i, j); _player.x = dx * i + dx * j / 2 + cellSize; _player.y = dy * j + radius; trace(_player.x, _player.y); addChild(_player); } private function makeGrid():void { _floor = new Sprite(); 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); var gray:Shape = makeHex(radius, 0x666666); removeFloorChildren(); 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 if (node == _grid.startNode || node == _grid.endNode) { hex.graphics.copyFrom(gray.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; //if (j % 2 != 0) hex.x += distance; } } } private function removeFloorChildren():void { for (var i:int = _floor.numChildren - 1; i >= 0; i--) { _floor.removeChildAt(i); } } private function onGridClick(event:MouseEvent):void { var mouse:Point = localToGlobal(new Point(mouseX, mouseY)); 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); } } drawGrid(); findPath(); } private function findPath():void { var astar:AStar = new AStar(); if (astar.findPath(_grid)) { _path = astar.path; _index = 0; addEventListener(Event.ENTER_FRAME, onEnterFrame); } } private function onEnterFrame(event:Event):void { var i:int = _path[_index].x; var j:int = _path[_index].y; var dx:Number = cells[i][j].x - _player.x; var dy:Number = cells[i][j].y - _player.y; var dist:Number = Math.sqrt(dx * dx + dy * dy); if (dist < 1 ) { _index++; if (_index>=_path.length) { removeEventListener(Event.ENTER_FRAME, onEnterFrame); } }else { _player.x += dx * 0.5; _player.y += dy * 0.5; } } 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; } } Code Fullscreen Preview Fullscreen smallwind191.. test Point.distance search Object Math.abs hitTestPoint localToGlobal parent Math.floor trace removeChildAt unshift sortOn MouseEvent.ENTER_FRAME Math.sqrt numChildren Array.NUMERIC concat shift Boolean sort new page view favorite forked pv433 Pathfind with camera NewKrok forked:0 favorite:4lines:371 (diff:68) tag: pathfind