绘制瓦片地图单游戏性能
Drawing tile-maps monogame performance
在特定情况下:
- 一张 32x32 的 Tile 地图即将用 C# 在 monogame 中绘制。
- 每个纹理都是 64x64 像素。
- 只有一种纹理(即一个 .png 文件)一遍又一遍地重复填充地图。
- 每个图块都是 class Tile.cs
中的对象
示例 1:
创建一个包含要绘制的纹理的 static/abstract class,以便每个图块对象在绘制时都可以使用它。
public void Draw(){
//Texture.GrassTexture is from the static class
tile.Draw(Textures.GrassTexture);
}
示例 2:
另一种方法是在从每个图块创建新对象时为每个图块设置一个纹理变量。
Texture2D tileTexture;
public Tile(Texture texture){
tileTexture = texture;
}
绘制tile时,可以使用tileTexture变量。
示例 3:
绘制瓦片时为每个瓦片发送纹理作为参数。
public void Draw(Texture2D texture){
tile.draw(texture)
}
从性能的角度来看,哪些示例是最佳实践?欢迎任何其他想法!
代码就是为了这个post.
从渲染性能的角度来看,重要的是您不会在一次绘制地图的过程中使用许多不同的纹理。
根据我的经验,经常切换纹理确实会损害性能。因此,您真正感兴趣的是将地图的所有图块保留在单个纹理上(这通常称为 纹理图集 )。
MonoGame 没有开箱即用的纹理图集支持。但是,您可以看看我们如何在 MonoGame.Extended.
中实现它
核心思想是实现一个 class 来表示一个 纹理区域 ,该区域表示多图块纹理中的单个图块。
public class TextureRegion2D
{
public TextureRegion2D(string name, Texture2D texture, int x, int y, int width, int height)
{
if (texture == null) throw new ArgumentNullException("texture");
Name = name;
Texture = texture;
X = x;
Y = y;
Width = width;
Height = height;
}
public string Name { get; private set; }
public Texture2D Texture { get; protected set; }
public int X { get; private set; }
public int Y { get; private set; }
public int Width { get; private set; }
public int Height { get; private set; }
public Rectangle Bounds
{
get { return new Rectangle(X, Y, Width, Height); }
}
}
然后当你渲染你的图块时,你使用了精灵批次的重载,它需要一个源矩形。
var sourceRectangle = textureRegion.Bounds;
spriteBatch.Draw(textureRegion.Texture, position, sourceRectangle, color);
当然,要使所有这些都很好地工作还需要一些其他步骤。
- 您需要将图块打包到一个纹理上。您可以手动执行此操作或使用 TexturePacker.
等工具
- 您需要一种方法将您的图块加载到纹理区域中。如果磁贴以简单的网格模式打包,则此代码手写起来相当简单。如果您使用过纹理打包器,则需要编写一个导入器。
最后,如果您已经在使用 Tiled Map Editor 创建地图,您可能有兴趣知道 MonoGame.Extended 已经支持加载和渲染它们。
在特定情况下:
- 一张 32x32 的 Tile 地图即将用 C# 在 monogame 中绘制。
- 每个纹理都是 64x64 像素。
- 只有一种纹理(即一个 .png 文件)一遍又一遍地重复填充地图。
- 每个图块都是 class Tile.cs
中的对象
示例 1:
创建一个包含要绘制的纹理的 static/abstract class,以便每个图块对象在绘制时都可以使用它。
public void Draw(){
//Texture.GrassTexture is from the static class
tile.Draw(Textures.GrassTexture);
}
示例 2:
另一种方法是在从每个图块创建新对象时为每个图块设置一个纹理变量。
Texture2D tileTexture;
public Tile(Texture texture){
tileTexture = texture;
}
绘制tile时,可以使用tileTexture变量。
示例 3:
绘制瓦片时为每个瓦片发送纹理作为参数。
public void Draw(Texture2D texture){
tile.draw(texture)
}
从性能的角度来看,哪些示例是最佳实践?欢迎任何其他想法!
代码就是为了这个post.
从渲染性能的角度来看,重要的是您不会在一次绘制地图的过程中使用许多不同的纹理。
根据我的经验,经常切换纹理确实会损害性能。因此,您真正感兴趣的是将地图的所有图块保留在单个纹理上(这通常称为 纹理图集 )。
MonoGame 没有开箱即用的纹理图集支持。但是,您可以看看我们如何在 MonoGame.Extended.
中实现它核心思想是实现一个 class 来表示一个 纹理区域 ,该区域表示多图块纹理中的单个图块。
public class TextureRegion2D
{
public TextureRegion2D(string name, Texture2D texture, int x, int y, int width, int height)
{
if (texture == null) throw new ArgumentNullException("texture");
Name = name;
Texture = texture;
X = x;
Y = y;
Width = width;
Height = height;
}
public string Name { get; private set; }
public Texture2D Texture { get; protected set; }
public int X { get; private set; }
public int Y { get; private set; }
public int Width { get; private set; }
public int Height { get; private set; }
public Rectangle Bounds
{
get { return new Rectangle(X, Y, Width, Height); }
}
}
然后当你渲染你的图块时,你使用了精灵批次的重载,它需要一个源矩形。
var sourceRectangle = textureRegion.Bounds;
spriteBatch.Draw(textureRegion.Texture, position, sourceRectangle, color);
当然,要使所有这些都很好地工作还需要一些其他步骤。
- 您需要将图块打包到一个纹理上。您可以手动执行此操作或使用 TexturePacker. 等工具
- 您需要一种方法将您的图块加载到纹理区域中。如果磁贴以简单的网格模式打包,则此代码手写起来相当简单。如果您使用过纹理打包器,则需要编写一个导入器。
最后,如果您已经在使用 Tiled Map Editor 创建地图,您可能有兴趣知道 MonoGame.Extended 已经支持加载和渲染它们。