簡體   English   中英

BitmapFont (libgdx) 的自定義角色

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM