0
\$\begingroup\$

I have some trouble with my GestureListener class i think. I'm just trying to detect swipe on two half screen. I'm creating two InputListener but I can't add them to InputMultiplexer. Actually, I added with no trouble but it is not working as how I wanted. How can I detect two swipe(fling or pan whatever) events simultaneously ?

Maybe this picture will help you that you understand it.enter image description here

EDIT : It's from my Player1 class and the other class' contents are the same. (Player2)

private void listenInputs() {

    inputProcessor = new InputProcessor() {

        @Override
        public boolean keyDown(int keycode) {
            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) {
            if (canMove) {
                lastTouch.set(screenX, screenY);
                firstD = screenX;
            }
            return true;
        }


        @Override
        public boolean touchUp(int screenX, int screenY, int pointer, int button) {
            canMove = true;
            distance= 0;
            return true;
        }

        @Override
        public boolean touchDragged(int screenX, int screenY, int pointer) {

            Vector2 newTouch = new Vector2(screenX, screenY);
            distance = screenX - firstD;

            if (firstD < CarcleGame.HALF_SCREEN) {
                if (Math.abs(distance) > 20) {
                    if (canMove) {
                        canMove = false;
                        Vector2 delta = newTouch.cpy().sub(lastTouch);
                        if (delta.x > 0.7f)
                            move(true); // if it's true then go to the direction right, else go left
                        else if (delta.x < -0.7f)
                            move(false);

                        lastTouch = newTouch;
                    }
                }
            }
            return true;
        }
\$\endgroup\$
2
\$\begingroup\$

Use touchDragged() method the from Screen interface. Example taken from https://stackoverflow.com/questions/23731073/how-will-touchdragged-works-in-libgdx

private Vector2 lastTouch = new Vector2();

public boolean touchDown(int screenX, int screenY, int pointer, int button){
    lastTouch.set(screenX, screenY);
}

public boolean touchDragged(int screenX, int screenY, int pointer) {
    Vector2 newTouch = new Vector2(screenX, screenY);
    // delta will now hold the difference between the last and the current touch positions
    // delta.x > 0 means the touch moved to the right, delta.x < 0 means a move to the left
    Vector2 delta = newTouch.cpy().sub(lastTouch);
    lastTouch = newTouch;
}

Now if you want to detect which side made the 'drag', make some edits:

private final float HALF_SCREEN_WIDTH = Gdx.graphics.getWidth() / 2f;
private Vector2 lastTouch = new Vector2();

public boolean touchDown(int screenX, int screenY, int pointer, int button){
    lastTouch.set(screenX, screenY);
}

public boolean touchDragged(int screenX, int screenY, int pointer) {
    Vector2 newTouch = new Vector2(screenX, screenY);

    if(newTouch.x < HALF_SCREEN_WIDTH && lastTouch.x < HALF_SCREEN_WIDTH){
        // swipe on left side of the screen
    }else if(newTouch.x > HALF_SCREEN_WIDTH && lastTouch.x > HALF_SCREEN_WIDTH){
        // swipe on right side of the screen
    }else{
        // swipe made on both sides of the screen
    }
    Vector2 delta = newTouch.cpy().sub(lastTouch);
    lastTouch = newTouch;



}

Edited answer - supporting simultanousness

I assume you have a class which implements Screen (cause you said that you don't have a stage). In show() method set the InputProcessor to this so the screen can receive touch events. If you have more things to receive events from - make a multiplexer (I assume you know how to do this cause you said you've tried!)

How does it work?

There's a method: Gdx.input.isTouched() which tells you if the screen is touched. There's also one more method with the same name, but with an additional parameter: Gdx.input.isTouched(int pointer). This method was created to support multi-touch. If screen is touched it checks how many fingers are already touching it and it's incrementing the pointer and we can get each separate finger by passing a number to this method. Numbers start from 0, increment one by each finger and reset back to 0 when all fingers are released.

So if I touch the screen somewhere and check the 'pointer' variable in the touchDown() method (see below) - it will give me 0. If I hold the finger and put another one on the screen, pointer value will be 1, because I'm still touching the screen with the first finger (0 value is in use by the first touch).

So we have detected multiple screen touches. Now, let's write the support for the screen sides. We create 4 Vectors (vectors are just for storing touch coordinates here - x,y).

When we have a touchDown (see touchDown() method below) we make a loop to <= pointer so we can get all the current touches with Gdx.input.isTouched(pointer). Now, we check if the touch was made on the left or the right side of the screen.

If for instance left was touched - we set the leftStart vector to the touch position (we'll use this in touchUp() method). We also change leftStarted to true (you'll know why in a moment).

Now in the touchUp() method we iterate again so we can retrieve all the touchUp events. Again, for example, if we got a touchUp on the left side of the screen, we take the coordinates and set them to leftEnd vector.

Now, we can use a simple math to calculate the distance between leftStart and leftEnd points. We have the distance, we can check if it was longer than some value (MIN_SWIPE_DISTANCE in our case) and if it was - it was a left swipe. Right side works in the same manner.

Also, notice that after the successful touchUp we set leftStarted/rightStarted back to false.

Now, for the boolean leftStarted and rightStarted - it's just a protection for a situation when screen is touched on the left side and released on the right.

Let's see:

If we touch the screen on the left side, leftStarted is true so touchUp() will know that this move was legit. But! Let's say that we touched the screen on the right side (touchDown) and swiped it to the left side. TouchUp fires and checks if 'leftStarted is true' - it's false, which is correct cause we didn't start the swipe on the left side, but on the right side.

I hope you get the idea! :) If you have any questions, feel free.

// these are class fields!
private Vector2 leftStart = new Vector2(), leftEnd = new Vector2();
private Vector2 rightStart = new Vector2(), rightEnd = new Vector2();

private boolean leftStarted = false, rightStarted = false;

private final float MIN_SWIPE_DISTANCE = 50f;

@Override
public void show() {
    // or without multiplexer, do what you want there
    InputMultiplexer plex = new InputMultiplexer(this);
    Gdx.input.setInputProcessor(plex);
}

@Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {

    for(int i=0;i<=pointer;i++){

        if(screenX < HALF_SCREEN_WIDTH) // left touched
        {
            leftStart.set(screenX, screenY);
            leftStarted = true;
        }

        if(screenX > HALF_SCREEN_WIDTH) // right touched
        {
            rightStart.set(screenX, screenY);
            rightStarted = true;
        }

    }
    return false;
}

@Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {

    for(int i=0;i<=pointer;i++){

        if(screenX < HALF_SCREEN_WIDTH && leftStarted) // left released
        {
            leftStarted = false;
            leftEnd.set(screenX, screenY);
            double distance = Math.sqrt((leftEnd.x - leftStart.x) * (leftEnd.x - leftStart.x) +
                    (leftEnd.y - leftStart.y) * (leftEnd.y - leftStart.y));


            if(distance > MIN_SWIPE_DISTANCE){
                // left swipe!
                System.out.println("Left swipe!");
            }

        }

        if(screenX > HALF_SCREEN_WIDTH && rightStarted) // right released
        {
            rightStarted = false;
            rightEnd.set(screenX, screenY);

            double distance = Math.sqrt((leftEnd.x - leftStart.x) * (leftEnd.x - leftStart.x) +
                    (leftEnd.y - leftStart.y) * (leftEnd.y - leftStart.y));

            if(distance > MIN_SWIPE_DISTANCE){
                // right swipe!
                System.out.println("Right swipe!");
            }
        }

    }
    return false;
}

For now it supports sides (left/right) but it doesn't support detection if the swipe was made 'up' or 'down' etc. It detects all directions. If you'd like to implement these, let me know and I'll add this ;)

\$\endgroup\$
  • \$\begingroup\$ Firstly thank you so much for your answer. I've tried it. I've tried it with 50 different way .Everything is working perfectly with your code BUT it doesn't detect SIMULTANEOUSLY. I also tried it with InputMultiplexer but doesn't work. \$\endgroup\$ – İbrahim Kasapoğlu Dec 1 '16 at 0:15
  • \$\begingroup\$ Simultaneousness will be hard to implement here, but you should try using this approach stackoverflow.com/questions/25399396/…. You should catch inputs with Gdx.input.isTouched() in render() method and do some math there with loops for taking the input twice. When I get some free time today or tomorrow I'll write it. \$\endgroup\$ – Jacob Dec 1 '16 at 8:06
  • \$\begingroup\$ Thank you for suggestion. I studied on it tonight and I can just say one thing that I'am so confused.. I did not understand anything. Should I write all the code in "for" loop and how is it possible ? I am looking forward to your next answer. If you write me some example code I will really appreciate. Also I'm gonna edit my question with my code which includes Touch Events \$\endgroup\$ – İbrahim Kasapoğlu Dec 1 '16 at 20:45
  • \$\begingroup\$ I'll write the code tomorrow morning. It's not that trivial task as it looks like for the first time. By the way, I thought about one more solution. There's a DragListener class in GDX which you can add to an Actor and the listener will detect drag events on it. If you have some free time today you could create two actors, add them to the stage and set the first's position to 0,0 and dims to screen_width/2, screen_height and second pos: screen_width/2, 0 and dims same as the first so the fiil the whole screen. Add two DragListeners to them and check if this will work simultanously ;> \$\endgroup\$ – Jacob Dec 1 '16 at 22:15
  • 1
    \$\begingroup\$ After the spend so many time we finally did it! Your answer/edit were very clear. I have never understand that what does it the "pointer". Strictly speaking; I didn't aware that there is a "pointer" even. In your suggestion, when user' touch up then move. But I don't wanted this and I some edited and I try to transport it into TouchDragged. The result is perfect ! It works like a charm ! You saved my day, you even saved my life ! Thank you so much for everything. \$\endgroup\$ – İbrahim Kasapoğlu Dec 2 '16 at 22:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.