平移和缩放时,将libgdx相机保持在边界内

wea*_*9x9 11 android libgdx

我正在使用LibGDX为Android开发游戏.我添加了捏缩放和平移.我的问题是如何避免走出游戏区域.实际上,你可以在游戏区域外平移到黑暗中.当我完全缩小时,我知道如何处理它,我只是说:

if(camera.zoom == 1.0f) ;
else {

}
Run Code Online (Sandbox Code Playgroud)

但是,如果放大,我该如何做到这一点.我知道这并不复杂,我似乎无法弄明白.创建后,我将相机设置在屏幕中间.我知道如何平移,我正在使用camera.translate(-input.deltaX,-input.deltaY,0),我只需要在此调用之前进行测试,看看该位置是否在游戏区域之外.当我放大时,如何测试我是否在屏幕边缘?

Mat*_*ann 7

你可以使用其中一个

camera.frustum.boundsInFrustum(BoundingBox box) 
camera.frustum.pointInFrustum(Vector3 point)
camera.frustum.sphereInFrustum(Vector3 point, float radius)
Run Code Online (Sandbox Code Playgroud)

检查点/盒/球是否在您的相机视图内.我通常做的是在我的世界周围定义4个盒子,玩家不应该被允许看到.如果相机被移动而其中一个盒子在平截头体中,我将相机移回到前一个位置.

编辑:AAvering已在下面的代码实现了这一点.


Sea*_*ord 6

这是我通过使用正交相机在我的2D游戏中平移或缩放来更新相机位置后调用的代码.它会校正摄像机位置,使其不会显示游戏区域边界之外的任何内容.

float camX = camera.position.x;
float camY = camera.position.y;

Vector2 camMin = new Vector2(camera.viewportWidth, camera.viewportHeight);
camMin.scl(camera.zoom/2); //bring to center and scale by the zoom level
Vector2 camMax = new Vector2(borderWidth, borderHeight);
camMax.sub(camMin); //bring to center

//keep camera within borders
camX = Math.min(camMax.x, Math.max(camX, camMin.x));
camY = Math.min(camMax.y, Math.max(camY, camMin.y));

camera.position.set(camX, camY, camera.position.z);
Run Code Online (Sandbox Code Playgroud)

camMin 是摄像机可以在播放区域外显示任何内容的最低左角,也是从摄像机角落到中心的偏移.

camMax 是相机可以处于相对最高的位置.

我猜你丢失的关键部分是按照缩放级别缩放相机尺寸.


AAv*_*rin 6

感谢Matsemann的想法,这是我使用的实现.

制作一个自定义MyCamera类,扩展OrthographicCamera并添加以下代码:

BoundingBox left, right, top, bottom = null;

public void setWorldBounds(int left, int bottom, int width, int height) {
    int top = bottom + height;
    int right = left + width;

    this.left = new BoundingBox(new Vector3(left - 2, 0, 0), new Vector3(left -1, top, 0));
    this.right = new BoundingBox(new Vector3(right + 1, 0, 0), new Vector3(right + 2, top, 0));
    this.top = new BoundingBox(new Vector3(0, top + 1, 0), new Vector3(right, top + 2, 0));
    this.bottom = new BoundingBox(new Vector3(0, bottom - 1, 0), new Vector3(right, bottom - 2, 0));
}

Vector3 lastPosition = new Vector3();
@Override
public void translate(float x, float y) {
    lastPosition.set(position.x, position.y, 0);
    super.translate(x, y);
}

public void translateSafe(float x, float y) {
    translate(x, y);
    update();
    ensureBounds();
    update();
}

public void ensureBounds() {
    if (frustum.boundsInFrustum(left) || frustum.boundsInFrustum(right) || frustum.boundsInFrustum(top) || frustum.boundsInFrustum(bottom)) {
        position.set(lastPosition);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,在你自定义的sceene或你使用的(在我的情况下,它是一个自定义的Board类)调用:

camera.setWorldBounds()
Run Code Online (Sandbox Code Playgroud)

在您的GestureListener.pan方法中,您可以调用

camera.translateSafe(x, y);
Run Code Online (Sandbox Code Playgroud)

它应该让你的相机在一定范围内


nmw*_*nmw 5

这是我的解决方案:

float minCameraX = camera.zoom * (camera.viewportWidth / 2);
float maxCameraX = worldSize.x - minCameraX;
float minCameraY = camera.zoom * (camera.viewportHeight / 2);
float maxCameraY = worldSize.y - minCameraY;
camera.position.set(Math.min(maxCameraX, Math.max(targetX, minCameraX)),
        Math.min(maxCameraY, Math.max(targetY, minCameraY)),
        0);
Run Code Online (Sandbox Code Playgroud)

在哪里:

  • targetXtargetY是目标所在位置的世界坐标。
  • worldSize是一个Vector2世界的大小。