2013-04-18 48 views
9

我试图围绕一个立方体实现A *寻路,立方体由6个网格组成,并保持简单我有4个方法GetXPlus,GetXMinus,GetYPlus,GetYMinus。每种方法检查下一个图块是否在当前网格空间内,如果它没有切换到适当的网格。A *寻找多个网格

我遇到的问题是,当试图从当前网格翻转的另一个网格中获取一个图块时,返回的图块位于另一面。有没有一种方法或方法可以让我避免为每一个单独的网格和方向编写独特的逻辑?

为了帮助阐明我的问题,在此我起源于(紫色)网格和使用GetXPlus方法:

enter image description here

我目前的执行情况进行SNIPPIT(每格为64 64 ):

public Tile GetXPlus(int currentX, int currentY) 
{ 
    var newX = currentX + 1; 
    var tile = GetTile(newX , currentY); 

    if(newX > 64) //Get adjacent XPlus Grid 
    { 
     currentGrid = SetCurrentGrid(XPlusGridIndex); 
     tile = GetTile(newX - 64, currentY); 
    } 

    return tile; 
} 

背景

此实现Ø从这里建议的另一个问题的绝佳答案中得到了很好的解答:https://gamedev.stackexchange.com/questions/53866/pathfinding-on-a-uneven-planetary-surface

+0

刚刚意识到有我的照片略有误差,在立方体的看法,蓝方的X和Y方向应该是相同的net view –

+1

一个有趣的问题,我还没有在[我的回答认为](http://gamedev.stackexchange.com/questions/53866/pathfinding-on-a-uneven-planetary-surface)。 – MichaelHouse

+0

听起来就像你只需要一个邻接矩阵,它描述了当你超出界限(或者改变为使用(x,y,z))时要走向哪个面。 – user7116

回答

0

您可以使用从“X坐标”,“Y坐标”和“平铺”组成的一个三维坐标空间到另一个三维坐标空间的函数映射。

发出的命令:

enum TileBorder 
{ 
    Left = 0, 
    Top = 1, 
    Right = 2, 
    Bottom = 3 
} 

可以将这些转换存储在您Tile类的数组:

​​

然后你只需要在设置的结构了要稍加注意。例如,这是您可以设置绿色瓷砖的方式,假设您的坐标从1到64(含)。

Tile pink = new Tile(); 
Tile green = new Tile(); 
Tile orange = new Tile(); 
Tile purple = new Tile(); 
Tile blue = new Tile(); 

green.Neighbors = new Tile[] 
{ 
    /* left */ orange, 
    /* top */ pink, 
    /* right */ blue, 
    /* bottom */ purple 
}; 

green.XTransitions = new Func<int, int, int>[] 
{ 
    /* left */ (x, y) => 1, 
    /* top */ (x, y) => x, 
    /* right */ (x, y) => 64, 
    /* bottom */ (x, y) => x 
}; 

green.YTransitions = new Func<int, int, int>[] 
{ 
    /* left */ (x, y) => 65 - y, 
    /* top */ (x, y) => 64, 
    /* right */ (x, y) => 65 - y, 
    /* bottom */ (x, y) => 1 
}; 

注意,瓷砖转换函数只是一个查询,但要完全灵活的,你也可以使用的功能类型:
Func<int, int, Tile, int>的x坐标,
Func<int, int, Tile, int>为y坐标,和
Func<int, int, Tile, Tile>

1

我建议你比以前的答案建议更进一步。创建一个代表所有图块的多维数据集,并缓存每个图块的邻居。由于瓷砖之间的关系是固定的,所以它可以保护你很多时间。

Afterwords可以使用double[,,]int[,,,]来跟踪您处理的瓷砖,并基于它将您的邻居添加到您的Queue<Tile>

如果需要,您也可以实施GetDirection(Tile tile)。该功能只需要在方向字典中搜索。

公共课多维数据集 {0}私人瓷砖[,,]瓷砖;

public Cube(int size) 
    { 
     tiles = new Tile[size, size, 6]; 

     // initialize. 
     for (var side = 0; side < 6; side++) 
     { 
      for (var x = 0; x < size; x++) 
      { 
       for (var y = 0; y < size; y++) 
       { 
        tiles[x, y, side] = new Tile(x, y, side); 
       } 
      } 
     } 

     // set directions & neighbors 
     for (var side = 0; side < 6; side++) 
     { 
      for (var x = 0; x < size; x++) 
      { 
       for (var y = 0; y < size; y++) 
       { 
        // todo: implement. 
       } 
      } 
     } 
    } 

    public Tile this[int x, int y, int side] 
    { 
     get 
     { 
      return tiles[x, y, side]; 
     } 
    } 
} 

public class Tile 
{ 
    private Dictionary<DirectionType, Tile> directions = new Dictionary<DirectionType, Tile>(); 

    private Tile[] neighbors = new Tile[4]; 

    public Tile(int x, int y, int side) 
    { 
     this.X = x; 
     this.Y = y; 
     this.Side = side; 
    } 

    public int X { get; private set; } 
    public int Y { get; private set; } 
    public int Side { get; private set; } 

    public Tile this[DirectionType dir] 
    { 
     get 
     { 
      return directions[dir]; 
     } 
    } 



    public Tile[] Neighbors { get { return neighbors; } } 
} 

public enum DirectionType 
{ 
    // delta: +1, 0 
    e, 
    // delta: 0, +1 
    n, 
    // delta: -1, 0 
    w, 
    // delta: 0, -1 
    s, 
    // delta: 0, 0 
    X 
} 
+0

+1小心数组(与List <> s或其他集合类型相反)。它们是不可改变的,每当你通过它们时都会被重复。以你的例子来说,这似乎不是一个问题,但那些不熟悉GC在这种情况下工作的人可能会很快陷入性能问题。 –

+0

@DavidLively这是一个很好的观点,你必须牢记这一点。但在这种情况下,数组正是你想要的。瓦片的邻居是不可变的,只能间接访问。关于立方体也是如此。内存使用和速度的优势在这种情况下更为可取。 –