13

LibGDXを使用してAndroid用のゲームを開発しています。ピンチズームとパンを追加しました。私の問題は、遊び場の外に出ないようにする方法です。そのまま、プレイエリアの外を真っ暗にすることができます。完全にズームアウトしたとき、私はそれに対処する方法を知っています、私はちょうど言いました:

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

}

しかし、ズームインした場合、どうすればこれを達成できますか。私はこれがそれほど複雑ではないことを知っています、私はそれを理解できないようです。作成時に、カメラを画面の中央に設定しました。パンする方法を知っています。camera.translate(-input.deltaX、-input.deltaY、0)を使用しています。この呼び出しの前に、位置がプレイエリアの外にあるかどうかをテストする必要があります。ズームインしたときに、画面の端にいるかどうかをテストするにはどうすればよいですか?

4

7 に答える 7

8

次のいずれかを使用できます

camera.frustum.boundsInFrustum(BoundingBox box) 
camera.frustum.pointInFrustum(Vector3 point)
camera.frustum.sphereInFrustum(Vector3 point, float radius)

ポイント/ボックス/球がカメラの視野内にあるかどうかを確認します。私が通常行うことは、プレイヤーが見ることを許可されるべきではない私の世界の4つのボックスを定義することです。カメラを動かして、ボックスの1つが錐台にある場合は、カメラを前の位置に戻します。

編集:AAveringはこれを以下のコードで実装しました。

于 2012-08-21T16:02:32.613 に答える
7

クレジットはMatsemannにアイデアを求めています。これが、私が使用した実装です。

OrthographicCameraを拡張するカスタムMyCameraクラスを作成し、次のコードを追加します。

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);
    }
}

さて、あなたのカスタムシーンまたはあなたが使用するもの(私の場合はカスタムボードクラスでした)は何でも呼び出します:

camera.setWorldBounds()

GestureListener.panメソッドで呼び出すことができます

camera.translateSafe(x, y);

それはあなたのカメラを範囲内に保つべきです

于 2014-04-11T15:42:33.280 に答える
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);

camMinは、プレイエリアの外側に何も表示せずにカメラを配置できる左下隅であり、カメラの隅から中央までのオフセットでもあります。

camMaxは、カメラが配置できる反対側の最も右側の位置です。

あなたが見逃していると私が推測している重要な部分は、ズームレベルでカメラサイズをスケーリングすることです。

于 2013-05-10T04:02:38.920 に答える
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);

どこ:

  • targetXtargetYは、ターゲットがどこにあるかの世界座標です。
  • worldSize世界のVector2大きさです。
于 2013-10-21T21:00:27.017 に答える
4

コメントを書くのに十分な評判がないので、以前の回答をいくつか指摘します。

Matsemannのアイデアで作成されたバウンディングボックスを使用したAAverinのソリューションは、一方のエッジ(境界)に近づき、斜めに平行移動しようとすると、煩わしく遅くなるため、適切ではありません。 。

で提示されているhandleInputメソッドの下部から解決策を試すことを強くお勧めします。

https://github.com/libgdx/libgdx/wiki/Orthographic-camera

これはスムーズに機能し、以前の回答のいくつかはそのように見えますが、これはMathUtils.clampを使用しており、簡単ではるかにクリーンです。

于 2014-11-03T09:44:16.220 に答える
2

このための完璧なクラス(AAverinのおかげもあります)

このクラスは、境界に固執するだけでなく、ズームすると境界にスナップします。

境界を設定し、カメラを移動するには、これらを呼び出します。

camera.setWorldBounds()
camera.translateSafe(x, y);

通話をズームするとき

camera.attemptZoom();

そして、これがクラスです:

public class CustomCamera extends OrthographicCamera
{
    public CustomCamera() {}

    public CustomCamera(float viewportWidth, float viewportHeight)
    {
        super(viewportWidth, viewportHeight);
    }

    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;
    @Override
    public void translate(float x, float y) {
        lastPosition = new Vector3(position);
        super.translate(x, y);
    }

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

    public void ensureBounds()
    {
        if(isInsideBounds())
        {
            position.set(lastPosition);
        }
    }

    private boolean isInsideBounds()
    {
        if(frustum.boundsInFrustum(left) || frustum.boundsInFrustum(right) || frustum.boundsInFrustum(top) || frustum.boundsInFrustum(bottom))
        {
            return true;
        }
        return false;
    }

    public void attemptZoom(float newZoom)
    {
        this.zoom = newZoom;
        this.snapCameraInView();
    }

    private void snapCameraInView()
    {
        float halfOfCurrentViewportWidth = ((viewportWidth * zoom) / 2f);
        float halfOfCurrentViewportHeight = ((viewportHeight * zoom) / 2f);

        //Check the vertical camera.
        if(position.x - halfOfCurrentViewportWidth < 0f) //Is going off the left side.
        {
            //Snap back.
            float amountGoneOver = position.x - halfOfCurrentViewportWidth;
            position.x += Math.abs(amountGoneOver);
        }
        else if(position.x + halfOfCurrentViewportWidth > viewportWidth)
        {
            //Snap back.
            float amountGoneOver = (viewportWidth - (position.x + halfOfCurrentViewportWidth));
            position.x -= Math.abs(amountGoneOver);
        }

        //Check the horizontal camera.
        if(position.y + halfOfCurrentViewportHeight > viewportHeight)
        {
            float amountGoneOver = (position.y + halfOfCurrentViewportHeight) - viewportHeight;
            position.y -= Math.abs(amountGoneOver);
        }
        else if(position.y - halfOfCurrentViewportHeight < 0f)
        {
            float amountGoneOver = (position.y - halfOfCurrentViewportHeight);
            position.y += Math.abs(amountGoneOver);
        }
    }
}
于 2015-06-06T20:54:05.920 に答える
1

指定されたCustomCameraクラスはうまく機能しません。ピンチジェスチャをzoomSafeにマッピングするために使用しました。カメラは、境界の端にあるときに左から右に常にバウンド/フラッシュしていました。また、カメラはパンニングでは正しく機能しません。境界のエッジに沿ってパンしようとすると、エッジが「粘着性」であるかのようにどこにもパンしません。これは、境界外の座標を調整するだけでなく、最後の位置に戻るためです。

于 2015-11-29T16:45:09.253 に答える