Libgdx различный входной слушатель для каждого объекта - PullRequest
0 голосов
/ 04 января 2019

Я пытаюсь создать игру, и мне нужно иметь несколько разных слушателей ввода (детекторов) для каждого объекта.У меня есть класс с именем «Blocker», в котором создается моя «блочная» форма.В моем основном классе игрового экрана я создаю массив из 10 экземпляров Block из класса Block, поскольку мне нужно 10 «блоков»

. Я реализовал интерфейс GestureDetector непосредственно в классе Block.

Вот класс Block:

public class Block implements GestureDetector.GestureListener {
    GameScreen gameScreen;
    Controller game;

    public Body block;

    float screenWidth;

    Stack distance;
    Stack time;

    //Calculated speed to be used once block is released
    public float speed;

    //Becomes true when user starts panning
    public boolean isPaning = false;
    public boolean isReleased = false;
    public boolean isActive = false;

    //Tracks user drag location
    public float panLocation;

    //Becomes true when the user release block
    public boolean released = false;

    public Block(GameScreen gameScreen, Controller game){
        this.gameScreen = gameScreen;
        this.game = game;

        distance = new Stack();
        time = new Stack();

        screenWidth = gameScreen.screenWidth;

        //Creates block that stops balls
        block = createBlock();
        //Sets properties
        setBlockProperties(block);
    }

    public Body createBlock(){
        float tmp = (screenWidth - gameScreen.goalPostThickness);
        float xPos = tmp/gameScreen.PPM;
        Body bBody;
        BodyDef def = new BodyDef();
        def.type = BodyDef.BodyType.DynamicBody;
        def.position.set(xPos, 0);
        def.fixedRotation = true;
        bBody = gameScreen.world.createBody(def);

        return bBody;
    }


     //Sets radius, density, etc.
    public void setBlockProperties(Body body){
        float gbt = screenWidth / 75;  //Goal post thickness

        // Create a circle shape and set its radius to 6
        PolygonShape square = new PolygonShape();
        square.setAsBox(gameScreen.goalPostThickness/gameScreen.PPM, (gameScreen.goalWidth/2)/gameScreen.PPM);

        // Create a fixture definition to apply our shape to
        FixtureDef fixtureDef = new FixtureDef();
        fixtureDef.shape = square;
        fixtureDef.density = 3.5f;
        fixtureDef.friction = 0.4f;
        fixtureDef.restitution = 0.6f; // Make it bounce a little bit

        fixtureDef.filter.categoryBits = 0x0004;
        fixtureDef.filter.maskBits = 0x0002;

        // Create our fixture and attach it to the body
        Fixture fixture = block.createFixture(fixtureDef);

        square.dispose();
    }

    //EVERYTHING BELOW IS FOR USER INPUT
     @Override
    public boolean touchDown(float x, float y, int pointer, int button) {
                                                                              return false;
                                                                                           }

    @Override
    public boolean tap(float x, float y, int count, int button) {
                                                                      return false;
                                                                                   }

    @Override
    public boolean longPress(float x, float y) {
                                                     return false;
                                                                  }

    @Override
    public boolean fling(float velocityX, float velocityY, int button) {
                                                                             return false;
                                                                                          }

    @Override
    public boolean pan(float x, float y, float deltaX, float deltaY) {
        isPaning = true;

        Vector3 input = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
        long currentTime = System.currentTimeMillis();
        double seconds = currentTime / 1000.0;
        //Input is backwards (Y down) to camera so this swaps it
        game.cam.unproject(input);
        float meters = input.y / gameScreen.PPM;
        distance.push(new Double(meters));
        time.push(new Double(seconds));

        setPanLocation(input.y);

        //Incase pan stop is not triggered, speed is still calculated
        if ((input.y / gameScreen.PPM) >= gameScreen.boundaryLocation){
            isPaning = false;
            speed = calculateSpeed(distance, time);
            setCheckRelease(true);
        }
        return false;
    }

