【问题标题】:Libgdx - camera.unproject is not fixing my coordinatesLibgdx - camera.unproject 没有修复我的坐标
【发布时间】:2015-10-17 22:25:00
【问题描述】:

下面的代码给了我非常奇怪的 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;
    }
}

【问题讨论】:

    标签: camera libgdx project


    【解决方案1】:

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


    关于你的输出,你实际上打印了 y 两次,但第二次调用它 uy:

    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 方法。

    【讨论】:

      【解决方案2】:

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

      另外(尽管这与 InputListener 无关),camera.unproject 假定一个 Viewport 会填满屏幕,而您正在使用的 FitViewport 则不是这样。如果您使用 Viewport 类,则需要使用 viewport.unproject 而不是 camera.unproject,因此它会考虑黑条。

      但你只需要担心与舞台无关的东西的取消投影。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-02-11
        • 1970-01-01
        • 1970-01-01
        • 2013-02-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多