如何在Libgdx Java中实现缩放和平移?

3
我希望能在我的游戏中添加缩放和平移功能,但我在网上查找的所有内容都失败了。
如果您能为我提供一个实现这些功能的好例子,那就太好了。
这是我正在尝试让它工作的类。
package com.adam.finis.screens;

import com.adam.finis.Main;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputMultiplexer;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.input.GestureDetector;
import com.badlogic.gdx.input.GestureDetector.GestureListener;
import com.badlogic.gdx.maps.tiled.TiledMap;
import com.badlogic.gdx.maps.tiled.TmxMapLoader;
import com.badlogic.gdx.maps.tiled.renderers.OrthogonalTiledMapRenderer;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.viewport.FitViewport;
import com.badlogic.gdx.utils.viewport.Viewport;

public class Play extends ApplicationAdapter implements Screen, GestureListener, ApplicationListener{
    //Core Variables
        private Main game;
        public static InputMultiplexer inputMultiPlex;
    //Texture Variables
        Texture Title;
        private TmxMapLoader mapLoader;
        private TiledMap map;
        private OrthogonalTiledMapRenderer renderer;
    //Sprite Variables
        public static boolean spawnSprite = false;
    //Font
        private BitmapFont font;
    //Window Variables
        private OrthographicCamera gameCam;
        private Viewport gamePort;
        private PlayHud hudPlay;
        private int mapX = 1952;
        private int mapY = 1952;
        private int mapHalfX = mapX / 2;
        private int mapHalfY = mapY / 2;
        public static boolean GAME_PAUSED = false;

    //Random Variables
        private Vector2 dragOld, dragNew;
        public static Vector2 worldSize;
    //DEBUG
        private String message;
        private Texture debugTexture;
        private Sprite debugSprite;


    public Play(Main game){
        this.game = game;
        gameCam = new OrthographicCamera();
        gameCam.setToOrtho(false, Main.V_WIDTH, Main.V_HEIGHT);
        gamePort = new FitViewport(Main.V_WIDTH, Main.V_HEIGHT, gameCam);
        hudPlay = new PlayHud(game.sb);

        mapLoader = new TmxMapLoader();
        map = mapLoader.load("images/level1.tmx");
        renderer = new OrthogonalTiledMapRenderer(map);

        gameCam.position.set(mapHalfX, mapHalfY, 0);

        GestureDetector gd = new GestureDetector(this);
        inputMultiPlex = new InputMultiplexer();
        inputMultiPlex.addProcessor(hudPlay.stage);
        inputMultiPlex.addProcessor(hudPlay.debugStage);
        inputMultiPlex.addProcessor(gd);
        Gdx.input.setInputProcessor(gd);

        debugTexture = new Texture(Gdx.files.internal("images/house.png"));
        debugSprite = new Sprite(debugTexture);

        worldSize = new Vector2(mapX, mapY);

        font = new BitmapFont(Gdx.files.internal("fonts/lemonMilk.fnt"),false);
        font.setColor(Color.RED);
    }

    @Override
    public void show() {

    }

    public void handleInput(float dt){
        //Keyboard Settings
        if (Gdx.input.isKeyPressed(Input.Keys.W)) {
            gameCam.position.y += 350 * dt;
        }

        if (Gdx.input.isKeyPressed(Input.Keys.A)) {
            gameCam.position.x -= 350 * dt;
        }
        if (Gdx.input.isKeyPressed(Input.Keys.S)) {
            gameCam.position.y -= 350 * dt;
        }

        if (Gdx.input.isKeyPressed(Input.Keys.D)) {
            gameCam.position.x += 350 * dt;
        }
        //ZOOM
        if (Gdx.input.isKeyPressed(Input.Keys.O)) {
            gameCam.zoom += 1.5f * dt;
        }

        if (Gdx.input.isKeyPressed(Input.Keys.P)) {
            gameCam.zoom -= 1.5f * dt;
        }
        //CAMERA BOUNDS
        gameCam.zoom = MathUtils.clamp(gameCam.zoom, 0.1f, mapX / gameCam.viewportWidth);
        //|
        float camX = gameCam.position.x;
        float camY = gameCam.position.y;
        //|
        Vector2 camMin = new Vector2(gameCam.viewportWidth, gameCam.viewportHeight);
        Vector2 camMax = new Vector2(1952, 1952);
        //|
        camMin.scl(gameCam.zoom/2);
        camMax.sub(camMin);
        //|
        camX = Math.min(camMax.x, Math.max(camX, camMin.x));
        camY = Math.min(camMax.y, Math.max(camY, camMin.y));
        gameCam.position.set(camX, camY, gameCam.position.z);
        //------------------------------------------------------------------------------------

        //Touch Settings
        if (Gdx.input.justTouched()){
            dragNew = new Vector2(Gdx.input.getX(), Gdx.input.getY());
            dragOld = dragNew;
        }

        if (Gdx.input.isTouched()){
            dragNew = new Vector2(Gdx.input.getX(), Gdx.input.getY());
            if (!dragNew.equals(dragOld)){
                gameCam.translate(dragOld.x - dragNew.x, dragNew.y - dragOld.y);
                dragOld = dragNew;
            }
        }
    }