    @Override
    public boolean panStop(float x, float y, int pointer, int button) {
        isPaning = false;

        Vector3 input = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
        long currentTime = System.currentTimeMillis();
        double seconds = currentTime / 1000.0;

        //Input is backwards (Y down) to camera so this swaps it
        game.cam.unproject(input);
        float meters = input.y / gameScreen.PPM;
        distance.push(new Double (meters));
        time.push(new Double (seconds));

        speed = calculateSpeed(distance, time);

        //System.out.println("Calculated speed: " + speed );
        //System.out.println("Stop time: " + meters);
        setCheckRelease(true);
        return false;
    }

    @Override
    public boolean zoom(float initialDistance, float distance) {
                                                                     return false;
                                                                                  }

    @Override
    public boolean pinch(Vector2 initialPointer1, Vector2 initialPointer2, Vector2 pointer1, Vector2 pointer2) {
        return false;
    }

    @Override
    public void pinchStop() {

    }

    public void setPanLocation(float v){
                                              panLocation = v;
                                                              }

    public float getPanLocation(){
                                        return panLocation;
                                                           }

    public void setCheckRelease(boolean check){
                                                     released = check;
                                                                      }

    public boolean getCheckRelease(){
                                           return released;
                                                           }

    //Calculates speed from the drag time and distance
    public float calculateSpeed(Stack distance, Stack time){
        boolean checkDifference = false;
        int popCount = 0;

        double tmpDis = 0;
        double tmpTime = 0;

        double endDistance = (Double) distance.pop();
        double endTime = (Double) time.pop();

        //pop elements until there can be a calculated difference
        //between start and end time/distance
        while (!checkDifference) {
            tmpDis = (Double) distance.pop();
            tmpTime = (Double) time.pop();

            if (tmpDis != endDistance && tmpTime != endTime){
                checkDifference = true;
            }
            popCount++;
        }
        //System.out.println("Pop count: " + popCount);

        double startDistance = tmpDis;
        double startTime = tmpTime;

        double finalDistance = endDistance - startDistance;
        double finalTime = endTime - startTime;

//        System.out.println("START DISTANCE: " + startDistance);
//        System.out.println("START TIME: " + startTime);
//        System.out.println("END DISTANCE: " + endDistance);
//        System.out.println("END TIME: " + endTime);
//        System.out.println("FINAL DISTANCE: " + finalDistance);
//        System.out.println("FINAL TIME: " + finalTime);


        double speed = (finalDistance/finalTime);
        float tmp = (float) speed;

        //System.out.println("DOUBLE SPEED: " + speed);


        return tmp;

    }
}

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

        multiplexer = new InputMultiplexer();
        for (int i = 0; i < 10 ; i++) {
            blockObj[i] = new Block(this, game);
            multiplexer.addProcessor(new GestureDetector(blockObj[i]));
        }

Яиспользуя переменную isActive, чтобы установить, какой блок используется в данный момент.Однако даже если это работает, как только следующий блок становится активным, он получает информацию из предыдущих блоков, такую ​​как местоположение перетаскивания.

Ответы [ 2 ]

0 голосов
/ 07 января 2019

Расширение класса BLOCK как Actor позволит вам присоединить слушателей к основному коду. Затем вы можете использовать:

for(Block block : blockobj)
{
  block.addListener(new InputListener(){  

   //You can add different listeners like ActorGestureListener etc...
   // press Ctrl + O while the cursor is inside this block to override methods.


 });


}
0 голосов
/ 05 января 2019

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

Однако, с небольшим рефакторингом, я думаю, вы можете получить именно то, что вы хотите. Во-первых, я рекомендую вам посмотреть сцены . Ваш Block класс должен расширяться Actor.

Делая это, мы можем использовать Блок со сценой и делать с ней много более сложных вещей. Вы обязательно должны взглянуть на метод hit() в актере. Вы захотите переопределить этот метод, чтобы Блок мог работать с сенсорными событиями.

Если вы посмотрите на раздел «Другие слушатели» того урока Scenes2d, который я связал выше, вы увидите, что он поддерживает ActorGestureListener.

Это, вероятно, потребует большого количества рефакторинга, и я не могу гарантировать, что это лучшее решение, потому что я не вижу весь ваш код и не знаю, что вы пытаетесь сделать, но что не так с вашим текущим установлено, что все блоки получают события при прикосновении к экрану, а не только фактически затронутые блоки.

...