【问题标题】:Using unProject correctly in Java Libgdx在 Java Libgdx 中正确使用 unProject
【发布时间】:2013-09-04 10:27:30
【问题描述】:

我想让一个按钮可点击,但它不起作用 - 似乎我需要使用 unproject() 但我不知道如何使用。有问题的代码是:

Texture playButtonImage;
SpriteBatch batch;
ClickListener clickListener;
Rectangle playButtonRectangle;
Vector2 touchPos;
OrthographicCamera camera;

@Override
public void show() {
    playButtonImage = new Texture(Gdx.files.internal("PlayButton.png"));

    camera = new OrthographicCamera();
    camera.setToOrtho(false, 800, 480);
    batch = new SpriteBatch();

    playButtonRectangle = new Rectangle();
    playButtonRectangle.x = 400;
    playButtonRectangle.y = 250;
    playButtonRectangle.width = 128;
    playButtonRectangle.height = 64;
}

@Override
public void render(float delta) {
    Gdx.gl.glClearColor(0, 0, 0.2f, 1);
    Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

    camera.update();
    batch.setProjectionMatrix(camera.combined);

    batch.begin();
    batch.draw(playButtonImage, playButtonRectangle.x, playButtonRectangle.y);
    batch.end();

    if (Gdx.input.isTouched()) {
        Vector2 touchPos = new Vector2();
        touchPos.set(Gdx.input.getX(), Gdx.input.getY());


        if (playButtonRectangle.contains(touchPos)) {
            batch.begin();
            batch.draw(playButtonImage, 1, 1);
            batch.end();
        }
    }
}

【问题讨论】:

  • 可能屏幕坐标(0,0)在左上角,但相机坐标(0,0)在左下角。如果你使用 Gdx.input.getY()*-1 会发生什么?

标签: java opengl libgdx


【解决方案1】:

一般来说,您使用camera.unproject(Vector) 将您的屏幕坐标从点击或触摸转换为您的游戏世界。这是必需的,因为原点不一定相同,并且使用相机您还可以放大和缩小、四处移动、旋转等。取消投影将处理所有这些问题,并为您提供与指针位置匹配的游戏世界坐标。

在你的例子中,它会是这样的:

Vector3 touchPos = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
camera.unproject(touchPos);

话虽如此,您实际上不应该手动执行此 UI 任务。 Libgdx 还提供了一些 UI 功能,称为Stage(请参阅this)。已经有很多可用的小部件(请参阅this)。他们使用皮肤(你可以从here 得到一个基本的皮肤,你需要所有的 uiskin.* 文件)。他们自动将输入事件转发到所谓的Actors,例如一个按钮,你只需要实现这些事件的处理。

【讨论】:

  • 如我的回答中所述,在触摸时在每一帧上初始化一个新的 Vector3 对象会引入大量开销。 GC 周期很重,尤其是在游戏等时间紧迫的应用程序上(在移动设备上更糟;而且 libgdx 也是为移动设备构建的)
  • 您也可以使用 Pools 来解决初始化新 Vector3 的问题。
【解决方案2】:

with camera.unproject(Vector3);您可以将屏幕坐标转换为游戏世界坐标。

Vector3 tmpCoords = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
camera.unproject(tmpCoords);

tmpCoords.x //is now the touched X coordinate in the game world coordinate system
tmpCoords.y //is now the touched Y coordinate in the game world coordinate system.

除此之外,最好将 tmpVector 定义为一个字段,并且只实例化一个 Vector3 对象一次。然后你可以用 .set() 方法做同样的事情。

tmpCoords.set(Gdx.input.getX(), Gdx.input.getY(), 0);
camera.unproject(tmpCoords);

tmpCoords.x //is now the touched X coordinate in the game world coordinate system
tmpCoords.y //is now the touched Y coordinate in the game world coordinate system.

因此,您可以减少对象创建并删除导致微滞后的不必要的 GC 调用。

【讨论】:

    【解决方案3】:
    @Override
    public void render(float delta) {
    Gdx.gl.glClearColor(0, 0, 0.2f, 1);
    Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
    
    camera.update();
    batch.setProjectionMatrix(camera.combined);
    
    batch.begin();
    batch.draw(playButtonImage, playButtonRectangle.x, playButtonRectangle.y);
    batch.end();
    
    if (Gdx.input.isTouched()) {
        Vector3 touchPos = new Vector3();
        touchPos.set(Gdx.input.getX(), Gdx.input.getY(),0);
        camera.unproject(touchPos);
    
    
        if (playButtonRectangle.contains(touchPos.x, touchPos.y)) {
            batch.begin();
            batch.draw(playButtonImage, 1, 1);
            batch.end();
        }
       }
       }
    

    【讨论】:

      【解决方案4】:

      当您需要用户的接触点并将这些接触点转换为相机时,您需要通过相机坐标将它们取消投影到相机坐标

      camera.unproject(touchPos.set(Gdx.input.getX(), Gdx.input.getY(), 0));
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-06-18
        • 1970-01-01
        • 1970-01-01
        • 2012-12-30
        • 2017-12-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多