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

3
有没有办法使用BMP图像加载自定义字体?
我在微软的网站上见过提供此功能的解决方案,但是尝试运行此解决方案时,我一直遇到内容加载异常。
看起来这曾经可以在XNA中使用,但现在在Monogame中可能不再适用。
我想要自己的自定义字体,因为这种字体不会预先安装在客户机上。
我已经查看了SpriteFont Converter生成的XNB文件,但那不是我想要的解决方案。
感谢任何帮助。
1个回答

2
经过长时间的研究,我最终在网上找到了一个解决方案。以下是教程链接:http://www.craftworkgames.com/blog/tutorial-bmfont-rendering-with-monogame/ 这种方法需要您下载一个名为bmFont的软件:http://www.angelcode.com/products/bmfont/ 使用该软件,您将获得2个文件输出:
1. .fnt文件,用于纹理中的图案 2. .png文件,即实际字符。
为了使这些文件与您的monoproject(也可能适用于XNA)配合使用,您需要将此类添加到您的项目中(注意:您需要更改命名空间):
// ---- 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;
        }
    }
}

我稍微修改了这个类,以面向对象的方式实现。以下是如何在您的主Game.cs文件中使用此类与您的自定义字体。
例如,我有由BmFonts软件生成的文件time_0.png和time.fnt。它们是我想要使用的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);
    }



}

好了,现在你应该没问题了,可以亲自看到它的工作方式。 难点在于调整字体大小,因为你需要为每个想要的字体大小生成一个文件。

虽然这种技术使你有可能直接嵌入字体,而不需要最终用户安装在计算机上(以前会导致崩溃)。

享受吧, 凯文


Craftwork Games已经倒闭。 - John Lord

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接