在 Monogame 中使用 BMP 图像作为字体

2024-04-16

有没有办法使用 BMP 图像加载自定义字体。

我在网上看到了 Microsoft 提供的解决方案,但在尝试运行此解决方案时,我不断收到内容加载异常。

看起来这曾经适用于 XNA,但对于 Monogame 可能不再是这样了。

我想要自己的自定义字体,因为该字体不会预安装在客户端的计算机上。

我已经查看了 SpriteFont Converter 中的 XNB 文件,这不是我想要的解决方案。

任何帮助将不胜感激,谢谢


经过很长一段时间的研究,我最终在网上找到了解决方案。这是教程的链接:http://www.craftworkgames.com/blog/tutorial-bmfont-rendering-with-monogame/ http://www.craftworkgames.com/blog/tutorial-bmfont-rendering-with-monogame/

此方法需要您下载一个名为 bmFont 的软件:http://www.angelcode.com/products/bmfont/ http://www.angelcode.com/products/bmfont/

使用此软件,您将收到 2 个文件形式的字体输出:

  1. .fnt 文件,用于纹理中的图案
  2. .png 文件,这是实际的字符。

为了使这些文件与您的 monoproject 一起使用(我想也可以与 XNA 一起使用),您需要将此类添加到您的项目中(注意:您需要更改命名空间) :

// ---- AngelCode BmFont XML serializer ----------------------
// ---- By DeadlyDan @ [email protected] /cdn-cgi/l/email-protection -------------------
// ---- There's no license restrictions, use as you will. ----
// ---- Credits to http://www.angelcode.com/ -----------------

using System;
using System.IO;
using System.Xml.Serialization;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;

namespace Dashboard
{
    public class BmFont {

        String fontFilePath;
        FontFile fontFile;
        Texture2D fontTexture;
        FontRenderer _fontRenderer;

        public BmFont(String fontTexture, String png, ContentManager c) {
            fontFilePath = Path.Combine(c.RootDirectory, fontTexture);
            fontFile = FontLoader.Load(fontFilePath);
            this.fontTexture = c.Load<Texture2D>(png);
            _fontRenderer = new FontRenderer(fontFile, this.fontTexture);
        }

        public void draw(String message, Vector2 pos, SpriteBatch _spriteBatch) {
            _fontRenderer.DrawText(_spriteBatch, (int)pos.X, (int)pos.Y, message);
        }

    }


    public class FontRenderer
    {

        public static FontFile Load(Stream stream)
        {
            XmlSerializer deserializer = new XmlSerializer(typeof(FontFile));
            FontFile file = (FontFile) deserializer.Deserialize(stream);
            return file;
        }

        public FontRenderer (FontFile fontFile, Texture2D fontTexture)
        {
            _fontFile = fontFile;
            _texture = fontTexture;
            _characterMap = new Dictionary<char, FontChar>();

            foreach(var fontCharacter in _fontFile.Chars)
            {
                char c = (char)fontCharacter.ID;
                _characterMap.Add(c, fontCharacter);
            }
        }

        private Dictionary<char, FontChar> _characterMap;
        private FontFile _fontFile;
        private Texture2D _texture;
        public void DrawText(SpriteBatch spriteBatch, int x, int y, string text)
        {
            int dx = x;
            int dy = y;
            foreach(char c in text)
            {
                FontChar fc;
                if(_characterMap.TryGetValue(c, out fc))
                {
                    var sourceRectangle = new Rectangle(fc.X, fc.Y, fc.Width, fc.Height);
                    var position = new Vector2(dx + fc.XOffset, dy + fc.YOffset);

                    spriteBatch.Draw(_texture, position, sourceRectangle, Color.White);
                    dx += fc.XAdvance;
                }
            }
        }
    }


    [Serializable]
    [XmlRoot ( "font" )]
    public class FontFile
    {
        [XmlElement ( "info" )]
        public FontInfo Info
        {
            get;
            set;
        }

        [XmlElement ( "common" )]
        public FontCommon Common
        {
            get;
            set;
        }

        [XmlArray ( "pages" )]
        [XmlArrayItem ( "page" )]
        public List<FontPage> Pages
        {
            get;
            set;
        }

        [XmlArray ( "chars" )]
        [XmlArrayItem ( "char" )]
        public List<FontChar> Chars
        {
            get;
            set;
        }

