SOLVED Android multi-touch not wortking...

FoxyOfJungle

Kazan Games
Hello!
So, I have a virtual joystick, but it only detects the click if the "device" is 0.
If I use a for loop, it doesn't recognize any clicks...


1 - This works:

GML:
for (var i = 0; i < 1; ++i) {
    if device_mouse_check_button(i, mb_left) {
        if point_in_circle(device_mouse_x_to_gui(i), device_mouse_y_to_gui(i), x, y, r) {
            ii.js_active = true;
        }
    } else {
        ii.js_active = false;
    }
}



2 - This doesn't works:

GML:
for (var i = 0; i < 4; ++i) {
    if device_mouse_check_button(i, mb_left) {
        if point_in_circle(device_mouse_x_to_gui(i), device_mouse_y_to_gui(i), x, y, r) {
            ii.js_active = true;
        }
    } else {
        ii.js_active = false;
    }
}


Notice in example 1 that I put 1 in the loop, using only device 0.
What am I doing wrong? Theoretically it should work...

Can anyone help? Thank you!
 

gnysek

Member
Cause your code says "if any device after previous isn't set/working set active to false even if you clicked already".

setting to false should be moved to before loop, and after setting active to true you should add break;
 

kburkhart84

Firehammer Games
It seems like your issue is because the touch is actually still just the first touch, but since you are not breaking out after you find a touch, you set it back.

1. Touch 1 works
2. The loop continues
3. Another touch isn't working, so it sets the variables as if no touch is there, despite the fact that the first touch was legit.

****EDIT Double Ninja'd...seems we all see the same thing and just worded it differently
 

FoxyOfJungle

Kazan Games
Thanks for the answers!
What you all said is correct, however I could not reset the variable to false in the same place (because if not, if I remove the mouse from the circle, it would reset to the starting position), only when I released the touch, so:

GML:
for (var i = 0; i < 4; ++i) {
        if device_mouse_check_button(i, mb_left) {
            ii.js_dir = point_direction(x, y, device_mouse_x_to_gui(i), device_mouse_y_to_gui(i));
            ii.js_dist = point_distance(x, y, device_mouse_x_to_gui(i), device_mouse_y_to_gui(i));
         
            if point_in_circle(device_mouse_x_to_gui(i), device_mouse_y_to_gui(i), x, y, r) {
                ii.js_active = true;
                break;
            }
        }
        if device_mouse_check_button_released(i, mb_left) {
            ii.js_active = false;
        }
    }
The break didn't make a difference there, but I put it just to keep from running the loop :)



Thanks!
 

gnysek

Member
@FoxyOfJungle After you said you can't reset variable before for-loop, I've tried to optimize your code a little to show that it's possible, plus to reduce functions used 3 times in a row, but then I came with much, much longer code :D I'm still posting it here only to show how different approaches can be to same feature, giving same results, but... I'm not happy with results šŸ¤£

GML:
/// create:

startx = 0;
starty = 0;
device = 0;

/// step:
if (device == -1) {
    var dmx, dmy;

    for (var i = 0; i < 4; ++i) {
        if device_mouse_check_button(i, mb_left) {
        
            dmx = device_mouse_x_to_gui(i);
            dmy = device_mouse_y_to_gui(i);
        
            if point_in_circle(dmx, dmy, x, y, r) {
                device = i;
                startx = dmx;
                starty = dmy;
                break;
            }
        }
    }
}
// no "else" here, so this code can be performed in same step after click is detected
if (device > -1) {
    ii.js_dir = point_direction(x, y, startx, starty);
    ii.js_dist = point_distance(x, y, startx, starty);
    
    if device_mouse_check_button_released(device, mb_left) {
        device = -1;
    }
}

// at end, device num is for sure proper now
ii.js_active = device > -1;
 

kburkhart84

Firehammer Games
Just as an FYI, I personally would have a single object be the "touch" controller. That object would simply have an array of structs, and each struct would have the typical input variables that apply, like down, pressed, released, timeHeld, screen x/y, and could even store extra helpers, like the vector direction from the original touch and the angle direction and distance. With all that helper information, all the joystick needs to do is loop through them like you are doing now, and "claim" a touch as soon as one is detected inside the boundaries, and then from then on, only check that touch index until the finger is lifted. This lets you track the finger outside of the joystick in case the player moves it too far.

The above system also makes it easy to do something like having a whole portion of the screen work for a sort of movable joystick. Like as soon as a finger lands anywhere on the left side of the screen, the joystick claims that touch index and centers the joystick where the finger first touched. If you store in the controller that the touch is claimed, then the other joystick on the right side of the screen could easily skip it when looking for its own finger to check.

Having a separate object handle this is the trick. Then your different objects for different types of joysticks could all access the data from the same place. It allows you to do things like simple buttons instead of joysticks as well, all in the same system, all using that one controller object to know where the fingers are.
 
Top