【问题标题】:XNA C# 2D Tile EngineXNA C# 2D 平铺引擎
【发布时间】:2013-06-18 17:09:02
【问题描述】:

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

  1. 加载地图

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

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. 碰撞检测

目前我有一个方法循环遍历存储在我的 testTiles 列表中的每个图块,并检查其尺寸是否与玩家尺寸相交,然后返回所有图块的列表。我有一个名为 CollisionTile 的瓦片类的派生类,当玩家和该矩形相交时会触发碰撞。 (公共类 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;
        }

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

抱歉,帖子太长了,我们将不胜感激。

【问题讨论】:

  • 您应该只绘制玩家视野中的图块。至于多层,您可以使用多种方法,例如创建另一个类 TileLayer,其中包含带有 ZIndex 的 List&lt;TileRow&gt;,您可以通过让每个图块包含具有 ZIndex 的实体来直接在图块上绘制或合并图层。跨度>
  • 请不要使用标签(例如 RPG),除非您了解其含义在此站点上。 RPG 是一种主要由专业程序员使用的编程语言,用于构建用于运行我们认为理所当然的大部分业务的软件。

标签: c# .net xna


【解决方案1】:

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

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

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

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

另一个例子,您可以使用玩家的 Rectangle 查询世界,并且只检查为您的世界的那部分返回的图块上的碰撞。

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

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

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

【讨论】:

  • 谢谢你的帮助
【解决方案2】:

对于具有标准宽度和高度的统一图块集,很容易计算哪些图块在屏幕上可见,并确定您的角色与哪些图块重叠。尽管我在 Jon 的回答中写了 QuadTree,但我认为这太过分了。一般公式为:

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

然后您可以在二维数组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 之外。

【讨论】:

  • 很高兴您对此提供了见解。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多