Handling touches

To get started with this conversation, add the OnTouchEvent method to the LiveDrawingView class:

@Override
public boolean onTouchEvent(MotionEvent motionEvent) {

   

   return true;
}

This is an overridden method and it is called by Android every time the user interacts with the screen. Look at the one and only parameter of onTouchEvent.

It turns out that motionEvent has a whole bunch of data tucked away inside of it, and this data contains the details of the touch that just occurred. The operating system sent it to us because it knows we will probably need some of it.

Notice that I said some of it. The MotionEvent class is quite extensive. It contains within it dozens of methods and variables.

Note

Over the course of this book, we will uncover quite a lot of them, but nowhere near all of them. You can explore the MotionEvent class here:

https://stuff.mit.edu/afs/sipb/project/android/docs/reference/android/vie w/MotionEvent.html.

Note that it is not necessary to do further research to complete this book.

For now, all we need to know is the screen coordinates at the precise moment when the player's finger was moved, touched the screen, or removed.

Some of the variables and methods contained within motionEvent that we will use include the following:

  • The getAction method, which, unsurprisingly, "gets" the action that was performed. Unfortunately, it supplies this information in a slightly encoded format, which explains the need for some of these other variables.
  • The ACTION_MASK variable, which provides a value known as a mask, which, with the help of a little bit more Java trickery, can be used to filter the data from getAction.
  • The ACTION_UP variable, which we can use to compare to see whether the action performed is the one (removing a finger) we want to respond to.
  • The ACTION_DOWN variable, which we can use to compare to see whether the action performed is the one we want to respond to.
  • The ACTION_MOVE variable, which we can use to compare to see whether the action performed is a move/drag.
  • The getX method notifies us of a horizontal floating point coordinate where the event happened.
  • The getY method notifies us of a vertical floating-point coordinate where the event happened.

As a specific example, say we need to filter the data returned by getAction using ACTION_MASK and see whether the result is the same as ACTION_UP. If it is, then we know that the user has just removed their finger from the screen; perhaps because they just tapped a button. Once we are sure that the event is of the correct type, we will need to find out where it happened using getX and getY.

There is one final complication. The Java trickery I referred to is the & bitwise operator, which is not to be confused with the logical && operator we have been using in conjunction with the if keyword.

The & bitwise operator checks to see whether each corresponding part in two values is true. This is the filter that is required when using ACTION_MASK with getAction.

Note

Sanity check. I was hesitant to go into detail about MotionEvent and bitwise operators. It is possible to complete this entire book and even a professional quality interactive app without ever needing to fully understand them. If you know that the line of code we write in the next section determines the event type the player has just triggered, that is all you need to know. I just guessed that a discerning reader such as yourself would like to know the ins and outs. In summary, if you understand bitwise operators, great, you are good to go. If you don't, it doesn't matter; you are still good to go. If you are curious about bitwise operators (there are quite a few), you can read more about them here: https://en.wikipedia.org/wiki/Bitwise_operation.

Now, we can code the onTouchEvent method and see all the MotionEvent stuff in action.

Coding the onTouchEvent method

You can handle the user moving their finger on the screen by adding the following highlighted code inside the onTouchEvent method to the code we already have:

// User moved a finger while touching screen
   if ((motionEvent.getAction() &
                 MotionEvent.ACTION_MASK)
                 == MotionEvent.ACTION_MOVE) {

          mParticleSystems.get(mNextSystem).emitParticles(
                       new PointF(motionEvent.getX(),
                                     motionEvent.getY()));

          mNextSystem++;
          if (mNextSystem == MAX_SYSTEMS) {
                 mNextSystem = 0;
          }
   }

   return true;

The if condition checks to see whether the type of event was the user moving their finger. If it was, then the next particle system in mParticleSystems has its emitParticles method called. Afterward, the mNextSystem variable is incremented and a test is performed to see whether it was the last particle system. If it was, then mNextSystem is set to zero ready to start reusing existing particle systems the next time one is required.

You can handle the user pressing one of the buttons by adding the following highlighted code right after the previous code we have just discussed, and before the return statement we have already coded:

// Did the user touch the screen
   if ((motionEvent.getAction() &
                 MotionEvent.ACTION_MASK)
                 == MotionEvent.ACTION_DOWN) {

          // User pressed the screen see if it was in a button
          if (mResetButton.contains(motionEvent.getX(),
                       motionEvent.getY())) {
                 // Clear the screen of all particles
                 mNextSystem = 0;
          }

          // User pressed the screen see if it was in a button
          if (mTogglePauseButton.contains(motionEvent.getX(),
                       motionEvent.getY())) {
                 mPaused = !mPaused;
          }
   }

   return true;

The condition of the if statement checks to see whether the user has tapped the screen. If they have, then the contains method of the RectF class is used in conjunction with getX and getY to see whether that press was inside one of our custom buttons. If the reset button was pressed, all the particles will disappear when mNextSystem is set to zero. If the paused button is pressed, then the value of mPaused is toggled, causing the update method to stop/start being called in the thread.

Finishing the HUD

Add the following highlighted code to the printDebuggingText method:

// We will add more code here in the next chapter
mCanvas.drawText("Systems: " + mNextSystem,
          10, mFontMargin + debugStart + debugSize * 2, mPaint);

mCanvas.drawText("Particles: " + mNextSystem * mParticlesPerSystem,
          10, mFontMargin + debugStart + debugSize * 3, mPaint);

This code will just print some interesting statistics to the screen to tell us how many particles and systems are currently being drawn.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.216.124.145