You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ShapeRenderer绘制Actor拖拽时边界偏移及缩放异常问题求助

修复ShapeRenderer与Batch变换矩阵不匹配的问题

你猜的没错,这个问题确实是因为ShapeRenderer没有同步Stage和Actor的变换矩阵导致的。Stage会自动处理SpriteBatch的投影和变换,但ShapeRenderer是独立的,必须手动让它和当前Actor的变换保持一致,才能让调试线和实际Actor的边界对齐。

下面是具体的修复方案,结合你的代码场景来调整:

1. 在Actor的draw方法中同步矩阵

在你的Bubble类的draw方法里,不要直接使用ShapeRenderer绘制,而是先同步Batch的矩阵到ShapeRenderer,再进行绘制。还要注意状态的保存和恢复,避免影响后续渲染:

class Bubble : Actor() {
    // 可以把ShapeRenderer作为参数传入,或者通过Stage获取
    private lateinit var sr: ShapeRenderer

    fun setShapeRenderer(sr: ShapeRenderer) {
        this.sr = sr
    }

    override fun draw(batch: Batch, parentAlpha: Float) {
        // 先暂停Batch,避免状态冲突
        batch.end()

        // 同步ShapeRenderer的矩阵到当前Batch的状态
        sr.projectionMatrix = batch.projectionMatrix
        sr.transformMatrix = batch.transformMatrix
        sr.setColor(color.r, color.g, color.b, color.a * parentAlpha)

        sr.begin(ShapeRenderer.ShapeType.Line)
        // 绘制圆形边界:要基于Actor的实际位置、尺寸和缩放计算
        val actualRadius = (width * scaleX) / 2f
        val centerX = x + originX * scaleX
        val centerY = y + originY * scaleY
        sr.circle(centerX, centerY, actualRadius)
        sr.end()

        // 恢复Batch状态,继续后续渲染
        batch.begin()

        // 如果你的Actor还有其他用Batch绘制的内容,放在这里
        // ...
    }
}

2. 在Main类中正确初始化和传递ShapeRenderer

确保ShapeRenderer和Stage使用相同的视口矩阵,并且传递给Bubble实例:

class Main : ApplicationAdapter() {
    lateinit var stage: Stage
    lateinit var sr: ShapeRenderer
    lateinit var bubble: Bubble

    override fun create() {
        val viewport = ExtendViewport(800f, 600f)
        stage = Stage(viewport)
        sr = ShapeRenderer()
        bubble = Bubble().apply {
            setSize(100f, 100f)
            setPosition(400f, 300f)
            setShapeRenderer(sr)
            // 添加拖拽逻辑示例
            addListener(object : DragListener() {
                override fun drag(event: InputEvent?, x: Float, y: Float, pointer: Int) {
                    moveBy(x - lastDragX, y - lastDragY)
                }
            })
        }
        stage.addActor(bubble)
        Gdx.input.inputProcessor = stage
    }

    override fun render() {
        Gdx.gl.glClearColor(0f, 0f, 0f, 1f)
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)

        stage.act()
        stage.draw()
    }

    override fun resize(width: Int, height: Int) {
        stage.viewport.update(width, height, true)
        // 同步ShapeRenderer的投影矩阵到视口相机
        sr.projectionMatrix = stage.viewport.camera.combined
    }

    override fun dispose() {
        stage.dispose()
        sr.dispose()
    }
}

3. 关键原理说明

Stage的Batch在绘制Actor时,会自动应用Actor的变换(位置、缩放、旋转)到自身的变换矩阵中,但ShapeRenderer不会自动继承这些变换。所以必须手动把Batch的projectionMatrix和transformMatrix赋值给ShapeRenderer,这样ShapeRenderer绘制的内容才会和Actor在Batch中的渲染处于同一个坐标空间。

另外,处理缩放时要注意:Actor的width/height是原始尺寸,实际渲染尺寸是width * scaleX/height * scaleY,同时要考虑Actor的原点设置,这样计算出的圆心和半径才会完全匹配Actor的实际边界。

内容的提问来源于stack exchange,提问作者Divelix

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:16:11