我已决定使用Xna框架制作一个地下城爬虫游戏。我是一名计算机科学专业的学生,对c#和.net框架非常熟悉。我对我的引擎的开发的不同部分有一些疑问。
我有一个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); } } }
问题: 这是我应该这样做的正确方法,还是我应该存储一个引用我的磁贴列表的列表?
我如何处理多层地图?
目前我有一个方法循环遍历我的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;
}
是的,我很确定这不是检查瓷砖碰撞的正确方法。任何帮助都会很棒。
对于长篇帖子感到抱歉,我们非常感谢任何帮助。
答案 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。