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

如何在libgdx的InputProcess中实现缩放(无法使用GestureListener/Detector)

在LibGDX的InputProcessor中实现缩放功能

没问题,既然你已经基于InputProcessor开发,又没法用GestureDetector,那我们直接通过跟踪多点触控的原始输入来实现缩放功能就行。核心思路是记录两个触摸点的位置,通过它们的距离变化来计算缩放比例,下面一步步拆解实现:

第一步:定义需要跟踪的状态变量

首先在你的InputProcessor实现类里,需要几个变量来记录触摸点的状态和缩放相关的数据:

public class MyInputProcessor implements InputProcessor {
    // 记录两个活跃触摸点的ID(-1表示无)
    private int activePointer1 = -1;
    private int activePointer2 = -1;
    // 存储两个触摸点的世界坐标
    private final Vector2 touchPos1 = new Vector2();
    private final Vector2 touchPos2 = new Vector2();
    // 触摸点初始距离,用来计算缩放比例
    private float initialDistance = 0f;
    // 当前缩放值(如果是相机的话,可以直接用camera.zoom)
    private float currentScale = 1f;

    // 假设你要缩放的目标是相机(也可以是Sprite等对象)
    private Camera targetCamera;

    public MyInputProcessor(Camera camera) {
        this.targetCamera = camera;
        this.currentScale = camera.zoom; // 初始化缩放为相机当前值
    }

第二步:处理触摸按下(touchDown)

当有手指按下时,我们需要为每个触摸点分配ID,并记录它们的位置。当两个点都按下时,计算初始距离:

@Override
    public boolean touchDown(int screenX, int screenY, int pointer, int button) {
        // 把屏幕坐标转换成世界坐标(如果你的操作基于世界空间的话)
        Vector2 worldPos = targetCamera.unproject(new Vector2(screenX, screenY));

        if (activePointer1 == -1) {
            activePointer1 = pointer;
            touchPos1.set(worldPos);
        } else if (activePointer2 == -1) {
            activePointer2 = pointer;
            touchPos2.set(worldPos);
            // 计算两个点的初始距离
            initialDistance = touchPos1.dst(touchPos2);
        }
        return true;
    }

第三步:处理触摸拖动(touchDragged)

当手指拖动时,更新对应触摸点的位置,然后通过当前距离和初始距离的比值计算缩放比例,应用到目标对象上:

@Override
    public boolean touchDragged(int screenX, int screenY, int pointer) {
        Vector2 worldPos = targetCamera.unproject(new Vector2(screenX, screenY));

        // 更新对应触摸点的位置
        if (pointer == activePointer1) {
            touchPos1.set(worldPos);
        } else if (pointer == activePointer2) {
            touchPos2.set(worldPos);
        }

        // 如果两个触摸点都处于活跃状态,计算缩放
        if (activePointer1 != -1 && activePointer2 != -1) {
            float currentDistance = touchPos1.dst(touchPos2);
            // 避免除以0的情况
            if (initialDistance > 0.001f) {
                float scaleFactor = currentDistance / initialDistance;
                // 应用缩放:如果是相机就调整zoom,是Sprite就setScale
                targetCamera.zoom = currentScale * scaleFactor;
                // 限制缩放范围(可选,比如最小0.5倍,最大2倍)
                targetCamera.zoom = Math.max(0.5f, Math.min(2f, targetCamera.zoom));
                // 更新当前缩放值,同时重置初始距离,让下一次拖动基于当前状态
                currentScale = targetCamera.zoom;
                initialDistance = currentDistance;
            }
        }
        return true;
    }

第四步:处理触摸抬起(touchUp)

当手指抬起时,清空对应的活跃触摸点ID,确保下次触摸能正确初始化:

@Override
    public boolean touchUp(int screenX, int screenY, int pointer, int button) {
        if (pointer == activePointer1) {
            activePointer1 = -1;
        } else if (pointer == activePointer2) {
            activePointer2 = -1;
        }
        return true;
    }

第五步:实现InputProcessor的其他方法

因为InputProcessor是接口,必须实现所有方法,其他不需要的方法可以返回false:

@Override
    public boolean keyDown(int keycode) { return false; }

    @Override
    public boolean keyUp(int keycode) { return false; }

    @Override
    public boolean keyTyped(char character) { return false; }

    @Override
    public boolean mouseMoved(int screenX, int screenY) { return false; }

    @Override
    public boolean scrolled(float amountX, float amountY) { return false; }
}

一些关键注意事项

  • 坐标转换:一定要把屏幕坐标转换成世界坐标(用unproject),否则缩放计算会基于屏幕像素,导致和你的游戏世界不匹配。
  • 缩放范围限制:建议给缩放加个上下限,避免缩放过度导致内容不可见或失真。
  • 相机更新:如果缩放的是相机,记得在每一帧调用targetCamera.update()来更新投影矩阵,确保渲染正确。
  • 触摸点稳定性:LibGDX的pointer参数会唯一标识每个触摸点,所以不用担心手指切换的问题,只要基于pointer判断就好。

内容的提问来源于stack exchange,提问作者장성혁

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:04:04