![](/img/trans.png)
[英]Add BitmapFont.draw from a Custom Actor to a ScrollPane/Table
[英]Custom actor for BitmapFont (libgdx)
我花了幾個令人沮喪的小時試圖實現(我認為會是)一個簡單的FontActor
類。
這個想法是使用提供的BitmapFont
在特定位置繪制文本。 這么多,我已經成功了。 但是,我正在努力根據呈現的文本計算演員的寬度/高度。
(使用 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
類實現中,我在每個窗口調整大小時重新調整我的字體,以便它們不會變得“平滑”或拉伸:
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
調用是錯誤的。
初始窗口:
使窗口水平變大后:
例如,如果我然后水平縮放我的窗口(這對世界大小沒有影響,因為我使用的是FitViewport
),字體看起來是正確的,正如預期的那樣。 然而,從draw()
返回的layout.width
值發生了變化,即使屏幕上的文本大小沒有改變。 經過調查,我意識到這是由於我使用了setScale
,但簡單地將寬度除以 x 縮放因子並不能糾正錯誤。 再一次,如果我刪除我的setScale
調用,數字是有道理的,但字體現在被壓扁了!
我嘗試的另一個策略是將寬度/高度轉換為屏幕坐標,然后使用相關的項目/取消項目方法來獲取世界坐標中的寬度和高度。 這遇到了圖像中顯示的相同問題。
我怎樣才能解決我的數學問題?
或者,是否有更智能/更簡單的方法來實現所有這些? (不,我不想要Label
,我只想要一個文本演員。)
一個問題是我的縮放代碼。 修復是更改相機更新如下:
context.inject<OrthographicCamera>().setToOrtho(false, stage.viewport.screenWidth.toFloat(), stage.viewport.screenHeight.toFloat())
這導致我的文本相機與世界視口相機相匹配。 我使用整個屏幕進行計算,因此拉伸。
由於同樣的原因,我的scaleX
/ Y
計算是錯誤的。 在糾正了這兩個錯誤計算之后,我有一個很好的縮放FontActor
,在世界坐標中具有正確的邊界。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.