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

时间:2015-04-05 01:11:52

标签: c# fonts monogame

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

我已经看到微软在线提供了一个解决方案,但在尝试运行此解决方案时,我一直在获取内容加载异常。

似乎这曾经与XNA一起使用,但Monogame可能不再适用。

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

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

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

1 个答案:

答案 0 :(得分:2)

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

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

使用此软件,您将收到Font输出为2个文件:

  1. .fnt文件,用于纹理中的图案
  2. .png文件,即实际字符。
  3. 为了使这些文件与你的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);
        }
    
    
    
    }
    

    你去吧。现在你应该都很好,看它适合自己。 困难的部分将使用你的字体大小,因为你需要为你想要的每种字体大小生成一个文件。

    尽管如此,这种技术可以让您直接嵌入字体,而无需最终用户将其安装到计算机上(过去常常崩溃)。

    享受, 凯文