I am trying to make it so that the game piece (red square) cannot be moved unless the player initially clicks on it, but can then drag it freely until releasing it. Currently, if the player clicks anywhere on the the screen the game piece will move to their cursor/finger when they start moving it. If I try to use something like:
case MotionEvent.ACTION_DOWN: //player pressing down if (gamePiece.getRectangle().contains((int) event.getX(), (int) event.getY())) { switch (event.getAction()) {; case MotionEvent.ACTION_MOVE: //player moving their finger gamePiecePoint.set((int) event.getX(), (int) event.getY() - 100); { }
Checking that the block contains the Point where the player clicked does prevent the player from moving, but it makes movement VERY inconsistent, because the cursor doesn’t stay directly on the game piece while moving.
What I want to do is require an initial touch on the game piece, then allow movement freely until they release the block. I’m just not sure how to accomplish this.
This is my current onTouchEvent implementation. the if statement in the ACTION_DOWN case prevents the block from snapping to the players Point immediately, but when the cursor is moved the game piece moves to it.
@Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: //player pressing down if (!(gamePiece.getRectangle().contains((int) event.getX(), (int) event.getY()))) { break; } case MotionEvent.ACTION_MOVE: //player moving their finger gamePiecePoint.set((int) event.getX(), (int) event.getY() - 100); //GameBoard.checkInteraction(gamePiecePoint); break; case MotionEvent.ACTION_UP: gamePiecePoint = GameBoard.checkInteraction(gamePiecePoint); break; } return true; //return super.onTouchEvent(event); }
EDIT: From suggestions by @Nicola I changed my switch-case block to the following (defined wasClicked at class level)…
switch (event.getAction()) { case MotionEvent.ACTION_DOWN: //player pressing down // Check if action down happened inside the gamePiece wasClicked = gamePiece.getRectangle().contains((int) event.getX(), (int) event.getY()); case MotionEvent.ACTION_MOVE: //player moving their finger if (wasClicked) { gamePiecePoint.set((int) event.getX(), (int) event.getY() - 100); } case MotionEvent.ACTION_UP: gamePiecePoint = GameBoard.snapToNearest(gamePiecePoint); // Snaps player gamePiece to nearest tile on release }
I did notice that if I put wasClicked = false;
into the ACTION_UP case it breaks the system and I can only move the gamePiece a small amount at a time. I am not 100% sure why this is happening, but when I used system.out to monitor ACTION_UP from console, I noticed that it triggers constantly as I am moving the piece, and not just when I release the block. I’m not sure this is intended, but it works without it so I am satisfied for now. Thank you so much!!
Advertisement
Answer
Creating a flag canMovePiece
could help.
When ACTION_DOWN
happens we can set canMovePiece
to true
if the coordinates of the event are contained inside the red square, if they’re not nothing happens.
Now, if the flag is true
we know that the player can move the red square, so everytime ACTION_MOVE
happens (don’t create a switch-case
block inside the ACTION_DOWN
, you could just use a single switch-case
inside the onTouchEvent()
) it’s possible to check the value of the flag: if it’s true
, we get the current x
and y
of the movement and update the position of the red square. If it’s false
, nothing happens.
I think this should be enough to establish a real-time movement of the red square based on the cursor (finger) position. When ACTION_UP
happens we should only set the flag to false
to start with another action in the future.