Here is a start.
I just loaded the image itself thru the content manager instead of from file i figured its not a big deal. I see you know how to load it from file anyways or you can convert the whole thing at the end to self load with that github project i posted.
I didn’t handle transparency. (plenty of people can help with that too if you have a hard time).
Couple notes…
-
The class that does the work generically… MonoSpacedFont
-
I made this class to specifically test the image you posted … MakeTheFont_fnt_null , it just calls to the static monospacedfont class and uses its method to make the image into a font.
-
I don’t know what the name of that font in the image is supposed to be ?
So i just used the name of the png for the texture that you named fnt_null and then named the one class similarily to reflect what it loads, not a very good name, but anyways. -
Your image isn’t in the right regional order so i couldn’t use the character range directly. so in the public class MakeTheFont_fnt_null and method GetFont(Game game)
I left a couple notes for you other wise that method would be just 2 or 3 lines.var chars = MonoSpacedFont.RangeToCharList(32, 96, new List());
return MonoSpacedFont.CreateMonoSpacedFont(“fnt_null”, game, chars, 16, 6, 0, null);
instead i left notes and made a alternate way to set the characters.
// // You messed this up, the character order in the image doesn't match utf16 character order. // //chars = MonoSpacedFont.RangeToCharList(32, 96, chars);
The class method GetFont(Game game) for game when you call to it in load content just use the (this) parameter you can see how its loaded in the actual game1 content method.
Here is the game one file there is static class that is has the primary method.
The other class uses it for a specific image in the content folder to return a spritefont.
Whole thing can be copy pasted over a game1 class change the namespace to yours then add your image in the content pipeline as named. It should run the same as shown in the image i posted.
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace GuysMonoSpacedFont
{
public class Game1 : Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
SpriteFont myfont;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
var m = new MakeTheFont_fnt_null();
myfont = m.GetFont(this);
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
spriteBatch.DrawString(myfont, "HELLO WORLD", new Vector2(100, 100), Color.White, 0f, Vector2.Zero, 5, SpriteEffects.None, 0);
string dup =
" !" + '"' + "#$%&'()*+,-./" +
"0123456789:;<=>?" +
"@ABCDEFGHIJKLMNO" +
"PQRSTUVWXYZ[" + "\\" + "]^_" +
"`abcdefghijklmno" +
"pqrstuvwxyz{|}~";
spriteBatch.DrawString(myfont, dup, new Vector2(100, 200), Color.White, 0f, Vector2.Zero, 5, SpriteEffects.None, 0);
spriteBatch.End();
base.Draw(gameTime);
}
}
public class MakeTheFont_fnt_null
{
public SpriteFont GetFont(Game game)
{
var chars = new List<char>();
//
// You messed this up, the character order in the image doesn't match utf16 character order.
//
//chars = MonoSpacedFont.RangeToCharList(32, 96, chars);
//
// directly inputed
// i cant tell what that last letter is so i skipped it.
//
chars = MonoSpacedFont.StringToCharList
(
" !" + '"' + "#$%&'()*+,-./" +
"0123456789:;<=>?" +
"@ABCDEFGHIJKLMNO" +
"PQRSTUVWXYZ[" + "\\" + "]^_" +
"`abcdefghijklmno" +
"pqrstuvwxyz{|}~"
, chars
);
return MonoSpacedFont.CreateMonoSpacedFont("fnt_null", game, chars, 16, 6, 0, null);
}
}
public static class MonoSpacedFont
{
public static SpriteFont CreateMonoSpacedFont(string imageName, Game game, List<char> characters, int rows, int columns, int extraSpaceBetweenCharacters, char? defaultchar)
{
var tex = game.Content.Load<Texture2D>(imageName);
int W = tex.Width / rows;
int H = tex.Height / columns;
List<Rectangle> bounds = new List<Rectangle>();
List<Rectangle> cropping = new List<Rectangle>();
List<Vector3> kerning = new List<Vector3>();
for (int y = 0; y < columns; y++)
{
for (int x = 0; x < rows; x++)
{
var posx = x * W;
var posy = y * H;
bounds.Add(new Rectangle(posx, posy, W, H));
cropping.Add(new Rectangle(0, 0, 0, 0));
kerning.Add(new Vector3(0, W, 0));
}
}
return new SpriteFont
(
tex,
bounds,
cropping,
characters,
H,
extraSpaceBetweenCharacters,
kerning,
defaultchar
);
}
public static List<char> StringToCharList(string s, List<char> charlist)
{
foreach (char c in s)
charlist.Add(c);
return charlist;
}
public static List<char> RangeToCharList(int start, int end, List<char> charlist)
{
for (int i = start; i < end; i++)
charlist.Add((char)i);
return charlist;
}
}
}
Once you get the kinks out. You could use my github project i posted at the begining to transform the finished result into a loadable class file if you wanted to as well its pretty straightforward just give it the spritefont you just made and it will turn it all into a class that self creates the whole spritefont.
