libgdx在触摸位置绘制图像

时间:2017-01-12 23:39:15

标签: java android libgdx

我只是试图让libgdx在我触摸屏幕的任何地方创建一张图片。

这就是我所做的不做任何事情

SpriteBatch batch;
Texture img;

@Override
public void create () {
    batch = new SpriteBatch();
    img = new Texture("badlogic.jpg");
}

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

public class MyInputProcessor implements InputProcessor {
    public boolean touchDown (int x, int y, int pointer, int button) {
        batch.begin();
        batch.draw(img,Gdx.input.getX(),Gdx.input.getY());
        batch.end();
        return true;
    }
    ... (the rest of the input methods)

如果你不知道,我真的不知道我在做什么,我认为它与batch.draw()方法中的touchDown而不是渲染区域有关但我无法从研究中弄清楚如何以不同的方式做到这一点

或者也许这也是错的,重点是我这样做是为了学习所以希望正确的答案能帮助我理解一般关于java的一些重要事情

1 个答案:

答案 0 :(得分:1)

与所有游戏引擎一样,LibGDX每次调用render()时都会重新渲染整个场景。 render()以游戏的帧速率被重复调用(如果您没有复杂且未经优化的游戏,则通常为60fps)。您通常在render()方法中执行的第一个与绘图相关的操作是清除您已使用Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);完成的屏幕。然后用最后一帧以来可能发生的任何变化重新绘制整个场景。

您正在尝试使用render方法之外的批处理绘制内容。在这种情况下,您在触地时执行此操作。但是,由于只有在触摸时才会执行此操作,因此对象将在下一次调用render()时出现并消失,因此它仅在屏幕上显示1/60秒。如果要使用输入处理器执行此操作,则需要将某个变量设置为true以指示render方法应该绘制它,以及其他变量以指示绘制它的位置。然后在render()方法中,如果变量为真,则绘制东西。

其次,输入处理器获得的xy不一定(并且通常不会)与OpenGL中的xy相对应。这是因为OpenGL拥有自己的坐标系,其坐标系的大小不一定与屏幕的坐标系完全相同。屏幕左上角有(0,0),Y轴向下,屏幕的宽度和高度与屏幕上的实际像素数相匹配。 OpenGL在屏幕中央有(0,0),Y轴向上,屏幕的宽度和高度为2,与实际屏幕像素无关。

但OpenGL坐标系是用投影矩阵修改的。 LibGDX相机类使这更简单。对于2D绘图,您需要OrthographicCamera。您可以使用相机设置OpenGL世界的宽度和大小,也可以定位相机。然后将相机的计算矩阵传递给SpriteBatch,以便将场景定位在OpenGL空间中。

因此,要在场景的坐标中输入输入坐标,您需要使用该相机来转换坐标。

最后,LibGDX无法神奇地知道它应该将输入命令传递给您创建的任何旧输入处理器。你必须告诉它应该使用哪个InputProcessor来调用Gdx.input.setInputProcessor()

所以要修好你的课程:

SpriteBatch batch;
Texture img;
boolean isTouchDown;
final Vector3 touchPosition = new Vector3();
OrthographicCamera camera;

@Override
public void create () {
    batch = new SpriteBatch();
    img = new Texture("badlogic.jpg");
    camera = new OrthographicCamera();
    Gdx.input.setInputProcessor(new MyInputProcessor()); // Tell LibGDX what to pass input to
}

@Override 
void resize (int width, int height) {
    // Set the camera's size in relation to screen or window size
    // In a real game you would do something more sophisticated or 
    // use a Viewport class to manage the camera's size to make your 
    // game resolution-independent.
    camera.viewportWidth = width;
    camera.viewportHeight = height;

    camera.update(); // re-calculate the camera's matrices
}

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

    batch.setProjectionMatrix(camera.combined); // pass camera's matrices to batch
    batch.begin();

    if (isTouchDown) { // Only draw this while the screen is touched.
        batch.draw(img, touchPosition.x, touchPosition.y);
    }

    batch.end();
}

public class MyInputProcessor implements InputProcessor {
    public boolean touchDown (int x, int y, int pointer, int button) {
        isTouchDown = true;

        touchPosition.set(x, y, 0); // Put screen touch coordinates into vector
        camera.unproject(touchPosition); // Convert the screen coordinates to world coordinates
        return true;
    }

    public boolean touchUp (int screenX, int screenY, int pointer, int button){
        isTouchDown = false;
        return true;
    }

    //... (the rest of the input methods)
}