【问题标题】:C# read only multidimensional array and tilemapsC# 只读多维数组和 tilemaps
【发布时间】:2014-02-10 13:57:53
【问题描述】:

我制作了一个瓦片地图类,它只包含获取或设置瓦片的数据和方法。 现在我有一个问题,我想制作一个瓦片地图渲染器。 但我认为调用方法 GetTile(int layerIndex, int x, int y); 并不是很快。迭代扔瓷砖并绘制它们。 所以我想提供获得包含所有数据的完整数组的可能性。 在这种情况下,tiledMapData。 但问题是,我希望有人不能更改数组的值,因为我想为更改物理图块创建事件。 我该怎么做。

public class TiledMap
{
    public int LayerCount
    {
        get;
        private set;
    }
    public int TileCountX
    {
        get;
        private set;
    }
    public int TileCountY
    {
        get;
        private set;
    }
    public int TotalTileCount
    {
        get;
        private set;
    }

    private int[,] tiledMapData;


    public TiledMap(int layerCount, int tileCountX, int tileCountY)
    {
        LayerCount = layerCount;
        TileCountX = tileCountX;
        TileCountY = tileCountY;
        TotalTileCount = TileCountX * TileCountY;

        tiledMapData = new int[LayerCount, TotalTileCount];
        for (int layerIndex = 0; layerIndex < TotalTileCount; layerIndex++)
        {
            for (int tileIndex = 0; tileIndex < TotalTileCount; tileIndex++)
            {
                tiledMapData[layerIndex, tileIndex] = 0;
            }
        }
    }


    public int  GetTile(int layerIndex, int x, int y)
    {
        return tiledMapData[layerIndex, y * TileCountX + x];
    }
    public void SetTile(int layerIndex, int x, int y, int tileType)
    {
        tiledMapData[layerIndex, y * TileCountX + x] = tileType;
    }
}

一般来说,你将如何设计一个 100 x 100 瓦片 16 位图形并破坏可/可建造的瓦片,如何处理物理玩家交互等等......? 也许有人知道好的教程(语言不重要)

谢谢你帮助我:)

【问题讨论】:

  • 您能简单地复制数据并返回该副本吗?
  • 由于@toATwork 在我撤销的答案中指出的数组优化,我猜这种直接访问是最高效的。我猜(未经测试)每种 ReadOnlyCollection 即使是多维的也无法与纯数组性能相匹配。

标签: c# arrays tile


【解决方案1】:

好的,我不得不拒绝这个,当不直接使用 Length 时,它会产生不同的事件。

        const int countX = 100;
        const int countY = 100;
        const int countLayer = 5;
        TiledMap tm = new TiledMap(countLayer, countX, countY);

        const int testRuns = 10000;

        Console.WriteLine("Run 1, start");
        DateTime start1 = DateTime.Now;
        for (int test = 0; test < testRuns; test++)
        {
            for (int i = 0; i < countLayer; i++)
            {
                for (int j = 0; j < countX; j++)
                {
                    for (int k = 0; k < countY; k++)
                    {
                        int data = tm.GetTile(i, j, k);
                        data++;
                    }
                }
            }
        }
        DateTime end1 = DateTime.Now;
        Console.WriteLine(String.Format("Run 1, time: {0}", end1-start1));

        Console.WriteLine("Run 2, start");
        DateTime start2 = DateTime.Now;
        for (int test = 0; test < testRuns; test++)
        {
            for (int i = 0; i < countLayer; i++)
            {
                for (int j = 0; j < countX; j++)
                {
                    for (int k = 0; k < countY; k++)
                    {
                        int data = tm.DirectArray[i, k*countX + j];
                        data++;
                    }
                }
            }
        }
        DateTime end2 = DateTime.Now;
        Console.WriteLine(String.Format("Run 1, time: {0}", end2 - start2));

        Console.ReadLine();

数组访问变体的表现要好得多。仍然不确定当您使用某种只读数组时是否会这样做。所以请务必检查一下。

【讨论】:

  • 这根本不正确!如果您使用诸如for (int i = 0; i &lt; arr.Length; i++)(重要的 Length 属性!)之类的 for 循环直接访问数组(也是锯齿状的,但不是多维的),则边界检查将只进行一次,而不是每次访问!这可以产生巨大的影响!
  • 您不需要Length。上面的对象有固定的层数,X 和 Y。我正在做一个性能检查项目......
  • 我进行了性能检查 - 并仔细阅读了文档。使用 Array 和 Length 运算符,它们会进行一些内部优化 - 如前所述,例如bounds 只在循环开始时检查一次,而不是循环中的每次访问。
  • @toATwork 你是对的,优化也适用于不自己使用 Length 的情况。他只知道这是一个数组。
  • @toATwork 感谢您的指出。每天都是学习日;)
猜你喜欢
  • 2012-04-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-18
  • 2019-01-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多