XNA Waterphysics自上而下基于十六进制的网格



我正在使用C#/XNA进行一个项目,在自上而下的基于十六进制的网格中创建水物理时遇到了问题。

我们使用的是一个十六进制波浪形图,其帮助如下:http://www.redblobgames.com/grids/hexagons.所以我想我可以为水流实现一个算法,但我似乎做不好,而且它的性能似乎很重。

/// <summary>
/// This method will level all the water to the same height. It does so by looking arround and make them all even
/// </summary>
/// <param name="tiles">The tile array needed to level arround</param>
public void Flow(List<Tile> tiles, Tilemap tileMap)
{
    float waterAmountEachTile;
    List<Water> waterTiles = new List<Water>(7);
    //include self
    waterTiles.Add(this);
    float waterAmount = (this.waterHeight + this.ZPos);
    for (int i = 0; i < tiles.Count; i++)//first loop to get all values
    {
        if (tiles[i].GetType() == typeof(Water))
        {
            waterTiles.Add((Water)tiles[i]);//check wich tiles are water and put them in a new array
            waterAmount += (waterTiles[waterTiles.Count - 1].waterHeight + waterTiles[waterTiles.Count - 1].ZPos);  //Increase the ammount - debuggen later werkt count goed
        }
    }
    waterAmountEachTile = waterAmount / waterTiles.Count; //Calculate how high each tile should be ( we need this for drycheck)
    dryCheck(ref waterAmount, waterTiles, waterAmountEachTile, tileMap);
    waterAmountEachTile = waterAmount / waterTiles.Count; //recalculate the ammount for each tile
    foreach (Water waterTile in waterTiles) //second loop to adjust the tile to the according hight
    {
        waterTile.waterHeight = (waterAmountEachTile - waterTile.ZPos);
    }
}
/// <summary>
/// Checks if the tile should be dry or continue being a water tile.
/// </summary>
/// <param name="waterAmount"> the ammount of water to divide among the tiles</param>
/// <param name="waterTiles">The watertiles list to do the drycheck on</param>
/// <param name="waterAmountEachTile">The height to set each water tile</param>
/// <returns></returns>
private void dryCheck(ref float waterAmount, List<Water> waterTiles, float waterAmountEachTile, Tilemap tileMap)
{
    //TODO dit fixen
    for (int i = 0; i < waterTiles.Count; i++)
    {
        if (waterTiles[i].ZPos > waterAmountEachTile) //is grond hoger dan water
        {
            waterAmount -= waterTiles[i].ZPos;
            tileMap.TileMap[waterTiles[i].XPos][waterTiles[i].YPos] = new Ground(this.graphics, waterTiles[i].XPos, waterTiles[i].YPos,
                waterTiles[i].ZPos, this.size, Tilemap.HexVertices);
            waterTiles.Remove(waterTiles[i]);
            i--;
        }
    }
}

现在我的问题是,你们中有人知道在自上而下的环境中实现水物理的方法吗,最好是使用基于十六进制的网格。

我查阅了一些自由论,发现了光滑粒子流体动力学,但我不确定它是否可以自上而下实现,而且我似乎找不到任何方向的指导。

任何帮助都将是伟大的,甚至一些指针可能就足够了。

提前感谢,C.Venhuizen

您是否分析了代码以确定最慢的部分?

我不太明白你的代码在做什么。您是为每个磁贴调用Flow一次,还是调用一次,然后它在所有磁贴上运行?如果我猜测,我会说为每个磁贴分配一个新列表会很慢。但最好的方法是了解情况。

最初让我写作的东西http://www.redblobgames.com/grids/hexagons是一个自上而下的六角游戏,一切都是关于水的流动。我在1995年写了这个游戏,最近我把它移植到了网上运行。我开始使用的算法很简单。对于每个十六进制,按随机顺序遍历

  1. 计算水位W+高程H
  2. 为每个邻居计算相同
  3. 使流向W+H最低的邻居的水量达到一半

随机顺序是为了使循环不会导致水向右流动许多六角体,但向左流动的六角体不多,或其他这样的方向伪影。更干净的方法是使用双缓冲区:将所有新值写入一个单独的数组,然后在最后将它们复制回第一个数组(或交换数组)。

除此之外,我还使用了大量的启发式方法来处理(未完成的)游戏的侵蚀和其他功能。代码很旧,很糟糕,但如果你想看一看,你可以在这里下载(ZIP文件)。参见water.cpp。我避免了在水流循环中分配内存。

相关内容

  • 没有找到相关文章

最新更新