如何只绘制在屏幕上可见的贴图(精灵)
本文关键字:精灵 绘制 屏幕 | 更新日期: 2023-09-27 18:16:41
我正在尝试创造一个简单的2d滚动游戏作为学习练习在一夫一妻制(XNA)。目前,我从文本文件中加载贴图信息,创建一个数组(tiles[,]),其中包含一个tile对象,用于存储关于在哪里写入贴图以及在调用draw方法时应该使用什么纹理的信息。目前,我一次绘制数组中的每个贴图,然后简单地更新贴图的位置,使其在屏幕上移动。显然,一次画出所有的贴图有点痛苦,我认为如果我只画屏幕上可见的贴图会更好,这样当贴图在屏幕上移动时,就会画出更多的贴图。我不知道怎么做最好?我有点不知所措,我怎么知道应该画什么瓷砖。任何帮助都将非常感激。下面是我在关卡类中的绘制和更新方法——它只是调用Tile类中的方法来绘制/更新位置。
/// <summary>
/// Draws each individual tile in the level.
/// </summary>
private void DrawTiles(SpriteBatch spriteBatch)
{
// For each tile position
for (int y = 0; y < Height; ++y)
{
for (int x = 0; x < Width; ++x)
{
tiles[x, y].Draw(spriteBatch);
}
}
}
public void Update(GameTime gameTime, int scrollSpeed, ScrollDirection direction)
{
// Update the positions of each of the Background sprites
foreach (Tile tile in tiles)
{
tile.Update(gameTime, new Vector2(0, scrollSpeed), scrollDirection);
}
}
}
Thanks in advance
我现在尝试只循环通过屏幕上可见的瓷砖来绘制,使用从图形设备传递的视口。在尝试绘制它们之前,我基本上会尝试获得屏幕上可以容纳的瓷砖数量,方法是将屏幕的高度除以瓷砖的高度,宽度也是如此。这工作得很好,它绘制了视点中可见的所有瓷砖。
唯一的问题是它不再绘制任何开始于视口之外的贴图,所以即使在更新贴图被移动到视口中,它们也不会被绘制,因为循环使用它们的原始位置。我想不出一种方法来解决这个问题,而不是通过所有的瓷砖循环:-(
)因为关卡可能很大,所以循环遍历所有贴图而只绘制屏幕上的内容是非常低效的。
如有任何建议,不胜感激。
这是更新后的图纸:
private void DrawTiles(SpriteBatch spriteBatch)
{
float tileWidth = 40;
float tileHeight = 32;
for (int y = 0; y < (int)Math.Ceiling(mViewport.Height / tileHeight); ++y)
{
for (int x = 0; x < (int)Math.Ceiling(mViewport.Width / tileWidth); ++x)
{
tiles[x, y].Draw(spriteBatch);
}
}
}
你需要关于你的相机的信息。如果你知道相机的中心位置和屏幕大小,你可以有这样一个draw调用:
private void DrawTiles(SpriteBatch spriteBatch)
{
// For each tile position
for (int y = cameraOffset.Y - screenHeight / 2; y < cameraOffset.Y + (int)Math.Ceiling(screenHeight / 2); ++y)
{
for (int x = cameraOffset.X - screenWidth / 2; x < cameraOffset.X + (int)Math.Ceiling(screenWidth / 2); ++x)
{
tiles[x, y].Draw(spriteBatch);
}
}
}
我用数学的原因。如果瓷砖部分在屏幕上,天花板将被覆盖。的数学。另一边的底数是隐含的,因为它是整数除法。
注意,这里假设cameraOffset, screenWidth和screenHeight都是以tile为单位的。如果不是,适当地转换它们。
创建名为WINDOW_WIDTH和WINDOW_HEIGHT的常量来存储窗口的宽度和高度。然后,像您所展示的那样绘制图块,但是只使用在WINDOW_WIDTH和WINDOW_HEIGHT值内的图块。在Tile类
中还需要X和Y属性private void DrawTiles(SpriteBatch spriteBatch)
{
float tileWidth = 40;
float tileHeight = 32;
for (int y = 0; y < (int)Math.Ceiling(mViewport.Height / tileHeight); ++y)
{
for (int x = 0; x < (int)Math.Ceiling(mViewport.Width / tileWidth); ++x)
{
if (tiles[x, y].X <= WINDOW_WIDTH &&
tiles[x, y].X >= 0 &&
tiles[x, y].Y <= WINDOW_HEIGHT &&
tiles[x, y].Y >= 0)
{
tiles[x, y].Draw(spriteBatch);
}
}
}
}