Wednesday, January 29, 2020

android - LibGDX Swipe Detection Left and Right


I have displayed an image at the center of the screen with libgdx. If I swipe left, the image should move to the left; and, if I swipe right, image should move to the right.


Subsequent swipes to the left should move the image left. The same should happen for right. I used GestureListener.


It works to some extent in the sense if I swipe left first image moves left. But after that if I try to swipe right the image still moves left.


So how do I implement the expected behavior?


class MyGestureListener implements GestureListener {
@Override
public boolean fling(float velocityX, float velocityY, int button) {
if (velocityX>0)
iX += 20;

else
iX -= 20;
System.out.println("iX: "+iX);
return true;
}
}

// ...
Gdx.input.setInputProcessor(new GestureDetector(0.0f, 0.0f, 0.0f, 5f, new MyGestureListener()));


// ...
batch.draw(splashTexture, iX, iY);

Answer



There are a few potential problems here. Lets take a look at your code first:


if(arg0>0)
iX += 20;
else
iX-=20;

arg0 is the velocityX of the last known horizontal velocity of the finger in pixels per second. Here's the method signature for fling():




fling


boolean fling(float velocityX, float velocityY, int button)


Called when the user dragged a finger over the screen and lifted it. Reports the last known velocity of the finger in pixels per second.


 Parameters: 
velocityX - velocity on x in seconds
velocityY - velocity on y in seconds

So, the method is not taking in ALL the data of the swipe, it's merely taking the final position info. What happens if you ended your swipe without any horizontal velocity? According to your code, the answer would be, move left because the X velocity in the final position would be zero.


if(arg0>0)  

iX += 20;
else // This includes X == 0 because you only checked greater than!
iX-=20;

What happens if you swipe upwards? According to your code, the final position would be move left, because arg1 has the upwards movement and is being ignored. What happens if you swipe downwards? According to your code, the final position would be move left. What happens if you swipe a little to the right and a little to the left? Move left.


I think what you want to do instead is something along the following lines:


   @Override
public boolean fling(float velocityX, float velocityY, int button) {
if(Math.abs(velocityX)>Math.abs(velocityY)){
if(velocityX>0){

iX+=20;
}else if (velocityX<0){
iX-=20;
} else {
// Do nothing.
}
}else{

// Ignore the input, because we don't care about up/down swipes.
}

return true;
}

A few additional notes:




  • Debugging: For debugging, I recommend that you log not only the resulting iX, but also the incoming arg0 (velocityX) values. I strongly suspect that a few minutes of looking at the input data will resolve the issue. In particular, you're going to want to know if this method is receiving zero values (which with your code will move the image left), if it's receiving non-negative values when it should be receiving negative values, and so forth.




  • Set the MaxFlingDelay: A word about fling(): fling() is not always called. You need to set the maxFlingDelay in the GestureDetector constructor for the amount you want to trigger a fling(), otherwise it uses a default value, which you may not be happy with.





  • Consider Pan and Other Alternatives:Consider alternatives to fling() including pan(). As has been noted by Benjamin, you may want pan() instead (or something else). That's an excellent suggestion and possible solution.




  • Run a Gesture Detector Test: To help decide on whether to use fling() and to see if fling() is giving the right values, play around with this gesture detector test.




  • Consider the Return Boolean: When you return true in this method, you're signalling that the input has been handled and shouldn't be processed further. That's not descriptive of the code sample I gave you (where up/down flings are ignored, for example). You may want to modify it to put the proper return trues/return falses in the appropriate places, so you don't run into unexpected behavior later if you implement other touch handling for nearby entities.





  • Variable Names: This is just a minor pet-peeve. It makes things much easier to read if you use descriptive variable names (like velocityX, velocityY, above) instead of Arg0, Arg1, iX, and so on. You asked above why you received a downvote. Don't know why somebody gave it, but sometimes code with bad naming conventions rubs people the wrong way.




No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...