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

Using a BMP image as font in Monogame

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

我在网上看到了 Microsoft 提供的解决方案,但是在尝试 运行 这个解决方案时,我一直收到内容加载异常。

似乎这曾经适用于 XNA,但可能不再适用于 Monogame。

我想要自己的自定义字体,因为这种字体不会预装在客户端的电脑上。

我已经看过来自 SpriteFont Converter 的 XNB 文件,但这不是我想要的解决方案。

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

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

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

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

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

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

// ---- AngelCode BmFont XML serializer ----------------------
// ---- By DeadlyDan @ deadlydan@gmail.com -------------------
// ---- 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;
        }
    }
}

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

对于这个例子,我有文件 time_0.pngtime.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);
    }



}

给你。现在你应该一切都好,看看它为你自己工作。 困难的部分是调整字体大小,因为您需要为所需的每种字体大小生成一个文件。

尽管如此,此技术为您提供了直接嵌入字体的可能性,而无需最终用户在其计算机上安装它(过去常常崩溃)。

享受, 凯文