【问题标题】:Event handling in libgdx not working as expectedlibgdx 中的事件处理未按预期工作
【发布时间】:2022-01-10 09:14:46
【问题描述】:

我最近一直在学习 libgdx。在按照他们的 libgdx wiki 上的说明进行操作的过程中,我遇到了一些问题。

特别是在第 99 行的 GameScreen 类中,我更改了里面的代码,使其返回到上一个屏幕(MainMenuScreen 类),是的,当你按下鼠标时,它工作了(我的意思是回到之前的屏幕) 但在很短的时间之后,屏幕自动切换到 GameScreen 类(就像我单击鼠标一次但它让我多了 1 个冗余任务)。我猜当我点击 GameScreen 屏幕时,它执行了第 99 行 if 语句中的代码以转到 MainMenuScreen 屏幕。在第 32 行的那个屏幕中,我猜在我到达这个屏幕之后这是真的,因为当我更改键时,它会正常工作(只转换一次)。我打算尝试在每个屏幕类上实现 InputProcessor,但现在我出于某种原因避免它。谁能给我一些建议推荐。谢谢

这是 MainMenuScreen 类的源代码。

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 类的源代码

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 类的源代码

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();
}
}

【问题讨论】:

    标签: java libgdx


    【解决方案1】:

    您对问题的分析对我来说似乎是正确的。 Gdx.input.isTouched() 方法将立即返回 true,如果您切换到主菜单后屏幕仍然被触摸。

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

    我打算尝试在每个屏幕类上实现 InputProcessor

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

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

    这样您就可以处理触摸事件,而不是在两个类中拉动触摸状态。

    【讨论】:

    • 如果您对InputProcessor 有其他问题,您可以编辑您的问题,我们可以尝试解决:)
    猜你喜欢
    • 1970-01-01
    • 2020-01-22
    • 2014-05-18
    • 2023-03-11
    • 2016-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多