使用 BmFont (MonoGame) 时居中文本

Center text when using BmFont (MonoGame)

有没有办法在使用 BmFont 绘图时使文本居中?我正在使用此处的代码:

我所做的唯一代码更改是我向 DrawText 添加了一个 _TextWidth int,它使用 DX - X 获取文本长度,然后使用函数 GetTextLength 来return 它到按钮 class,然后它使用 ((button width - text width) / 2) 获取文本的起点,并将其居中。但是,似乎存在一些问题,文本不会使用自己的文本宽度居中,而是使用下一个按钮的文本宽度。返回文本宽度很好,但由于某些原因,当它在屏幕上绘制时,它总是错误的值。

Added/changed代码:

Public Sub DrawText(ByVal spritebatch As SpriteBatch, ByVal X As Integer, ByVal Y As Integer, ByVal Text As String)
    Dim DX As Integer = X
    Dim DY As Integer = Y
    For Each C As Char In Text
        Dim FC As New FontChar
        If _CharacterMap.TryGetValue(C, FC) Then
            Dim sourceRectangle = New Rectangle(FC.X, FC.Y, FC.Width, FC.Height)
            Dim position = New Vector2(DX + FC.XOffset, DY + FC.YOffset)
            spritebatch.Draw(_Texture, position, sourceRectangle, Color.White)
            DX += FC.XAdvance
        End If
    Next
    _TextWidth = DX - X
End Sub

Public Function GetTextLength() As Integer
    Return _TextWidth
End Function

截图:

Uncentered text, which could be centered if the right values were used for each button

MonoGame.Extended 有一个 BMFont 渲染器的实现,对旧教程进行了一些改进,包括 SpriteBatch.DrawString 扩展。

我还有一个关于 my blog 的关于如何设置它的教程。但是,它不涉及将文本居中,所以我现在将讨论它。

如果选择使用MonoGame.Extended,应该可以得到如下居中效果

首先,像往常一样加载位图字体 SpriteFont。请注意,要使其正常工作,您需要使用 MonoGame 管道工具设置 MonoGame.Extended。

_bitmapFont = Content.Load(Of BitmapFont)("my-font")

接下来,在您的Draw方法中,您可以使用GetStringRectangle测量文本的大小,然后计算出正确的位置。像这样的东西(对不起,如果我的 VB.net 有点生疏):

Dim text = "Start game"
Dim textRectangle = _bitmapFont.GetStringRectangle(text, Vector2.Zero)
Dim textOffset = buttonWidth / 2F - textRectangle.Width / 2F

_spriteBatch.DrawString(_bitmapFont, text, buttonPosition + textOffset, Color.White)

当然,如果您不想这样做,也可以不使用 MonoGame.Extended。我认为您的代码只是有一个错误,因为它看起来像是打算做 MonoGame.Extended 无论如何都会做的事情。

据我所知,您的代码在 DrawText 方法中计算文本的宽度,并在 GetTextLength 方法中 return 计算它。这种方法的问题在于,如果您在 DrawText 之前调用 GetTextLength ,您将得到错误的值。

我假设你正在做这样的事情:

Dim y = buttonPos.Y
Dim x = buttonPos.X - buttonWidth / 2F - GetTextLength() / 2F

DrawText(_spriteBatch, x, y, text)

不幸的是,这 不会 起作用,因为 GetTextLength 之前不会 return 正确的值DrawText 运行。

解决方法当然是正确计算文本长度,而不是在绘制操作期间将其存储在成员变量中。

Public Function GetTextLength(ByVal Text As String) As String
    Dim TextWidth As Integer
    For Each C As Char In Text
    Dim FC As New FontChar
    If _CharacterMap.TryGetValue(C, FC) Then
        TextWidth += FC.XAdvance
    End If
    Next
    GetTextLength = TextWidth
End Sub