        [XmlArray ( "kernings" )]
        [XmlArrayItem ( "kerning" )]
        public List<FontKerning> Kernings
        {
            get;
            set;
        }
    }

    [Serializable]
    public class FontInfo
    {
        [XmlAttribute ( "face" )]
        public String Face
        {
            get;
            set;
        }

        [XmlAttribute ( "size" )]
        public Int32 Size
        {
            get;
            set;
        }

        [XmlAttribute ( "bold" )]
        public Int32 Bold
        {
            get;
            set;
        }

        [XmlAttribute ( "italic" )]
        public Int32 Italic
        {
            get;
            set;
        }

        [XmlAttribute ( "charset" )]
        public String CharSet
        {
            get;
            set;
        }

        [XmlAttribute ( "unicode" )]
        public Int32 Unicode
        {
            get;
            set;
        }

        [XmlAttribute ( "stretchH" )]
        public Int32 StretchHeight
        {
            get;
            set;
        }

        [XmlAttribute ( "smooth" )]
        public Int32 Smooth
        {
            get;
            set;
        }

        [XmlAttribute ( "aa" )]
        public Int32 SuperSampling
        {
            get;
            set;
        }

        private Rectangle _Padding;
        [XmlAttribute ( "padding" )]
        public String Padding
        {
            get
            {
                return _Padding.X + "," + _Padding.Y + "," + _Padding.Width + "," + _Padding.Height;
            }
            set
            {
                String[] padding = value.Split ( ',' );
                _Padding = new Rectangle ( Convert.ToInt32 ( padding[0] ), Convert.ToInt32 ( padding[1] ), Convert.ToInt32 ( padding[2] ), Convert.ToInt32 ( padding[3] ) );
            }
        }

        private Point _Spacing;
        [XmlAttribute ( "spacing" )]
        public String Spacing
        {
            get
            {
                return _Spacing.X + "," + _Spacing.Y;
            }
            set
            {
                String[] spacing = value.Split ( ',' );
                _Spacing = new Point ( Convert.ToInt32 ( spacing[0] ), Convert.ToInt32 ( spacing[1] ) );
            }
        }

        [XmlAttribute ( "outline" )]
        public Int32 OutLine
        {
            get;
            set;
        }
    }

    [Serializable]
    public class FontCommon
    {
        [XmlAttribute ( "lineHeight" )]
        public Int32 LineHeight
        {
            get;
            set;
        }

        [XmlAttribute ( "base" )]
        public Int32 Base
        {
            get;
            set;
        }

        [XmlAttribute ( "scaleW" )]
        public Int32 ScaleW
        {
            get;
            set;
        }

        [XmlAttribute ( "scaleH" )]
        public Int32 ScaleH
        {
            get;
            set;
        }

        [XmlAttribute ( "pages" )]
        public Int32 Pages
        {
            get;
            set;
        }

        [XmlAttribute ( "packed" )]
        public Int32 Packed
        {
            get;
            set;
        }

        [XmlAttribute ( "alphaChnl" )]
        public Int32 AlphaChannel
        {
            get;
            set;
        }

        [XmlAttribute ( "redChnl" )]
        public Int32 RedChannel
        {
            get;
            set;
        }

        [XmlAttribute ( "greenChnl" )]
        public Int32 GreenChannel
        {
            get;
            set;
        }

        [XmlAttribute ( "blueChnl" )]
        public Int32 BlueChannel
        {
            get;
            set;
        }
    }

    [Serializable]
    public class FontPage
    {
        [XmlAttribute ( "id" )]
        public Int32 ID
        {
            get;
            set;
        }

        [XmlAttribute ( "file" )]
        public String File
        {
            get;
            set;
        }
    }

    [Serializable]
    public class FontChar
    {
        [XmlAttribute ( "id" )]
        public Int32 ID
        {
            get;
            set;
        }

        [XmlAttribute ( "x" )]
        public Int32 X
        {
            get;
            set;
        }

        [XmlAttribute ( "y" )]
        public Int32 Y
        {
            get;
            set;
        }

        [XmlAttribute ( "width" )]
        public Int32 Width
        {
            get;
            set;
        }

        [XmlAttribute ( "height" )]
        public Int32 Height
        {
            get;
            set;
        }

