【问题标题】:Drawing tile-maps monogame performance绘制瓷砖地图单游戏性能
【发布时间】:2016-05-08 20:28:51
【问题描述】:

在给定的情况下:
- 一张 32x32 的 Tile 地图即将用 C# 在 monogame 中绘制。
- 每个纹理都是 64x64 像素。
- 只有一种纹理(即一个 .png 文件)不断重复自己来填充地图。
- 每个图块都是 Tile.cs 类中的对象

示例 1:
创建一个包含要绘制的一个纹理的静态/抽象类,以便每个平铺对象在绘制时都可以使用它。

    public void Draw(){
        //Texture.GrassTexture is from the static class
        tile.Draw(Textures.GrassTexture);
    }

示例 2:
另一种方法是在创建新对象时为每个图块设置一个纹理变量。

    Texture2D tileTexture;
    public Tile(Texture texture){
        tileTexture = texture;
    }

绘制瓦片时,可以使用tileTexture变量。

示例 3:
绘制图块时发送纹理作为每个图块的参数。

    public void Draw(Texture2D texture){
        tile.draw(texture)
    }


从性能的角度来看,哪些示例是最佳实践?欢迎任何其他想法!


代码是为这篇文章编写的。

【问题讨论】:

    标签: c# monogame texture2d


    【解决方案1】:

    渲染性能的角度来看,重要的是在一次绘制地图期间您不会使用许多不同的纹理。

    根据我的经验,经常切换纹理确实会损害性能。因此,您真正感兴趣的是将地图的所有图块保存在单个纹理上(这通常称为纹理图集)。

    MonoGame 没有开箱即用的纹理图集支持。不过,你可以看看我们是如何在MonoGame.Extended 中实现的。

    核心思想是实现一个类来表示一个纹理区域,该区域表示多图块纹理中的单个图块。

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

    然后,当您渲染图块时,您会使用采用 源矩形的 sprite 批处理的重载。

    var sourceRectangle = textureRegion.Bounds;
    spriteBatch.Draw(textureRegion.Texture, position, sourceRectangle, color);
    

    当然,要让这一切顺利进行还需要一些其他步骤。

    1. 您需要将图块打包到单个纹理上。您可以手动执行此操作,也可以使用 TexturePacker 之类的工具。
    2. 您需要一种将切片加载到纹理区域的方法。如果图块以简单的网格模式打包,则此代码手动编写相当简单。如果您使用过纹理打包器,则需要编写一个导入器。

    最后,如果您已经在使用 Tiled Map Editor 创建地图,您可能想知道 MonoGame.Extended 已经支持加载和渲染它们。

    【讨论】:

    • 谢谢!如果我将所有意图的平铺纹理合并到图集,我假设 ContentManager 无论如何只会加载一次纹理?如果不是这样,这不是很重,因为在我的游戏中,屏幕上通常同时有 100 多个图块。我的 tile 类看起来很像你在这里描述的那个。
    • 是的,内容管理器只会加载每个纹理一次,但如果您将所有图块作为单独的纹理,它会在渲染时将负载加载到 GPU 上,因为每次都需要切换纹理呈现不同的图块。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多