Почему мой подход не работает, чтобы постоянно повторять действие до тех пор, пока не будет нажата кнопка libgdx scene2d, и не остановить его, когда кнопка будет отпущена?

Я знаю, что многие вопросы были заданы, чтобы решить подобную проблему, но я не мог найти ответ на него.

Проблема: я сделал экран для своей игры libgdx, который выглядит так, как показано на следующем снимке экрана.

введите описание изображения здесь Я хочу, чтобы ввод осуществлялся только касанием. Когда я нажимаю и удерживаю кнопку с надписью "ниже", она уменьшает число в середине один раз. Я хочу, чтобы он продолжал уменьшаться, пока я не отпущу кнопку «ниже». Кнопку я поместил в стол, который в свою очередь добавляется на сцену. Чтобы добиться того, чего я хочу, я использовал следующий подход:

    TextButton less;   //for the button labeled 'lower'
    ....

***constructor start****
            stage = new Stage(new ScreenViewport());
            Gdx.input.setInputProcessor(stage);
            table = new Table();
            table.setFillParent(true);
            stage.addActor(table);
    ......
    ......
            style = new TextButton.TextButtonStyle();
            style.up = new TextureRegionDrawable(upRegion);
            style.down = new TextureRegionDrawable(downRegion);
            style.font = buttonFont;
            less = new TextButton("lower", style);
            table.add(less).expand().fill();
    ....
    ....
    less.addListener(new ChangeListener() {
     @Override
                public void changed(ChangeEvent event, Actor actor) {
                    while(less.isPressed()) {
                        Gdx.app.log("ispressed ","yes");
                        curLevel--;
                        level.setText("" + curLevel);
                        Gdx.app.log("curLevel: ",curLevel+"");
                        try{
                            Thread.sleep(1000);
                        }catch (Exception e){

                        }
                    }
                }
    }
....
....
***constructor ends****

Но цикл while в change() становится бесконечным, даже если я отпущу кнопку «меньше/ниже». Я также пробовал решение этого вопроса, но это также приводит к бесконечному циклу .

Также подробности моего проекта: (если они имеют значение):

ext {
        appName = 'kombat'
        gdxVersion = '1.5.2'
        roboVMVersion = '1.0.0-beta-01'
        box2DLightsVersion = '1.3'
        ashleyVersion = '1.3.1'
        aiVersion = '1.4.0'
    }

Я попробовал решение от gaRos, но в результате число на этикетке продолжает бесконечно уменьшаться даже после одного касания и отпускания. Вот что я сделал, следуя инструкциям gaRos:

  1. Переопределить метод действия

            package com.zeher.kombat;
            import com.badlogic.gdx.scenes.scene2d.ui.Skin;
            import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
            import com.zeher.kombat.Screens.LevelChooser;
            /**
               * Created by zucky on 10/4/2015.
            */
                public class LessButton extends TextButton {
                    LevelChooser lc;
                    public LessButton(String text,TextButton.TextButtonStyle skin,Kombat game) {
        super(text, skin);
        this.lc=game.introScreen.lc;
    
    }
    @Override
    public void act(float delta){
        if(lc.lowerFlag ) {
            lc.curLevel--;
            lc.level.setText("" + lc.curLevel);
        }
    
    }
    

    }

  2. Использовал inputListener.

             less.addListener(new InputListener() {
        public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
            lowerFlag = true;
                return false;
            }
            public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
                lowerFlag = false;
                Gdx.app.log("occured: ","touchUp on less");
            }
        });
    

Но проблема в том, что событие touchUp не запускается, а нижний флаг никогда не переключается на false.

Пожалуйста, скажите мне, что вызывает это неожиданное поведение и как обращаться с жестами нажатия и удержания так, как я хочу.


person Sunil Kumar    schedule 28.09.2015    source источник
comment
Засыпание игрового потока приостановит всю вашу игру. Вместо этого используйте отложенное действие или таймер libgdx, если вам нужно чего-то дождаться. Или посчитайте дельту времени. И ChangeListener — это не то, что вам нужно, потому что change() не сработает, пока вы не отпустите кнопку.   -  person Tenfour04    schedule 28.09.2015
comment
Вам удалось решить проблему, Сунил?   -  person gaRos    schedule 01.10.2015
comment
наконец решил это. скоро поделюсь решением.   -  person Sunil Kumar    schedule 04.10.2015


Ответы (2)


TextButton — это Актер, поэтому вы можете установить InputListener для этого.

Этот интерфейс имеет два метода для реализации:

less.addListener(new InputListener() {
        public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
                lowerFlag = true;
                return true;
        }


    public void touchUp (InputEvent event, float x, float y, int pointer, int button) {
            lowerFlag = false;
        }
 }); 

И вы переопределяете метод act кнопки и уменьшаете значение, если флаг равен true. Используйте дельту в качестве параметра, насколько быстро вы хотите уменьшить curLevel.

(если дельта больше уменьшите больше, если меньше уменьшите меньше)

person gaRos    schedule 28.09.2015
comment
Это потому, что я использую старую версию libgdx? - person Sunil Kumar; 04.10.2015
comment
Проблема заключалась в том, что touchDown должен возвращать true, я только что проверил документацию InputListener: вызывается, когда кнопка мыши или касание пальца поднимаются в любом месте, но только если touchDown ранее возвращал true для кнопки мыши или касания. - person gaRos; 05.10.2015

Прежде всего, я хочу поблагодарить gaRos за подсказку.

  1. Слушатель, который мы должны использовать с актерами для этой цели, это ActorGestureListener . Это должно быть так:

    less.addListener(new ActorGestureListener() {
            public void touchDown(InputEvent event, float x, float y, int pointer, int button) {
                lowerFlag = true;
                Gdx.app.log("occured: ","touchDown on less"); //to test whether it works or not
            }
    
    
            public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
                lowerFlag = false;
                Gdx.app.log("occured: ","touchUp on less");
            }
    });
    
  2. Теперь переопределите метод действия для этой кнопки «меньше», создав новый класс, расширяющий TextButton таким образом, чтобы он уменьшал значение, если флаг равен true. Используйте дельту в качестве параметра, насколько быстро вы хотите уменьшить curLevel.

(если дельта больше, уменьшите больше, если меньше, уменьшите меньше). Например, я создал класс LessButton.java.

    public class LessButton extends TextButton {
    LevelChooser lc;
    public LessButton(String text, TextButton.TextButtonStyle skin,Kombat game) {
        super(text, skin);
        this.lc=game.introScreen.lc;
    }
    @Override
    public void act(float delta){
        wait+=delta;
        if(lc.lowerFlag && lc.curLevel>0 && wait>delta*8) {
            lc.curLevel--;
            lc.level.setText("" + lc.curLevel);
            wait=0f;
        }
    }
    }

3. Теперь используйте это так:

        LessButton less;
        ....
        less = new LessButton("lower", style,game);
person Sunil Kumar    schedule 05.10.2015