2006/10/27 | Flash地图A*算法
类别(Flash&AS2) | 评论(0) | 阅读(843) | 发表于 16:23

    在之前的广度优先算法上加了对每个节点的估价函数变成了A*,有兴趣的可以看看代码,没写注释,有不懂的联系我,呵呵。

    不知道怎么回事,5d居然不能显示上传的swf了,演示地址http://blog.5d.cn/user10/Billows/upload/2006-010/20061027162236094.swf这样吧

/**
 * @author Billow
 */
class AStar {
 private var pathTime:Number;
 private var path:Object;
 private var root:MovieClip;
 private var openA:Array;
 private var closeA:Array;
 private var mapArray:Array;
 private var pathArray:Array;
 private var colID:Number = 50;
 private var rowID:Number = 50;
 private var startColID:Number;
 private var startRowID:Number;
 private var isPathFind:Boolean = false;
 private var endRowID, endColID:Number;
 //private var nodeArray:Array;
 private var indexNum:Number = 0;
 private var preNum:Number = 0;
 //private var blockArray:Array;
 public function AStar(root:MovieClip) {
  //trace(root);
  init(root);
  attachTile();
  //attachBlock();
 }
 private function init(root:MovieClip):Void {
  this.root = root;
  startRowID = 5;
  startColID = 5;
  this.mapArray = new Array();
  //this.pathArray = new Array();
 }
 public function attachTile():Void {
  //trace("attachTile");
  var self = this;
  for (var i:Number = 0; i<rowID; i++) {
   mapArray[i] = new Array();
   for (var j:Number = 0; j<colID; j++) {
    var depth:Number = i*colID+j;
    var tile_mc = root.attachMovie("mc_tile", "mc_tile"+depth, depth);
    tile_mc._x = j*tile_mc._width;
    tile_mc._y = i*tile_mc._height;
    //trace(tile_mc);
    var type:String;
    var randomNum = Math.floor(Math.random()*3);
    if (randomNum == 0) {
     //mapArray[i][j].graphic.gotoAndStop(4);
     type = "block";
    } else if (randomNum>0) {
     type = "common";
     //mapArray[i][j].graphic.gotoAndStop(3);
    }
    if (i == startColID && j == startRowID) {
     //mapArray[i][j].graphic.gotoAndStop(2);
     type = "start";
    }
    mapArray[i][j] = new Tile(this, tile_mc, i, j, false, type);
   }
  }
 }
 public function onPressHandle(pressRowID:Number, pressColID:Number):Void {
  //trace("the start point is:"+startRowID+","+startColID);
  //trace("the end point is:"+pressRowID+","+pressColID);
  //trace("mapArray[pressRowID][pressRowID].type="+mapArray[pressRowID][pressColID].type);
  if (mapArray[pressRowID][pressColID].type != "common") {
   //trace("can't press");
   return;
  } else {
   //this.endRowID = pressRowID;
   //this.endColID = pressColID;
   initMapData();
   //searchPath(startRowID, startColID, pressRowID, pressColID);
   findPath(startRowID, startColID, pressRowID, pressColID);
   //pushPathArray(pressRowID, pressColID);
   attachPath();
  }
 }
 private function initMapData():Void {
  resetAllIsChecked();
  preNum = 0;
  indexNum = 0;
  closeA.splice(0);
  pathArray.splice(0);
 }
 private function attachPath():Void {
  for (var i:Number = 0; i<pathArray.length; i++) {
   var rowNum = pathArray[i].x;
   var colNum = pathArray[i].y;
   //trace("x,y="+rowNum+","+colNum);
   mapArray[rowNum][colNum].graphic.gotoAndStop("move");
  }
 }
 private function resetAllIsChecked():Void {
  for (var i:Number = 0; i<rowID; i++) {
   for (var j:Number = 0; j<colID; j++) {
    mapArray[i][j].setIsChecked(false);
    mapArray[i][j].graphic.gotoAndStop(mapArray[i][j].type);
   }
  }
 }
 private function pushPathArray(ex, ey:Number) {
  pathArray.push({x:ex, y:ey});
  var curIndexNum:Number = closeA[closeA.length-1].preNum;
  while (curIndexNum>0) {
   pathArray.push({x:closeA[curIndexNum-1].sx, y:closeA[curIndexNum-1].sy});
   curIndexNum = closeA[curIndexNum-1].preNum;
  }
 }
 function make_path(ob) {
  // create path array
  pathArray = new Array();
  // loop until no more parents
  while (ob.parentx != null) {
   // add the x and y
   //pathArray[pathArray.length] = ob.x;
   //pathArray[pathArray.length] = ob.y;
   pathArray.push({x:ob.x, y:ob.y});
   // mark the tile
   //game.clip["t_"+ob.y+"_"+ob.x].mark.gotoAndStop(2);
   // make its parent new object
   ob = path["node_"+ob.parenty+"_"+ob.parentx];
  }
  // show time it took to find path
  trace(getTimer()-pathTime+" ms");
 }
 function findPath(startx, starty, targetx, targety:Number) {
  // start timer
  pathTime = getTimer();
  // make new path object
  path = {};
  // make new array for unchecked tiles
  path.Unchecked_Neighbours = [];
  // not done yet
  path.done = false;
  // initialize
  path.name = "node_"+starty+"_"+startx;
  // create first node
  var cost = Math.abs(startx-targetx)+Math.abs(starty-targety);
  path[path.name] = {x:startx, y:starty, visited:true, parentx:null, parenty:null, cost:cost};
  // add node to array
  path.Unchecked_Neighbours[path.Unchecked_Neighbours.length] = path[path.name];
  // loop
  while (path.Unchecked_Neighbours.length>0) {
   // get the next node
   var N = path.Unchecked_Neighbours.shift();
   // we've finished
   if (N.x == targetx and N.y == targety) {
    // done
    make_path(N);
    path.done = true;
    break;
   } else {
    N.visited = true;
    // right neighbour
    addNode(N, N.x+1, N.y, targetx, targety);
    // left neighbour
    addNode(N, N.x-1, N.y, targetx, targety);
    // up neighbour
    addNode(N, N.x, N.y+1, targetx, targety);
    // down neighbour
    addNode(N, N.x, N.y-1, targetx, targety);
    // rightUp neighbour
    addNode(N, N.x+1, N.y-1, targetx, targety);
    // leftUp neighbour
    addNode(N, N.x-1, N.y-1, targetx, targety);
    // rightDown neighbour
    addNode(N, N.x+1, N.y+1, targetx, targety);
    // leftDown neighbour
    addNode(N, N.x-1, N.y+1, targetx, targety);
    
   }
  }
  // remove path object
  delete path;
  // check if path was found
  if (path.done) {
   // we reached the goal
   return true;
  } else {
   // we couldn't get there;
   return false;
  }
 }
 function addNode(ob, x, y, targetx, targety) {
  // name of the new node
  path.name = "node_"+y+"_"+x;
  // add to the unchecked neighbours, if its walkable
  //if (game["t_"+y+"_"+x].walkable) {
  if (mapArray[x][y].type == "common") {
   // find estimated cost to the target
   var cost = Math.abs(x-targetx)+Math.abs(y-targety);
   // and if its not visited yet
   if (path[path.name].cost>cost || path[path.name].cost == undefined) {
    // make new node
    path[path.name] = {x:x, y:y, visited:false, parentx:ob.x, parenty:ob.y, cost:cost};
    // add to the array
    for (var i = 0; i<path.Unchecked_Neighbours.length; i++) {
     if (cost<path.Unchecked_Neighbours[i].cost) {
      path.Unchecked_Neighbours.splice(i, 0, path[path.name]);
      break;
     }
    }
    // didnt add it yet, too much cost, add to the end
    if (i>=path.Unchecked_Neighbours.length) {
     path.Unchecked_Neighbours[path.Unchecked_Neighbours.length] = path[path.name];
    }
   }
  }
 }
 public static function main(root:MovieClip) {
  new AStar(root);
 }
}

点击在新窗口中查看
0

评论Comments

日志分类
首页[116]
Flash&AS2[56]
FMS[3]
Flex&AS3[5]
Asp[5]
My Works[13]
My Life[34]