        [XmlAttribute ( "xoffset" )]
        public Int32 XOffset
        {
            get;
            set;
        }

        [XmlAttribute ( "yoffset" )]
        public Int32 YOffset
        {
            get;
            set;
        }

        [XmlAttribute ( "xadvance" )]
        public Int32 XAdvance
        {
            get;
            set;
        }

        [XmlAttribute ( "page" )]
        public Int32 Page
        {
            get;
            set;
        }

        [XmlAttribute ( "chnl" )]
        public Int32 Channel
        {
            get;
            set;
        }
    }

    [Serializable]
    public class FontKerning
    {
        [XmlAttribute ( "first" )]
        public Int32 First
        {
            get;
            set;
        }

        [XmlAttribute ( "second" )]
        public Int32 Second
        {
            get;
            set;
        }

        [XmlAttribute ( "amount" )]
        public Int32 Amount
        {
            get;
            set;
        }
    }

    public class FontLoader
    {
        public static FontFile Load ( String filename )
        {
            XmlSerializer deserializer = new XmlSerializer ( typeof ( FontFile ) );
            TextReader textReader = new StreamReader ( filename );
            FontFile file = ( FontFile ) deserializer.Deserialize ( textReader );
            textReader.Close ( );
            return file;
        }
    }
}

我稍微修改了这个类,以便以面向对象的方式实现它。以下是如何在主 Game.cs 文件中将此类与自定义字体结合使用。

对于这个例子,我有文件时间_0.png and time.fnt由 BmFonts 软件制作。它们是我想使用的 Avenir Next Condensed 字体的结果。

public class Game1 : Game
{
    // Graphic variables used for the game to work
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;
    BmFont fontTime;



    public Game1 ()
    {
        graphics = new GraphicsDeviceManager (this);
        Content.RootDirectory = "Content";              
        graphics.IsFullScreen = true;       
    }

    protected override void LoadContent ()
    {
        // Create a new SpriteBatch, which can be used to draw textures.
        spriteBatch = new SpriteBatch (GraphicsDevice);
        fontTime = new BmFont ("time.fnt", "time_0.png", this.Content);
    }

    protected override void Draw (GameTime gameTime)
    {
        graphics.GraphicsDevice.Clear (Color.CornflowerBlue);



        spriteBatch.Begin();
            fontTime.draw (DateTime.Now.ToString("HH mm"), new Vector2 (100, 50)), spriteBatch);
        spriteBatch.End();
        base.Draw (gameTime);
    }



}

就这样吧。现在你应该一切都好了,看看它对你自己有用。 困难的部分是调整你的字体大小,因为你需要为你想要的每种字体大小生成一个文件。

尽管如此,这种技术为您提供了直接嵌入字体的可能性,而不需要最终用户在他的计算机上安装它(这曾经会崩溃)。

