Libgdx - camera.unproject没有修复我的坐标

时间:2015-10-17 22:25:01

标签: camera libgdx project

以下代码给出了非常奇怪的y坐标。

10-18 00:13:36.834  30543-30567/com.xxxx.yyyy.android I/x﹕ 137.4782
10-18 00:13:36.834  30543-30567/com.xxxx.yyyy.android I/y﹕ -1984.2426
10-18 00:13:36.835  30543-30567/com.xxxx.yyyy.android I/ux﹕ 91.65213
10-18 00:13:36.835  30543-30567/com.xxxx.yyyy.android I/uy﹕ -1984.2426

我想我在运行时设置错误而不是做错了? camera.unproject调用应该处理从屏幕坐标到游戏坐标的所有重映射,不应该吗?或者我必须在取消投影之前进行缩放和反转?

package com.xxxx.yyyy;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;


public class LetterActor extends Actor
{
    private Texture texture;
    private Vector3 touchPosition = new Vector3();
    private Camera camera;
    private boolean unproject = true;

    public LetterActor(Texture letterTexture, Camera theCamera)
    {
        texture = letterTexture;
        camera = theCamera;

        touchPosition.set(240, 800, 0);
        camera.unproject(touchPosition);
        setPosition(touchPosition.x, touchPosition.y);

        setSize(texture.getWidth(), texture.getHeight());

        addListener(new InputListener()
        {
            @Override
            public boolean touchDown(InputEvent event, float x, float y, int pointer, int button)
            {
                touchPosition.set(x, y, 0);
                if (unproject)
                {
                    camera.unproject(touchPosition);
                }
                setPosition(touchPosition.x, touchPosition.y);

                logPositions(x, y, touchPosition.x, touchPosition.y);

                return true;
            }

            @Override
            public void touchUp(InputEvent event, float x, float y, int pointer, int button)
            {
                touchPosition.set(x, y, 0);
                if (unproject)
                {
                    camera.unproject(touchPosition);
                }
                setPosition(touchPosition.x, touchPosition.y);

                logPositions(x, y, touchPosition.x, touchPosition.y);
            }

            @Override
            public void touchDragged(InputEvent event, float x, float y, int pointer)
            {
                touchPosition.set(x, y, 0);
                if (unproject)
                {
                    camera.unproject(touchPosition);
                }
                setPosition(touchPosition.x, touchPosition.y);

                logPositions(x, y, touchPosition.x, touchPosition.y);
            }
        });
    }

    private void screenTo()
    {

    }

    private void logPositions(float x, float y,float ux, float uy)
    {
        Gdx.app.log("x", Float.toString(x));
        Gdx.app.log("y", Float.toString(y));
        Gdx.app.log("ux", Float.toString(ux));
        Gdx.app.log("uy", Float.toString(y));
    }

    @Override
    public void draw(Batch batch, float alpha)
    {
        batch.draw(texture, getX(), getY(), getWidth(), getHeight());
    }

    @Override
    public void act(float delta) {}
}



package com.xxxx.yyyy;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.utils.viewport.ExtendViewport;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.Touchable;
import com.badlogic.gdx.utils.viewport.FitViewport;

public class WordPuzzle extends ApplicationAdapter
{
    private final static float VIRTUAL_WIDTH = 480;
    private final static float VIRTUAL_HEIGHT = 800;

    private OrthographicCamera camera;
    private FitViewport viewport;
    private Stage stage;

    @Override
    public void create()
    {
        camera = new OrthographicCamera(VIRTUAL_WIDTH, VIRTUAL_HEIGHT);
        camera.setToOrtho(false, VIRTUAL_WIDTH, VIRTUAL_HEIGHT);

        viewport = new FitViewport(VIRTUAL_WIDTH, VIRTUAL_HEIGHT, camera);
        stage = new Stage();
        stage.setViewport(viewport);
        Gdx.input.setInputProcessor(stage);

        Texture[] textures = LetterLoader.loadLetters();
        for (int i = 0; i < textures.length; i++)
        {
            LetterActor letterActor = new LetterActor(textures[i], camera);
            letterActor.setTouchable(Touchable.enabled);
            stage.addActor(letterActor);
        }
    }

    @Override
    public void render()
    {
        Gdx.gl.glClearColor(1, 1, 1, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);

        stage.act(Gdx.graphics.getDeltaTime());
        stage.draw();
    }


    @Override public void resize(int width, int height)
    {
        stage.getViewport().update(width, height, true);
    }

    @Override public void dispose()
    {
        stage.dispose();
    }
}



package com.xxxx.yyyy;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;

public class LetterLoader {

    public static Texture[] loadLetters()
    {
        Texture[] letters = new Texture[26];

        for (int i = 0; i < 26; i++)
        {
            char letter = (char) (i + 65);
            letters[i] = new Texture(Gdx.files.internal("bigletters/" + letter + ".png"));
        }

        return letters;
    }
}

2 个答案:

答案 0 :(得分:1)

首先,从输入侦听器获得的触摸位置(x,y)已经是正确的坐标。

关于你的输出,你实际打印了两次,但是第二次打电话给你:

Gdx.app.log("uy", Float.toString(y));

如果touchPosition.set(240, 800, 0);在屏幕坐标中,则需要取消投影,但

camera.unproject(touchPosition);

假设您的相机填满整个屏幕,因此它会在内部调用:

unproject(screenCoords, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());

由于您使用虚拟大小,这是错误的。最简单的解决方案是使用您正在使用的视口中的unproject方法:

viewport.unproject(touchPosition);

这将自动调用带有正确参数的相机unproject方法。

答案 1 :(得分:0)

由于您使用的是Stage和InputListener,因此您在touchDown中获得的坐标和相关方法已经在世界坐标中,因此取消它们是没有意义的。您可以直接使用x和y。

另外(尽管这与InputListener无关),camera.unproject假定一个填充屏幕的视口,这与您正在使用的FitViewport不同。如果您使用的是Viewport课程,则需要使用viewport.unproject代替camera.unproject,因此需要考虑黑条。

但是你只需要担心与舞台无关的东西的未投射。