【问题标题】:Center text when using BmFont (MonoGame)使用 BmFont (MonoGame) 时居中文本
【发布时间】:2016-01-13 18:59:38
【问题描述】:

在使用 BmFont 绘图时,有没有办法使文本居中?我正在使用这里的代码:Using a BMP image as font in Monogame

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

添加/更改代码:

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

【问题讨论】:

  • 我认为你在 draw 中缺少原点,origin 也应该在文本的中心。 FC.Width/2FC.Height/2
  • @DavorMlinaric 它在这里绘制文本的方式是逐个字符,而不是一次全部绘制。那么有没有办法在绘制一次之前先将所有内容绘制到缓冲区?这样我就可以使用原点来居中。
  • 啊,是的,没错。您可以通过SpriteBatch.DrawString 绘制全文
  • @DavorMlinaric 我不能,因为我没有使用SpriteFont。我正在使用自定义 BmFont 类(OP 中的链接),它可以使用自定义字体。

标签: vb.net xna monogame


【解决方案1】:

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

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

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

首先,像往常一样加载您的位图字体SpriteFont。请注意,要使其正常工作,您需要使用 MonoGame Pipeline 工具设置 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 方法中返回它。这种方法的问题是,如果你调用GetTextLength before DrawText 你会得到错误的值。

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

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

DrawText(_spriteBatch, x, y, text)

不幸的是,这将起作用,因为 GetTextLength 直到 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

【讨论】:

  • 成功了,谢谢!我不得不通过渲染器和 BmFont 类两次返回值,然后使用相同的文本来计算长度,但结果都很好。
  • 很高兴你能成功。请接受我的回答。谢谢:)
猜你喜欢
  • 2022-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-24
  • 2013-10-12
  • 2023-03-23
  • 1970-01-01
  • 2018-10-30
相关资源
最近更新 更多