享受, 凯文

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Monogame 中使用 BMP 图像作为字体 的相关文章

  • 谁能建议我一种在 C++ 中分割名称的简单方法

    我一直在尝试将名称分为名字和姓氏 但我确信我的实现就简单性而言并不是最好的 string name John Smith string first string last name name find getting lastname fo
  • 尚未注册类型“IServiceProviderFactory[Autofac.ContainerBuilder]”的服务

    当运行以下命令添加数据库迁移脚本时 出现以下错误 dotnet ef migrations add InitialCreate v o Migrations context MyContext 访问 Microsoft Extensions
  • 通过 SocketCAN 进行 boost::asio

    我正在考虑利用升压阿西奥 http www boost org doc libs 1 49 0 doc html boost asio html从a读取数据套接字CAN http en wikipedia org wiki SocketCA
  • FileStream 构造函数和默认缓冲区大小

    我们有一个使用 NET 4 用 C 编写的日志记录类 我想添加一个构造函数参数 该参数可以选择设置文件选项 WriteThrough http msdn microsoft com en us library system io fileo
  • 如何在 C# / .NET 中创建内存泄漏[重复]

    这个问题在这里已经有答案了 可能的重复 托管代码中是否可能存在内存泄漏 特别是 C 3 0 https stackoverflow com questions 6436620 is it possible to have a memory
  • 平滑滚动.net 表单

    您好 我正在 net 中使用表单 并且在运行时动态添加大量链接标签 我将这些链接标签添加到面板并将该面板添加到 winform 当链接标签的数量增加时 表单会显示一个自动滚动条 垂直 现在 当我使用自动滚动向下滚动时 表单在滚动时不会更新其
  • 我如何在 C# .NET(win7 手机)中使用“DataContractJsonSerializer”读入“嵌套”Json 文件?

    我有一个问题 如果我的 json 文件看起来像这样 Numbers 45387 Words 空间桶 我可以很好地阅读它 但是如果它看起来像这样 Main Numbers 45387 Words 空间桶 某事 数字 12345 单词 克兰斯基
  • 与 Qt 项目的静态链接

    我有一个在 Visual Studio 2010 Professional 中构建的 Qt 项目 但是 当我运行它 在调试或发布模式下 时 它会要求一些 Qt dll 如果我提供 dll 并将它们放入 System32 中 它就可以工作 但
  • 指向特征矩阵的指针数组

    我在代码中使用 Eigen 的 MatrixXd 矩阵 在某个时刻我需要一个 3D 矩阵 由于 Eigen 没有三维矩阵类型 因为它仅针对线性代数进行了优化 因此我创建了一个 MatrixXd 类型的指针数组 Eigen MatrixXd
  • 找不到 assimp-vc140-mt.dll ASSIMP

    我已经从以下位置下载了 Assimp 项目http assimp sourceforge net main downloads html http assimp sourceforge net main downloads html Ass
  • fprintf() 线程安全吗?

    我正在为野人就餐问题的某些变量编写一个 C 解决方案 现在 我创建线程 每个线程都将 FILE 获取到同一个调试文件 在线程内我正在使用 fprintf 进行一些打印 打印的语句不受任何类型的互斥锁等保护 我没有在调试文件中观察到任何交错行
  • 单例模式和 std::unique_ptr

    std unique ptr唯一地控制它指向的对象 因此不使用引用计数 单例确保利用引用计数只能创建一个对象 那么会std unique ptr与单例执行相同 单例确保只有一个实例属于一种类型 A unique ptr确保只有一个智能指针到
  • std::forward_as_tuple 将参数传递给 2 个构造函数

    我想传递多个参数以便在函数内构造两个对象 以同样的方式std pair
  • 运行选定的代码生成器时出错:“未将对象引用设置到对象的实例。”错误?

    我已经尝试了所有解决方案 例如修复 VS 2013 但没有用 当您通过右键单击控制器文件夹来创建控制器并添加控制器时 然后右键单击新创建的控制器的操作并选择添加视图 当我尝试创建视图时 就会发生这种情况 它不是一个新项目 而是一个现有项目
  • 如何分析组合的 python 和 c 代码

    我有一个由多个 python 脚本组成的应用程序 其中一些脚本正在调用 C 代码 该应用程序现在的运行速度比以前慢得多 因此我想对其进行分析以查看问题所在 是否有工具 软件包或只是一种分析此类应用程序的方法 有一个工具可以将 python
  • IEnumerable.Except 不起作用,那么我该怎么办?

    我有一个 linq to sql 数据库 非常简单 我们有 3 个表 项目和用户 有一个名为 User Projects 的连接表将它们连接在一起 我已经有了一个获得的工作方法IEnumberable
  • 使用restsharp序列化对象并将其传递给WebApi而不是序列化列表

    我有一个看起来像的视图模型 public class StoreItemViewModel public Guid ItemId get set public List
  • 在简单注入器中解析具有自定义参数的类

    我正在使用以下命令创建 WPF MVVM 应用程序简易注射器作为 DI 容器 现在 当我尝试从简单注入器解析视图时遇到一些问题 因为我需要在构造时将参数传递到构造函数中 而不是在将视图注册到容器时 因此这不是适用的 简单注入器将值传递到构造
  • C++0x中disable_if在哪里?

    Boost 两者都有enable if and disable if 但 C 0x 似乎缺少后者 为什么它被排除在外 C 0x 中是否有元编程工具允许我构建disable if按照enable if 哦 我刚刚注意到std enable i
  • 使我的 COM 程序集调用异步

    我刚刚 赢得 了在当前工作中维护用 C 编码的遗留库的特权 这个dll 公开使用 Uniface 构建的大型遗留系统的方法 除了调用 COM 对象之外别无选择 充当此遗留系统与另一个系统的 API 之间的链接 在某些情况下 使用 WinFo

随机推荐