Search code examples
javaandroidtouch-event

onTouchEvent() not working as I intend


Following: https://developer.android.com/training/gestures/movement.html

for handling movement in an onTouchEvent. My problem is though that it seems the touch is never registered, even when following the tutorial linked.

Code:

public class Sprite extends Activity {

private static final int BMP_ROWS = 4;
private static final int BMP_COL = 3;
private int x, y = 0;
private int speedx, speedy = 5;
private int currentFrame = 0;
private int width, height;
private float xTouch, yTouch;
private VelocityTracker mVelocityTracker = null;
private GameView gameView;
private Bitmap bmp;

int [] DIRECTION_TO_ANIMATE_MAP = {3, 1, 0, 2};

public Sprite(GameView gameView, Bitmap bmp) {
    this.gameView = gameView;
    this.bmp = bmp;
    this.width = bmp.getWidth() / BMP_COL;
    this.height = bmp.getHeight() / BMP_ROWS;
}

private void Update() {
    if (x >= gameView.getWidth() - width - speedx|| x + speedx <= 0) {
    }

    if (y >= gameView.getHeight() - height - speedy || y + speedy <= 0) {
    }

    currentFrame = ++currentFrame % BMP_COL;
}

public boolean onTouchEvent(MotionEvent event) {
    int index = event.getActionIndex();
    int action = event.getActionMasked();
    int pointerId = event.getPointerId(index);

    synchronized (gameView.getHolder()) {
        if (this.isCollition(event.getX(), event.getY())) {
            Log.d("", "Sprite touched!");
        }

        switch (action) {
            case MotionEvent.ACTION_DOWN:
                if (mVelocityTracker == null) {
                    mVelocityTracker = VelocityTracker.obtain();
                } else {
                    mVelocityTracker.clear();
                }

                xTouch = event.getX();
                yTouch = event.getY();
                Log.d("", "You clicked: " + Float.toString(xTouch) + "," + Float.toString(yTouch));
                mVelocityTracker.addMovement(event);
                break;

            case MotionEvent.ACTION_MOVE:
                mVelocityTracker.addMovement(event);
                mVelocityTracker.computeCurrentVelocity(1000);
                Log.d("", "X velocity: " + VelocityTrackerCompat.getXVelocity(mVelocityTracker, pointerId));
                Log.d("", "Y velocity: " + VelocityTrackerCompat.getYVelocity(mVelocityTracker, pointerId));
                break;

            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                mVelocityTracker.recycle();
                break;

        }
    }

    boolean ret = super.onTouchEvent(event);
    return ret;
}

public void onDraw(Canvas canvas) {
    MotionEvent event = null;
    Update();

    int srcX = 1 * width;
    int srcY = 0 * height;

    Rect src = new Rect(srcX, srcY, srcX + width, srcY + height);
    Rect dst = new Rect(x, y, x + width, y + height);
    canvas.drawBitmap(bmp, src, dst, null);

}

public boolean isCollition(float x2, float y2) {
    return x2 > x && x2 < x + width && y2 > y && y2 < y + height;
}
}

I get a logcat message each time I touch the sprite but whenever i touch the screen or swipe I get nothing. I realise that the most possible reason is me not utilizing onTouchEvent properly but I've tried implementing some of the things suggested in other questions but without luck.


EDIT:

It was as suggested below my game logic that was wrong here. I had the onTouchEvent in a wrong class. When I changed it into the view class it works perfectly:

public class GameView extends SurfaceView {

private Bitmap bmp;
private SurfaceHolder holder;
private GameLoop gameLoop;
private Sprite sprite;
private int x = 0;
private long lastClick;
private VelocityTracker mVelocityTracker;
private float xTouch;
private float yTouch;

public GameView(Context context) {
    super(context);
    gameLoop = new GameLoop(this);
    holder = getHolder();
    holder.addCallback(new SurfaceHolder.Callback() {

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
        }

        @SuppressLint("WrongCall")
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            gameLoop.setRunning(true);
            gameLoop.start();
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        }

    });

    bmp = BitmapFactory.decodeResource(getResources(), R.drawable.image);
    sprite = new Sprite(this, bmp);
}

@Override
protected void onDraw(Canvas canvas) {
    canvas.drawColor(Color.BLACK);
    sprite.onDraw(canvas);
}

public boolean onTouchEvent(MotionEvent event) {
    int index = event.getActionIndex();
    int action = event.getActionMasked();
    int pointerId = event.getPointerId(index);

    synchronized (getHolder()) {
        if (sprite.isCollition(event.getX(), event.getY())) {
            Log.d("", "Sprite touched!");
        }

        switch (action) {
            case MotionEvent.ACTION_DOWN:
                if (mVelocityTracker == null) {
                    mVelocityTracker = VelocityTracker.obtain();
                } else {
                    mVelocityTracker.clear();
                }

                xTouch = event.getX();
                yTouch = event.getY();
                Log.d("", "You clicked: " + Float.toString(xTouch) + "," + Float.toString(yTouch));
                mVelocityTracker.addMovement(event);
                break;

            case MotionEvent.ACTION_MOVE:
                mVelocityTracker.addMovement(event);
                mVelocityTracker.computeCurrentVelocity(1000);
                Log.d("", "X velocity: " + VelocityTrackerCompat.getXVelocity(mVelocityTracker, pointerId));
                Log.d("", "Y velocity: " + VelocityTrackerCompat.getYVelocity(mVelocityTracker, pointerId));
                break;

            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                mVelocityTracker.recycle();
                break;

        }
    }

    boolean ret = super.onTouchEvent(event);
    return ret;
}
}

Solution

  • check your game logic again and handle return value manually, instead of super.onTouchEvent(event);