Обработка ввода на сцене и актере

Я устанавливаю этап в качестве процессора ввода в конструкторе моего экрана,

public GameScreen() {
    stage = new GameStage();
    Gdx.input.setInputProcessor(stage);
}


@Override
public void render(float delta) {
    Gdx.gl.glClearColor(0, 0, 0.2f, 1);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    stage.act();
    stage.draw();
}

На этапе я вызываю обработчики событий следующим образом:

   private OrthographicCamera camera;
    private Box2DDebugRenderer renderer;
    private Vector3 touchPoint;

    private static final int VIEWPORT_WIDTH = 1280;
    private static final int VIEWPORT_HEIGHT = 720;

    public GameStage() {
        touchPoint = new Vector3();
        setupCamera();
        this.setViewport(new ScreenViewport(camera));
        renderer = new Box2DDebugRenderer();
        setUpWorld();
    }


    private void setUpWorld() {
        world = WorldUtils.createWorld();
        world.setContactListener(this);
        setUpGround();
    }

    private void setUpGround() {
        addActor(new Rock(WorldUtils.createGroundRock(world, 320 / Constants.PIXELS_TO_METERS, Constants.GROUND_HEIGHT, 640f / Constants.PIXELS_TO_METERS, 130f / Constants.PIXELS_TO_METERS)));
    }


    private void setupCamera() {
        camera = new OrthographicCamera(VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
        camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0);
        camera.update();
    }

    @Override
    public void act(float delta) {
        super.act(delta);
        accumulator += delta;
        while (accumulator >= delta) {
            world.step(TIME_STEP, 6, 2);
            accumulator -= TIME_STEP;
        }
        camera.update();
    }

    @Override
    public void draw() {
        super.draw();
        renderer.render(world, camera.combined);
    }

    @Override
    public boolean touchDown(int screenX, int screenY, int pointer, int button) {
        translateScreenToWorldCoordinates(screenX, screenY);
        Gdx.app.log("LOG", "Touch Coords " + screenX + " : " + screenY);
        return super.touchDown(screenX, screenY, pointer, button);
    }

    private void translateScreenToWorldCoordinates(int x, int y) {
        getCamera().unproject(touchPoint.set(x, y, 0));
    }

    @Override
    public void beginContact(Contact contact) {
        //TODO
    }

    @Override
    public void endContact(Contact contact) {

    }

    @Override
    public void preSolve(Contact contact, Manifold oldManifold) {

    }

    @Override
    public void postSolve(Contact contact, ContactImpulse impulse) {

    }

    @Override
    public boolean scrolled(int amount) {
        camera.zoom -= .42 * amount;
        return true;
    }

Теперь у меня есть актор, в конструкторе которого есть обработчик событий,

   public class Rock extends Actor {
    Texture texture = new Texture(Gdx.files.internal("brick.png"));
    Sprite sprite = new Sprite(texture, 150, 130);

    public Rock(Body body) {
        setBounds(body.getPosition().x * Constants.PIXELS_TO_METERS, body.getPosition().y * Constants.PIXELS_TO_METERS, 150, 130);
        setTouchable(Touchable.enabled);
        addListener(new InputListener() {
            @Override
            public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
                Gdx.app.log("LOG", "TAPPED");
                return super.touchDown(event, x, y, pointer, button);
            }
        });
    }


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

    @Override
    protected void positionChanged() {
        sprite.setPosition(getX(), getY());
        super.positionChanged();
    }
}

Теперь основной обработчик ввода в сцене работает, а в актере нет. Это не сработает, даже если я удалю обработчики ввода на этапе. Я предполагаю, что это должно быть реализовано по-другому, но не уверен. Как мне убедиться, что оба этих обработчика ввода работают. Кроме того, если у меня есть несколько рок-актеров, мне нужен обработчик ввода, чтобы все они работали.


person redGREENblue    schedule 19.01.2016    source источник
comment
Просто чтобы убедиться: вы не забыли добавить Actor (Rock) к Stage?   -  person asherbar    schedule 19.01.2016
comment
@ user2016436 Да. это добавлено.   -  person redGREENblue    schedule 19.01.2016
comment
Вы вызываете stage.act()? Возможно, если вы разместите немного больше кода (например, функцию рендеринга, определения классов и т. д.), мы сможем найти проблему, потому что код, который вы разместили, МОЖЕТ быть правильным.   -  person p.streef    schedule 19.01.2016
comment
@p-streef Да, я вызываю act() в Screen. Я добавил больше кода для сцены и актера. У меня есть внутреннее чувство, что я делаю что-то не так с координатами, и поэтому он не обнаруживает, когда я нажимаю на актера. Но я не уверен, что это такое.   -  person redGREENblue    schedule 19.01.2016


Ответы (1)


Я бы посоветовал вам подойти к этому с помощью шаблона проектирования Singleton.

Теоретически:

  1. создать несколько InputProcessors для различных задач
  2. создайте экземпляр всех входных процессоров статически при запуске и создайте один экземпляр InputMultiplexer - это позволяет вам обрабатывать несколько входных процессоров
  3. в вашем игровом классе всякий раз, когда вы закончите загрузку карты — установите InputMultiplexer, содержащий все ваши InputProcessors.

Практически:

создайте класс, расширяющий InputProcessor, назовем его UiInput:

public class UiInput implements InputProcessor {

@Override
public boolean keyDown(int keycode) {

    //not a great way but what ever. 
    if (keycode == Keys.ESCAPE) {
        GameConstants.gameScreen.pauseOrResume = !GameConstants.gameScreen.pauseOrResume;
        if (!GameConstants.gameScreen.pauseOrResume) {
            GameConstants.gameScreen.resume();
        } else {
            GameConstants.gameScreen.pause();
        }
        return true;
    } else {
        return false;
    }

}

@Override
public boolean keyUp(int keycode) {
    return false;
}

@Override
public boolean keyTyped(char character) {
    return false;
}
@Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {return false;}

@Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {return false;}

@Override
public boolean touchDragged(int screenX, int screenY, int pointer) {return false;}

@Override
public boolean mouseMoved(int screenX, int screenY) {return false;}

@Override
public boolean scrolled(int amount) {return false;}


}

Вы можете создать несколько классов.

Затем вы должны создать экземпляр для всех ваших InputProcessors, включая InputMultiplexer.

/* UI-Input */
private static UiInput uiInput = new UiInput();

/* DebugInput */
private static DebugInput debugInput = new DebugInput(); //etc. 

/* inputMultiplexer */
public static InputMultiplexer inputMultiplexer = new InputMultiplexer(uiInput, debugInput);

Теперь вместо того, чтобы устанавливать сцену как InputProcessor, на вашем GameScreen вы должны указать InputMultiplexer как InputProcessor:

public GameScreen() {
   stage = new GameStage();
   //Gdx.input.setInputProcessor(stage);
   Gdx.input.setInputProcessor(inputMultiplexer);
}
person NullOverFlow    schedule 19.01.2016