MonoGame - 适当的 SpriteFont 缩放
MonoGame - proper SpriteFont scaling
我正在为我的游戏制作 GUI,但现在我被困在动画上。我需要在鼠标悬停在字体上时放大字体,在鼠标悬停时缩小字体。这是我的代码:
// Update()
if (!IsDisabled)
{
elapsedSecondsFast = (float)gameTime.ElapsedGameTime.TotalSeconds * 3;
if (Size.Contains(InputManager.MouseRect))
{
scale += elapsedSecondsFast;
if (scale >= 1.05f) scale = 1.05f;
}
else
{
scale -= elapsedSecondsFast;
if (scale <= 1.0f) scale = 1.0f;
}
}
// Draw()
if ((PrimaryFont != null) && (SecondaryFont != null) && (!string.IsNullOrEmpty(Text)))
{
if (IsHovered) TextOutliner.DrawBorderedText(spriteBatch, SecondaryFont, Text, new Vector2(TextRectangle.X, TextRectangle.Y), ForeColor, 0.0f, new Vector2((SecondaryFont.MeasureString(Text).X / 2 * scale - SecondaryFont.MeasureString(Text).X / 2), (SecondaryFont.MeasureString(Text).Y / 2 * scale - SecondaryFont.MeasureString(Text).Y / 2)), scale);
else TextOutliner.DrawBorderedText(spriteBatch, PrimaryFont, Text, new Vector2(TextRectangle.X, TextRectangle.Y), ForeColor, 0.0f, new Vector2(PrimaryFont.MeasureString(Text).X / 2 * scale - PrimaryFont.MeasureString(Text).X / 2, (PrimaryFont.MeasureString(Text).Y / 2 * scale - PrimaryFont.MeasureString(Text).Y / 2)), scale);
}
以上是我的Button
class继承的GUIElement
class。让我简要解释一下我的代码:
PrimaryFont
和 SecondaryFont
是 2 个使用相同的 SpriteFonts
字体,但大小不同。这为我提供了我需要的比例 up/down 动画,而不会模糊我的 PrimaryFont
.
TextRectangle
和 Size
是 2 个不同的矩形。因为我的按钮有纹理和文本,所以我决定不在纹理文件上绘制文本,而是让游戏将我的文本放置在纹理上以达到 "fake" 效果。所以 TextRectangle
是按钮文本的大小和位置,Size
是按钮纹理的大小和位置。 TextRectangle
在 Button texture
的 center
中有它的 center point
。到目前为止,我一直在使用幻数来实现这一目标。这就是问题的核心所在。
- 你可以看到我的
origin
,我把它传给了我的TextOutliner
class的DrawBorderedText
方法。属性的顺序与 spriteBatch.DrawString()
调用相同,只是没有 SpriteEffects
和 layerDepth
.
问题
由于我正在缩放字体(origin = center
我认为)它将不再位于按钮的中心。因为我一直在使用幻数将未缩放的文本定位在按钮纹理的中心,所以我不想被迫对缩放文本做同样的事情。我正在寻找一种算法,无论文本是否缩放,始终将文本定位在我的 270x72 纹理的中间,同时保持上面显示的 scale
动画,每个实例Button
class。最好让它的原点在中心。
编辑
所以我应该这样画:
if (IsHovered) TextOutliner.DrawBorderedText(spriteBatch, SecondaryFont, Text, new Vector2(TextRectangle.X, TextRectangle.Y), ForeColor, 0.0f, new Vector2((SecondaryFont.MeasureString(Text).X / 2), (SecondaryFont.MeasureString(Text).Y / 2)), scale);
else TextOutliner.DrawBorderedText(spriteBatch, PrimaryFont, Text, new Vector2(TextRectangle.X, TextRectangle.Y), ForeColor, 0.0f, new Vector2(PrimaryFont.MeasureString(Text).X / 2, (PrimaryFont.MeasureString(Text).Y / 2)), scale);
然后在 btn.Size.Width / 2, btn.Size.Height / 2, (int)MainGame.GameFontLarge.MeasureString("Play").X / 2, (int)MainGame.GameFontLarge.MeasureString("Play").Y / 2
处绘制按钮的文本
所以我最终自己找到了算法,并最终消除了对文本位置使用幻数的需要。这是我的技巧:
TextOutliner.DrawBorderedText(spriteBatch, Font, Text, new Vector2(Size.X + ((Size.Width - Font.MeasureString(Text).X) / 2), Size.Y + ((Size.Height - Font.MeasureString(Text).Y)) / 2), ForeColor, 0.0f, new Vector2((Font.MeasureString(Text).X / 2 * scale - Font.MeasureString(Text).X / 2), (Font.MeasureString(Text).Y / 2 * scale - Font.MeasureString(Text).Y / 2)), scale);
我无法按照@LibertyLocked 的建议从 origin
等式中取出 scale
,因为鼠标悬停时字体是从左上角开始缩放的,而不是我想要的中心
我正在为我的游戏制作 GUI,但现在我被困在动画上。我需要在鼠标悬停在字体上时放大字体,在鼠标悬停时缩小字体。这是我的代码:
// Update()
if (!IsDisabled)
{
elapsedSecondsFast = (float)gameTime.ElapsedGameTime.TotalSeconds * 3;
if (Size.Contains(InputManager.MouseRect))
{
scale += elapsedSecondsFast;
if (scale >= 1.05f) scale = 1.05f;
}
else
{
scale -= elapsedSecondsFast;
if (scale <= 1.0f) scale = 1.0f;
}
}
// Draw()
if ((PrimaryFont != null) && (SecondaryFont != null) && (!string.IsNullOrEmpty(Text)))
{
if (IsHovered) TextOutliner.DrawBorderedText(spriteBatch, SecondaryFont, Text, new Vector2(TextRectangle.X, TextRectangle.Y), ForeColor, 0.0f, new Vector2((SecondaryFont.MeasureString(Text).X / 2 * scale - SecondaryFont.MeasureString(Text).X / 2), (SecondaryFont.MeasureString(Text).Y / 2 * scale - SecondaryFont.MeasureString(Text).Y / 2)), scale);
else TextOutliner.DrawBorderedText(spriteBatch, PrimaryFont, Text, new Vector2(TextRectangle.X, TextRectangle.Y), ForeColor, 0.0f, new Vector2(PrimaryFont.MeasureString(Text).X / 2 * scale - PrimaryFont.MeasureString(Text).X / 2, (PrimaryFont.MeasureString(Text).Y / 2 * scale - PrimaryFont.MeasureString(Text).Y / 2)), scale);
}
以上是我的Button
class继承的GUIElement
class。让我简要解释一下我的代码:
PrimaryFont
和SecondaryFont
是 2 个使用相同的 SpriteFonts 字体,但大小不同。这为我提供了我需要的比例 up/down 动画,而不会模糊我的PrimaryFont
.TextRectangle
和Size
是 2 个不同的矩形。因为我的按钮有纹理和文本,所以我决定不在纹理文件上绘制文本,而是让游戏将我的文本放置在纹理上以达到 "fake" 效果。所以TextRectangle
是按钮文本的大小和位置,Size
是按钮纹理的大小和位置。TextRectangle
在Button texture
的center
中有它的center point
。到目前为止,我一直在使用幻数来实现这一目标。这就是问题的核心所在。- 你可以看到我的
origin
,我把它传给了我的TextOutliner
class的DrawBorderedText
方法。属性的顺序与spriteBatch.DrawString()
调用相同,只是没有SpriteEffects
和layerDepth
.
问题
由于我正在缩放字体(origin = center
我认为)它将不再位于按钮的中心。因为我一直在使用幻数将未缩放的文本定位在按钮纹理的中心,所以我不想被迫对缩放文本做同样的事情。我正在寻找一种算法,无论文本是否缩放,始终将文本定位在我的 270x72 纹理的中间,同时保持上面显示的 scale
动画,每个实例Button
class。最好让它的原点在中心。
编辑
所以我应该这样画:
if (IsHovered) TextOutliner.DrawBorderedText(spriteBatch, SecondaryFont, Text, new Vector2(TextRectangle.X, TextRectangle.Y), ForeColor, 0.0f, new Vector2((SecondaryFont.MeasureString(Text).X / 2), (SecondaryFont.MeasureString(Text).Y / 2)), scale);
else TextOutliner.DrawBorderedText(spriteBatch, PrimaryFont, Text, new Vector2(TextRectangle.X, TextRectangle.Y), ForeColor, 0.0f, new Vector2(PrimaryFont.MeasureString(Text).X / 2, (PrimaryFont.MeasureString(Text).Y / 2)), scale);
然后在 btn.Size.Width / 2, btn.Size.Height / 2, (int)MainGame.GameFontLarge.MeasureString("Play").X / 2, (int)MainGame.GameFontLarge.MeasureString("Play").Y / 2
所以我最终自己找到了算法,并最终消除了对文本位置使用幻数的需要。这是我的技巧:
TextOutliner.DrawBorderedText(spriteBatch, Font, Text, new Vector2(Size.X + ((Size.Width - Font.MeasureString(Text).X) / 2), Size.Y + ((Size.Height - Font.MeasureString(Text).Y)) / 2), ForeColor, 0.0f, new Vector2((Font.MeasureString(Text).X / 2 * scale - Font.MeasureString(Text).X / 2), (Font.MeasureString(Text).Y / 2 * scale - Font.MeasureString(Text).Y / 2)), scale);
我无法按照@LibertyLocked 的建议从 origin
等式中取出 scale
,因为鼠标悬停时字体是从左上角开始缩放的,而不是我想要的中心