XNA C#2D平铺引擎

时间:2013-06-18 17:09:02

标签: c# .net xna

我已决定使用Xna框架制作一个地下城爬虫游戏。我是一名计算机科学专业的学生,​​对c#和.net框架非常熟悉。我对我的引擎的开发的不同部分有一些疑问。

  1. 加载地图
  2. 我有一个tile类,它存储了vector2的位置,2dtexture和tile的尺寸。我有另一个名为tilemap的类,它有一个按位置索引的tile列表。我正在从一个上面的数字格式的文本文件中读取,该文件与图块列表中索引的编号相匹配,并创建一个具有正确纹理和位置的新图块,并将其存储到另一个图块列表中。

    public List<Tile> tiles = new List<Tile>(); // List of tiles that I have added to the game
    public List<TileRow> testTiles = new List<TileRow>(); // Tilerow contains a list of tiles along the x axis along with there vector2 position.
    

    阅读并存储地图图块。

        using (StreamReader stream = new StreamReader("TextFile1.txt"))
                    {
                        while (stream.EndOfStream != true)
                        {
                            line = stream.ReadLine().Trim(' ');
                            lineArray = line.Split(' ');
                            TileRow tileRow = new TileRow();
                            for (int x = 0; x < lineArray.Length; x++)
                            {  
            tileXCo = x * tiles[int.Parse(lineArray[x])].width;
            tileYCo =  yCo * tiles[int.Parse(lineArray[x])].height;
            tileRow.tileList.Add(new Tile(tiles[int.Parse(lineArray[x])].titleTexture, new Vector2(tileXCo,tileYCo)));
                            }
                            testTiles.Add(tileRow);
                            yCo++;
                        }
                    }
    

    绘制地图。

     public void Draw(SpriteBatch spriteBatch, GameTime gameTime)
            {
                foreach (TileRow tes in testTiles)
                {
                    foreach (Tile t in tes.tileList)
                    {
                        spriteBatch.Draw(t.titleTexture, t.position, Color.White);
                    }
                }
            }
    

    问题: 这是我应该这样做的正确方法,还是我应该存储一个引用我的磁贴列表的列表?

    我如何处理多层地图?

    1. 碰撞检测
    2. 目前我有一个方法循环遍历我的testTiles列表中存储的每个磁贴,并检查其尺寸是否与玩家尺寸相交,然后返回所有瓷砖的列表。我有一个名为CollisionTile的tile类的派生类,当玩家和那个矩形相交时会触发碰撞。 (公共类CollisionTile:Tile)

      public List<Tile> playerArrayPosition(TileMap tileMap)
              {  
                  List<Tile> list = new List<Tile>();
                  foreach (TileRow test in tileMap.testTiles)
                  {
                      foreach (Tile t in test.tileList)
                      {
                          Rectangle rectangle = new Rectangle((int)tempPosition.X, (int)tempPosition.Y, (int)playerImage.Width / 4, (int)playerImage.Height / 4);
                          Rectangle rectangle2 = new Rectangle((int)t.position.X, (int)t.position.Y, t.width, t.height);
                          if (rectangle.Intersects(rectangle2))
                          {
                              list.Add(t);
                          }
                      }
                  }
                  return list;
              }
      

      是的,我很确定这不是检查瓷砖碰撞的正确方法。任何帮助都会很棒。

      对于长篇帖子感到抱歉,我们非常感谢任何帮助。

2 个答案:

答案 0 :(得分:3)

你是对的。这是一种非常低效的方法来绘制和检查瓷砖上的碰撞。您应该研究的是Quadtree数据结构。

四叉树将以一种允许您使用矩形查询世界的方式存储您的图块,并且您的四叉树将返回该Rectangle内包含的所有图块。

List<Tiles> tiles = Quadtree.GetObjects(rectangle);

这允许您仅选择需要处理的切片。例如,在绘制切片时,可以指定视口大小的矩形,并且只绘制那些切片(剔除)。

另一个例子是,您可以使用播放器的矩形查询世界,并仅检查为您的世界部分返回的磁贴上的碰撞。

要加载切片,您可能需要考虑加载到二维数组中,而不是加载List。这将允许您根据其位置获取图块,而不是在两个列表之间交叉引用它。

Tile[,] tiles = new Tile[,]
Tile tile = tiles[x,y];

此外,在这种情况下,数组数据结构比使用List更有效。

答案 1 :(得分:3)

对于标准宽度和高度的均匀瓷砖组,可以很容易地计算出哪些瓷砖在屏幕上可见,并确定您的角色与哪些瓷砖重叠。尽管我在Jon的回答中写了QuadTree,但我觉得这样做太过分了。通常,公式为:

tileX = someXCoordinate % tileWidth;
tileY = someYCoordinate % tileHeight;

然后你可以在2D数组tiles[tileX, tileY]中查找它。对于绘图,这可用于确定哪个图块位于屏幕的左上角,然后再次对右下角(+1)执行相同操作,或者在左上角添加图块以填充屏幕。然后你的循环看起来更像:

leftmostTile = screenX % tileWidth;    // screenX is the left edge of the screen in world coords
topmostTile = screenY % tileHeight;
rightmostTile = (screenX + screenWidth) % tileWidth;
bottommostTile = (screenY + screenHeight) % tileHeight;
for(int tileX = leftmostTile; tileX <= rightmostTile; tileX++)
{
    for(int tileY = topmostTile; tileY <= bottommostTile; tileY++)
    {
        Tile t = tiles[tileX][tileY];
        // ... more stuff
    }
}

可以使用相同的简单公式快速确定哪些图块位于矩形区域下。

但是,如果你的瓷砖是不均匀的,或者你有一个等轴测视图,或者你想要QuadTree提供的附加功能,我会考虑Jon的答案并使用QuadTree。如果可以的话,我会尽量让瓷砖远离QuadTree。