gpt4 book ai didi

java - BitmapFont 的自定义 actor (libgdx)

转载 作者:行者123 更新时间:2023-12-02 08:58:07 25 4
gpt4 key购买 nike

我花了几个令人沮丧的小时来尝试实现(我认为的)一个简单的 FontActor 类。

这个想法是使用提供的 BitmapFont 在特定位置绘制文本。我已经做到了这么多。但是,我正在努力根据渲染的文本计算 Actor 的宽度/高度。

(使用FitViewport进行测试)

open class FontActor<T : BitmapFont>(val font: T, var text: CharSequence = "") : GameActor() {
val layout = Pools.obtain(GlyphLayout::class.java)!!

companion object {
val identity4 = Matrix4().idt()
val distanceFieldShader: ShaderProgram = DistanceFieldFont.createDistanceFieldShader()
}

override fun draw(batch: Batch?, parentAlpha: Float) {
if (batch == null) return
batch.end()

// grab ui camera and backup current projection
val uiCamera = Game.context.inject<OrthographicCamera>()
val prevTransform = batch.transformMatrix
val prevProjection = batch.projectionMatrix
batch.transformMatrix = identity4
batch.projectionMatrix = uiCamera.combined
if (font is DistanceFieldFont) batch.shader = distanceFieldShader

// the actor has pos = x,y in local coords, but we need UI coords
// start by getting group -> stage coords (world)
val coords = Vector3(localToStageCoordinates(Vector2(0f, 0f)), 0f)

// world coordinate destination -> screen coords
stage.viewport.project(coords)

// screen coords -> font camera world coords
uiCamera.unproject(coords,
stage.viewport.screenX.toFloat(),
stage.viewport.screenY.toFloat(),
stage.viewport.screenWidth.toFloat(),
stage.viewport.screenHeight.toFloat())

// adjust position by cap height so that bottom left of text aligns with x, y
coords.y = uiCamera.viewportHeight - coords.y + font.capHeight

/// TODO: use BitmapFontCache to prevent this call on every frame and allow for offline bounds calculation
batch.begin()
layout.setText(font, text)
font.draw(batch, layout, coords.x, coords.y)
batch.end()

// viewport screen coordinates -> world coordinates
setSize((layout.width / stage.viewport.screenWidth) * stage.width,
(layout.height / stage.viewport.screenHeight) * stage.height)

// restore camera
if (font is DistanceFieldFont) batch.shader = null
batch.projectionMatrix = prevProjection
batch.transformMatrix = prevTransform
batch.begin()
}
}

在我的父 Screen 类实现中,我在每次调整窗口大小时重新缩放字体,这样它们就不会变得“平滑”或拉伸(stretch):

override fun resize(width: Int, height: Int) {
stage.viewport.update(width, height)
context.inject<OrthographicCamera>().setToOrtho(false, width.toFloat(), height.toFloat())

// rescale fonts
scaleX = width.toFloat() / Config.screenWidth
scaleY = height.toFloat() / Config.screenHeight
val scale = minOf(scaleX, scaleY)
gdxArrayOf<BitmapFont>().apply {
Game.assets.getAll(BitmapFont::class.java, this)
forEach { it.data.setScale(scale) }
}
gdxArrayOf<DistanceFieldFont>().apply {
Game.assets.getAll(DistanceFieldFont::class.java, this)
forEach { it.data.setScale(scale) }
}
}

在您调整窗口大小之前,此方法可以正常工作并且看起来很棒。调整大小后,字体看起来很好,并且会根据窗口的相对大小自动调整,但是 FontActor 的大小错误,因为我对 setSize 的调用是错误的。

初始窗口:

before horizontal stretch

使窗口水平变大后:

after horizontal stretch

例如,如果我随后水平缩放窗口(这对世界大小没有影响,因为我使用的是 FitViewport),则字体看起来是正确的,正如预期的那样。但是,即使屏幕上的文本大小没有改变,从 draw() 返回的 layout.width 值也会发生变化。经过调查,我意识到这是由于我使用了 setScale,但简单地将宽度除以 x 缩放因子并不能纠正错误。再说一次,如果我删除 setScale 调用,这些数字是有意义的,但字体现在被压扁了!

我尝试的另一个策略是将宽度/高度转换为屏幕坐标,然后使用相关的project/unproject方法来获取世界坐标中的宽度和高度。这与图像中显示的问题相同。

如何解决我的数学问题?

或者,是否有更智能/更简单的方法来实现这一切?(不,我不需要 Label,我只想要一个文本 Actor 。)

最佳答案

一个问题是我的缩放代码。修复方法是更改​​相机更新,如下所示:

context.inject<OrthographicCamera>().setToOrtho(false, stage.viewport.screenWidth.toFloat(), stage.viewport.screenHeight.toFloat())

这使得我的文本相机与世界视口(viewport)相机相匹配。我使用整个屏幕进行计算,因此进行了拉伸(stretch)。

出于同样的原因,我的 scaleX/Y 计算也是错误的。纠正这两个错误计算后,我得到了一个可以很好缩放的 FontActor,并且在世界坐标中具有正确的边界。

关于java - BitmapFont 的自定义 actor (libgdx),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60367268/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com