javaandroidandroid-studiotouch-eventmulti-touch

Why does my multi-touch event not work in my Android Studio App?


Around line 12 of this exempt I have marked a section where the code never gets executed. In the ACTION_POINTER_DOWN, everything else works, so if the joystick is pressed the else if statement sets joystick.setIsPressed() to true which sets joystick.getIsPressed() to true so the first if statement should be true, therefore executing code which I marked and also checking the if statement above it.

    @Override
public boolean onTouchEvent(MotionEvent event) {

    switch (event.getActionMasked()) {
        case MotionEvent.ACTION_DOWN:
        case MotionEvent.ACTION_POINTER_DOWN:
            if (joystick.getIsPressed()) {
                // Joystick was pressed before this event
                if (event.getX() > screenX / 2 && event.getY() > screenY / 2) {
                    cat.isJumping = true;
                }
                // Code here never gets executed
            } else if(joystick.isPressed((double) event.getX(), (double) event.getY())) { // Joystick is pressed in this event and ID stored
                joystickPointerId = event.getPointerId(event.getActionIndex());
                joystick.setIsPressed(true);
            } else { // Joystick was not previously, and is not pressed in this event
                if (event.getX() > screenX / 2 && event.getY() > screenY / 2) {
                    cat.isJumping = true;
                }
            }

            if(event.getX() >= mainMenuButton.getValue(1) &&
                    event.getX() <= mainMenuButton.getValue(3) &&
                        event.getY() >= mainMenuButton.getValue(2) &&
                            event.getY() <= mainMenuButton.getValue(4)) {
                isPlaying = false;
                activity.startActivity(new Intent(activity, MainActivity.class));
                activity.overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
                activity.finish();

            }
            break;

        case MotionEvent.ACTION_MOVE:
            if(joystick.getIsPressed()) {
                joystick.setActuator((double) event.getX(), (double) event.getY());
            }
            break;

        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_POINTER_UP:
            if (joystickPointerId == event.getPointerId(event.getActionIndex())) { // Joystick was let go of
                joystick.setIsPressed(false);
                joystick.resetActuator();
            }
            cat.isJumping = false;
            break;
    }
    return true;
}

Here's my Joystick.java class for reference:

package com.example.combatcats;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;

import androidx.core.graphics.ColorUtils;


public class Joystick {

private int outerCircleCenterPositionX;
private int outerCircleCenterPositionY;
private int innerCircleCenterPositionX;
private int innerCircleCenterPositionY;
private int outerCircleRadius;
private int innerCircleRadius;
private Paint outerCirclePaint;
private Paint innerCirclePaint;
private double joystickCenterToTouchDistance;
private boolean isPressed;
private double actuatorX;
private double actuatorY;

public Joystick(int centerpositionX, int centerpositionY, int outerCircleRadius, int innerCircleRadius) {

    outerCircleCenterPositionX = centerpositionX;
    outerCircleCenterPositionY = centerpositionY;
    innerCircleCenterPositionX = centerpositionX;
    innerCircleCenterPositionY = centerpositionY;

    this.outerCircleRadius = outerCircleRadius;
    this.innerCircleRadius = innerCircleRadius;

    outerCirclePaint = new Paint();
    outerCirclePaint.setColor(ColorUtils.setAlphaComponent(Color.GRAY,125));
    outerCirclePaint.setStyle(Paint.Style.FILL_AND_STROKE);

    innerCirclePaint = new Paint();
    innerCirclePaint.setColor(ColorUtils.setAlphaComponent(Color.BLUE,125));
    innerCirclePaint.setStyle(Paint.Style.FILL_AND_STROKE);



}

public void draw(Canvas canvas) {

    canvas.drawCircle(
            outerCircleCenterPositionX,
            outerCircleCenterPositionY,
            outerCircleRadius,
            outerCirclePaint
    );

    canvas.drawCircle(
            innerCircleCenterPositionX,
            innerCircleCenterPositionY,
            innerCircleRadius,
            innerCirclePaint
    );
}
public void update() {
    updateInnerCirclePosition();
}

private void updateInnerCirclePosition() {
    innerCircleCenterPositionX = (int) (outerCircleCenterPositionX + actuatorX*outerCircleRadius);
    innerCircleCenterPositionY = (int) (outerCircleCenterPositionY + actuatorY*outerCircleRadius);

}

public boolean isPressed(double touchPositionX, double touchPositionY) {
    joystickCenterToTouchDistance = Math.sqrt(
            Math.pow(outerCircleCenterPositionX - touchPositionX, 2) +
            Math.pow(outerCircleCenterPositionY - touchPositionY, 2)
    );
    return joystickCenterToTouchDistance < outerCircleRadius;
}

public void setIsPressed(boolean isPressed) {
    this.isPressed = isPressed;
}

public boolean getIsPressed() {
    return isPressed;
}

public void setActuator(double touchPositionX, double touchPositionY) {
    double deltaX = touchPositionX - outerCircleCenterPositionX;
    double deltaY = touchPositionY - outerCircleCenterPositionY;
    double deltaDistance = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));

    if(deltaDistance < outerCircleRadius) {
        actuatorX = deltaX/outerCircleRadius;
        actuatorY = deltaY/outerCircleRadius;
    } else {
        actuatorX = deltaX/deltaDistance;
        actuatorY = deltaY/deltaDistance;
    }
}

public void resetActuator() {
    actuatorX = 0.0;
    actuatorY = 0.0;
}

public double getActuatorX() {
    return actuatorX;
}
public double getActuatorY() {
    return actuatorY;
}
}

Solution

  • The multi-touch works, the event.getX() and event.getY() were the problem.

    The solution is to input a pointer id like this:

            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_POINTER_DOWN:
                if (joystick.getIsPressed()) {
                    // Joystick was pressed before this event
                    secondPointerId = event.getPointerId(event.getActionIndex());
                    if (event.getX(secondPointerId) > screenX / 2 && event.getY(secondPointerId) > screenY / 2) {
                        cat.isJumping = true;
                    }