繁体   English   中英

XNA C#2D Tile Engine

[英]XNA C# 2D Tile Engine

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

  1. 载入地图

我有一个图块类,用于存储图块的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:图块)

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;
        }

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

抱歉,很长的帖子,我们将不胜感激。

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

四叉树将以某种方式存储您的图块,使您可以使用Rectangle查询世界,并且四叉树将返回该Rectangle中包含的所有图块。

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

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

另一个示例是,您可以使用玩家的Rectangle查询世界,并且仅检查在该部分世界中返回的图块上是否存在碰撞。

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

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

同样,在这种情况下,数组数据结构比使用列表要有效得多。

对于具有标准宽度和高度的统一的图块集,很容易计算出屏幕上可见的图块,并确定角色与哪些图块重叠。 即使我在乔恩的答案中写了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中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM