libgdx 中的事件处理未按预期工作

Event handling in libgdx not working as expected

我最近一直在学习 libgdx。在遵循他们 libgdx wiki 上的说明的过程中,我 运行 遇到了一些问题。

特别是在第 99 行的 GameScreen class 中,我更改了里面的代码,以便它返回到上一个屏幕(MainMenuScreen class),是的,当鼠标被按下时你会看到它工作了(我的意思是回到之前的屏幕)但在非常短的时间之后,屏幕自动切换到 GameScreen class(就像我单击鼠标一次但它让我多了一项冗余任务)。我想当我点击 GameScreen 屏幕时,它执行了第 99 行 if 语句中的代码以转到 MainMenuScreen 屏幕。在第 32 行的那个屏幕中,我猜这是在我到达这个屏幕后是真的,因为当我更改密钥时,它会被监听然后它工作正常(只转换一次)。我打算尝试在每个屏幕 class 上实现 InputProcessor,但现在出于某种原因我正在避免它。有人可以给我一些建议吗recommend.Thank你

这是 MainMenuScreen 的源代码 class。

package com.mygdx.game;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.utils.ScreenUtils;
//import com.mygdx.game.Drop;
public class MainMenuScreen implements Screen {

final Drop game;
OrthographicCamera camera;

public MainMenuScreen(final Drop gam) {
    game = gam;

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

@Override
public void render(float delta) {
    ScreenUtils.clear(0, 0, 0.2f, 1);

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

    game.batch.begin();
    game.font.draw(game.batch, "Welcome to Drop!!! ", 100, 150);
    game.font.draw(game.batch, "Tap anywhere to begin!", 100, 100);
    game.batch.end();

    if (Gdx.input.isTouched()) { //I guess right after switching to this screen this conditional sentence was true before
        game.setScreen(new GameScreen(game));
        dispose();
    }
}

@Override
public void resize(int width, int height) {
}

@Override
public void show() {
}

@Override
public void hide() {
}

@Override
public void pause() {
}

@Override
public void resume() {
}

@Override
public void dispose() {
}
}

这是 GameScreen 的源代码class

package com.mygdx.game;

import java.util.Iterator;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.ScreenUtils;
import com.badlogic.gdx.utils.TimeUtils;

public class GameScreen implements Screen {

final Drop game;

Texture dropImage;
Texture bucketImage;
//Sound dropSound;
//Music rainMusic;
OrthographicCamera camera;
Rectangle bucket;
Array<Rectangle> raindrops;
long lastDropTime;
int dropsGathered;

public GameScreen(final Drop gam) {
    this.game = gam;

    // load the images for the droplet and the bucket, 64x64 pixels each
    dropImage = new Texture(Gdx.files.internal("drop.png"));
    bucketImage = new Texture(Gdx.files.internal("bucket.png"));

    // load the drop sound effect and the rain background "music"
    //dropSound = Gdx.audio.newSound(Gdx.files.internal("drop.wav"));
    //rainMusic = Gdx.audio.newMusic(Gdx.files.internal("rain.mp3"));
    //rainMusic.setLooping(true);

    // create the camera and the SpriteBatch
    camera = new OrthographicCamera();
    camera.setToOrtho(false, 800, 480);

    // create a Rectangle to logically represent the bucket
    bucket = new Rectangle();
    bucket.x = 800 / 2 - 64 / 2; // center the bucket horizontally
    bucket.y = 20; // bottom left corner of the bucket is 20 pixels above
                    // the bottom screen edge
    bucket.width = 64;
    bucket.height = 64;

    // create the raindrops array and spawn the first raindrop
    raindrops = new Array<Rectangle>();
    spawnRaindrop();

}

private void spawnRaindrop() {
    Rectangle raindrop = new Rectangle();
    raindrop.x = MathUtils.random(0, 800 - 64);
    raindrop.y = 480;
    raindrop.width = 64;
    raindrop.height = 64;
    raindrops.add(raindrop);
    lastDropTime = TimeUtils.nanoTime();
}

@Override
public void render(float delta) {
    // clear the screen with a dark blue color. The
    // arguments to clear are the red, green
    // blue and alpha component in the range [0,1]
    // of the color to be used to clear the screen.
    ScreenUtils.clear(0, 0, 0.2f, 1);

    // tell the camera to update its matrices.
    camera.update();

    // tell the SpriteBatch to render in the
    // coordinate system specified by the camera.
    game.batch.setProjectionMatrix(camera.combined);

    // begin a new batch and draw the bucket and
    // all drops
    game.batch.begin();
    game.font.draw(game.batch, "Drops Collected: " + dropsGathered, 0, 480);
    game.batch.draw(bucketImage, bucket.x, bucket.y);
    for (Rectangle raindrop : raindrops) {
        game.batch.draw(dropImage, raindrop.x, raindrop.y);
    }
    game.batch.end();

    // process user input
    if (Gdx.input.justTouched()) { //This conditional works fine
    /*  Vector3 touchPos = new Vector3();
        touchPos.set(Gdx.input.getX(), Gdx.input.getY(), 0);
        camera.unproject(touchPos);
        bucket.x = touchPos.x - 64 / 2;
    */
    game.setScreen(new MainMenuSceen(game)); //Screen switch
    }
    if (Gdx.input.isKeyPressed(Keys.LEFT))
        bucket.x -= 200 * Gdx.graphics.getDeltaTime();
    if (Gdx.input.isKeyPressed(Keys.RIGHT))
        bucket.x += 200 * Gdx.graphics.getDeltaTime();

    // make sure the bucket stays within the screen bounds
    if (bucket.x < 0)
        bucket.x = 0;
    if (bucket.x > 800 - 64)
        bucket.x = 800 - 64;

    // check if we need to create a new raindrop
    if (TimeUtils.nanoTime() - lastDropTime > 1000000000)
        spawnRaindrop();

    // move the raindrops, remove any that are beneath the bottom edge of
    // the screen or that hit the bucket. In the later case we play back
    // a sound effect as well.
    Iterator<Rectangle> iter = raindrops.iterator();
    while (iter.hasNext()) {
        Rectangle raindrop = iter.next();
        raindrop.y -= 200 * Gdx.graphics.getDeltaTime();
        if (raindrop.y + 64 < 0)
            iter.remove();
        if (raindrop.overlaps(bucket)) {
            dropsGathered++;
            //dropSound.play();
            iter.remove();
        }
    }
}

@Override
public void resize(int width, int height) {
}

@Override
public void show() {
    // start the playback of the background music
    // when the screen is shown
    //rainMusic.play();
}

@Override
public void hide() {
}

@Override
public void pause() {
}

@Override
public void resume() {
}

@Override
public void dispose() {
    dropImage.dispose();
    bucketImage.dispose();
    //dropSound.dispose();
    //rainMusic.dispose();
}

}

这是 Drop class

的来源
package com.mygdx.game;

import com.badlogic.gdx.Game;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;

public class Drop extends Game {

SpriteBatch batch;
BitmapFont font;

public void create() {
    batch = new SpriteBatch();
    // Use LibGDX's default Arial font.
    font = new BitmapFont();
    this.setScreen(new MainMenuScreen(this));
}

public void render() {
    super.render(); // important!
}

public void dispose() {
    batch.dispose();
    font.dispose();
}
}

我觉得你对问题的分析是正确的。如果切换到主菜单后屏幕仍在触摸,方法 Gdx.input.isTouched() 将立即 return 为真。

另外,您已经尝试过的解决方案似乎是正确的:

I was intending to try implementing InputProcessor on each screen class

当使用 InputProcessor 时,您将在触摸屏幕时获得一个事件(对 touchDowntouchUp 的方法调用),并且不需要拉动触摸使用 isTouched 方法的事件。

使用类实现InputProcessor时的一个问题可能是,您只能使用方法Gdx.input.setInputProcessor将其中一个设置为游戏的输入处理器。 (当设置第二个输入处理器时,第一个被移除)。
这个问题的一个解决方案是InputMultiplexer。您可以将此多路复用器添加为游戏的输入处理器(使用 Gdx.input.setInputProcessor(multiplexer)),然后将您的输入处理器(主菜单和游戏对象)添加到此多路复用器:multiplexer.addProcessor(mainMenu)((InputMultiplexer) Gdx.input.getInputProcessor()).addProcessor(game)

这样您就可以处理触摸事件,而不是在您的 类.

中拉动触摸状态