    public void update(float dt){
        handleInput(dt);
        gameCam.update();
        renderer.setView(gameCam);
    }

    @Override
    public void render(float delta) {
        if(GAME_PAUSED == false){
            update(delta);
            //CLEAR SCREEN - BLACK
            Gdx.gl.glClearColor(0, 0, 0, 1);
            Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

            //INIT ALL INPUT
            Gdx.input.setInputProcessor(inputMultiPlex);

            //RENDER MAP
            renderer.setView(gameCam);
            renderer.render();
            //DRAW
            if(spawnSprite == true){
                game.sb.begin();
                    game.sb.draw(debugSprite, 1500, 500);
                game.sb.end();
            }
            //DRAW HUD
            hudPlay.stage.getViewport().apply();
            hudPlay.stage.act();
            hudPlay.stage.draw();
            //debug DRAW HUD
            hudPlay.debugStage.getViewport().apply();
            hudPlay.debugStage.act();
            hudPlay.debugStage.draw();
            //PROJECTION
            game.sb.setProjectionMatrix(gameCam.combined);
            game.hudSb.setProjectionMatrix(hudPlay.debugStage.getCamera().combined);
            game.hudSb.setProjectionMatrix(hudPlay.stage.getCamera().combined);


            if(Main.zoomOut == true){
                gameCam.zoom += 1.5f * delta;
            }

            if(Main.zoomIn == true){
                gameCam.zoom -= 1.5f * delta;
            }
        }

        if(GAME_PAUSED == true){
            Gdx.gl.glClearColor(0, 0, 0, 1);
            Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
            Gdx.input.setInputProcessor(inputMultiPlex);
            game.sb.setProjectionMatrix(hudPlay.debugStage.getCamera().combined);
            hudPlay.debugStage.getViewport().apply();
            hudPlay.debugStage.act();
            hudPlay.debugStage.draw();
        }
    }

    @Override
    public void resize(int width, int height) {
        gamePort.update(width, height);
        gameCam.viewportWidth = width/5f;  //We will see width/32f units!
        gameCam.viewportHeight = gameCam.viewportWidth * height/width;
        hudPlay.stage.getViewport().update(width, height, true);
        hudPlay.debugStage.getViewport().update(width, height, true);
    }

    @Override
    public void pause() {}

    @Override
    public void resume() {}

    @Override
    public void hide() {}

    @Override
    public void dispose() {
        game.sb.dispose();
        renderer.dispose();
        hudPlay.dispose();
        font.dispose();
    }

    @Override
    public boolean touchDown(float x, float y, int pointer, int button) {
        return false;
    }

    @Override
    public boolean tap(float x, float y, int count, int button) {
        message = "TAP";
        Gdx.app.log("INFO", message);
        return false;
    }

    @Override
    public boolean longPress(float x, float y) {
        message = "LONG PRESS";
        Gdx.app.log("INFO", message);
        return false;
    }

    @Override
    public boolean fling(float velocityX, float velocityY, int button) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean pan(float x, float y, float deltaX, float deltaY) {
        message = "PAN";
        Gdx.app.log("INFO", message);
        return false;
    }

    @Override
    public boolean panStop(float x, float y, int pointer, int button) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean zoom(float initialDistance, float distance) {
        message = "Zoom performed";
        Gdx.app.log("INFO", message);
        return false;
    }

    @Override
    public boolean pinch(Vector2 initialPointer1, Vector2 initialPointer2,
            Vector2 pointer1, Vector2 pointer2) {
        message = "Pinch performed";
        Gdx.app.log("INFO", message);

        return true;
    }
}
2个回答

5

您的答案是正确的,但这里有一个改进版本,第二次缩放是在前一次缩放的基础上进行的。

此外,相机平移速度与当前相机缩放成比例。

@Override
public boolean pan(float x, float y, float deltaX, float deltaY) {
    message = "PAN";
    Gdx.app.log("INFO", message);

    gameCam.translate(-deltaX * currentZoom,deltaY * currentZoom);
    gameCam.update();
    return false;
}
@Override
public boolean zoom(float initialDistance, float distance) {
    message = "Zoom performed";
    Gdx.app.log("INFO", message);

    gameCam.zoom = (initialDistance / distance) * currentZoom;
    gameCam.update();

    return true;
}
@Override
public boolean panStop(float x, float y, int pointer, int button) {
    Gdx.app.log("INFO", "panStop");
    currentZoom = gameCam.zoom;
    return false;
}

2
非常感谢你,伙计,这正是我所需要的。我会把你放在我的游戏制作人员名单中:D - Adam Brickhill
currentZoom 可以被 gameCam.zoom 替换吗?如果不行,为什么? - TobTobXX

1

我解决了问题,抱歉我对这一切都很新,让我有些思考过度。

@Override
    public boolean pan(float x, float y, float deltaX, float deltaY) {
        message = "PAN";
        Gdx.app.log("INFO", message);

        gameCam.translate(-deltaX, deltaY);
        gameCam.update();
        return false;
    }
@Override
    public boolean zoom(float initialDistance, float distance) {
        message = "Zoom performed";
        Gdx.app.log("INFO", message);

        gameCam.zoom = (initialDistance / distance) * ZOOM;
        gameCam.update();

        return true;
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接