Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to Increase Area of touch by a certain percentage?

Ive been trying to develop this game where users have to click certain points on a image. Ive been storing these points based on their pixel locations. i can easily get the pixel pressed by getting the X and Y coordinates in the onTouch Event. But the problem im facing is that its practically impossible to press the exact location of the pixels every time( So for testing purposes ive set a tolerance to 40 px in all 4 directions). So is there a way i can set some sort of tolerance which can be adjusted from the settings menu so that it can be used by people with diff finger sizes with ease and played from different screen sizes? Any help or Suggestions is gratefully accepted

tolerance = 40
public boolean onTouchEvent(MotionEvent event) {
    // MotionEvent object holds X-Y values
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
        int XCood = (int) event.getX();
        int YCood = (int) event.getY();
        int XMin = ActXCod[index] - tolerance, 
            XMax = ActXCod[index] + tolerance, 
            YMin = ActYCod[index] - tolerance, 
            YMax = ActYCod[index] + tolerance;
        if (index < (limit - 1)) // loop to check number of images
        {
            if(XCood > XMin && XCood < XMax && YCood > YMin && YCood < YMax){
            //Do stuff
        }}}

here XMin and XMax are the min and max rage the X co-ordinate can be in and Ymin and Ymax are the min and max range of the Y co-ordinate.
XCood and YCood are the a and y coordinates of the users touch.

like image 803
Clinton Dsouza Avatar asked Sep 29 '22 13:09

Clinton Dsouza


2 Answers

I suggest you to take a look at the TouchDelegate, if I got your question right it should be exactly what you need. Once you have the tolerance from the settings, you can compute the proper amount of pixels to properly size the delegate.

There is some more information and sample code at http://developer.android.com/training/gestures/viewgroup.html#delegate

happy coding!

like image 134
Francesco Mapelli Avatar answered Oct 02 '22 15:10

Francesco Mapelli


users have to click certain points on a image tells me that rather than putting invisible/transparent buttons over the image, each with it's own event handling, you've opted to have any clicks on the image sent to one place and are going to decide what clicks go with what target.

enter image description here(a) enter image description here(b) enter image description here(c)

Which means if your image looked like (a) that you'd set up your dots (pixel locations) like (b):

This is understandably causing you problems since it's very hard for humans to hit those little targets.

You've decided the way to fix this is to give the human fatter fingers and are trying to calibrate how fat to make them. Lets try a use case where a user tries to dial 1238. In (c) I increase the size of their finger as they go. Since the press on 8 covered the dots from both 8 and 0 I'd say that's too big.

enter image description here(d) enter image description here(e) enter image description here(f)

(d) shows a reasonable size to calibrate with this approach. Notice that 1 and 3 still miss. 1 is a miss simply because these buttons aren't square. That's a limitation of this fat finger approach. 3 is a miss because the human actually missed and hit between the buttons. If you insist that 3 should count I don't know how we'd do it without 2, 5, & 6 counting as well. If that's what you want we need rectangular collision detection. More on that later.

Assuming 3 should be treated as a miss I'd like you to consider that (d) is mathematically identical to (e). It's achievable simply by adding the tolerance to the targets point not the users finger. 1 and 3 are still misses but now rather than being concerned with calibrating the fatness of a users finger, we only concern ourselves with how big the targets are.

Simply thinking this way gives us the freedom deal with the fact that our targets aren't square. They're rectangles. Doing that in (f) fixes 1 being missed. If you're targets are all the same size and proportional you don't need to deal with using different x and y tolerances. If you want to have the flexibility to change sizes so you can deal with that green button properly then stop modeling targets as a single point. Model them with a android.graphics.Rect. Actually I'd prefer you model them with their own class that contains a android.graphics.Rect but that's an OOP soap box I'll climb up some other time.

Assuming you've defined the target with a new Rect(left, top, right, bottom)] somewhere and assigned it to Rect r; you can now detect a hit with r.contains( (int) event.getX(), (int) event.getY() ); Since we've already thumbed our nose at the OOP gods and rejected the button idea I'd say for each click you loop thru all targets testing contains().

enter image description here(g)

Now, if you really insist that 2, 3, 5, and 6 should all trigger when the user misses hitting 3 then look into motionEvent.getSize(). That will measure the "fatness" of the touch from 0 to 1. If getToolMajor() or getTouchMajor() are available they might help you estimate the actual pixels touched. It may help to know the screen size but as far as I can tell from the documentation any pixel sizes produced by using any of this are going to be approximate. Some testing will help determine if this works as is or if any scaling constant is needed. This is likely smaller than you expect because these were designed for paint programs that give a bolder stroke with added pressure, not for watching your fingertip bump into things.

Use that like tolerance to build another Rect around the click (lets call it fatFinger). Test r.intersects(fatFinger) in a loop that supplies you with every r over your image. Every time it's true you've found another r to deal with.

That should give you something like (g). Now the 3 press is a 2, 3, 5, & 6 press, the 1 press is now a 1 & 4 press and the 8 press is a 8 & 0 press.

The 2 press is miraculously still just a 2 press. Pulling that off is nearly as hard as hitting the dots with touch dots. This might be fine for your game but please don't do it to my phone. :)

If you don't want to go insane, do a little OOP and make a class for your targets that contains a Rect and provide your own intersects method backed by the Rect one. That way you can loop them, get each t and when t.intersects(fatFinger) is true you can call your own t.wasTouched();

In short, fatten the targets, not the finger, unless you want it touching everything it comes near. If so, fatten both.

Regardless of if you decide to go with (f) or (g) I think you'll find much less of a need for the user to configure finger size if you take this approach. Happy coding!

like image 45
candied_orange Avatar answered Oct 02 '22 14:10

candied_orange