Learning Java by Building Android  Games
上QQ阅读APP看书,第一时间看更新

Linking up our methods

So far, we know that we can define methods with code like this:

void draw(){
   // Handle all the drawing here
}

And we can call/execute methods with code like this:

draw();

We have also alluded to, as well as mentioned in our comments that the onCreate method (provided automatically by Android) will handle the One-time Setup part of the flowchart.

The reason for this is that all Android games (and the vast majority of other Android apps) must have an Activity class as the starting point. Activity is what interacts with the operating system. Without one the operating system cannot run our code. The way that the operating system interacts with and executes our code is through the methods of the Activity class. There are many methods in the Activity class but the one we care about right now is onCreate.

The onCreate method is called by Android itself when the player taps our game's icon on their screen.

Note

Actually, there are a number of methods that are called but onCreate is enough to complete the Sub' Hunter game. As we write more complicated games we will learn about and use more methods that the operating system can call.

All we need to know for now is to put the One-time Setup code in onCreate and we can be sure it will be executed before any of the other methods we write.

We want to call newGame from the end of onCreate and after that, we want to initially draw the screen, so we also call draw too. Add this highlighted code shown next.

/*
   Android runs this code just before
   the app is seen by the player.
   This makes it a good place to add
   the code that is needed for
   the one-time setup.
 */

@Override
protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);

   Log.d("Debugging", "In onCreate");
   newGame();
 draw();
}

So that we can track the flow of the code and perhaps if necessary debug our game the previous code not only calls newGame followed by draw but it also contains this line of code.

Log.d("Debugging", "In onCreate");

This code will print out a message in Android Studio to let us know that we are "Debugging" and that we are "In OnCreate". Once we have connected the rest of the methods we will view this output to see whether our methods work as they should.

Now let's print some text in newGame so we can see it being called as well. Add the highlighted code.

/*
   This code will execute when a new
   game needs to be started. It will
   happen when the app is first started
   and after the player wins a game.
 */
public void newGame(){
   Log.d("Debugging", "In newGame");
   
}

After this, to implement the course of our flowchart we need to call takeShot from onTouchEvent. Note as well that we are printing some text for tracking purposes here also. Remember that onTouchEvent is called by Android when the player touches the screen. Add the highlighted code to onTouchEvent.

/*
   This part of the code will
   handle detecting that the player
   has tapped the screen
 */
@Override
public boolean onTouchEvent(MotionEvent motionEvent) {
   Log.d("Debugging", "In onTouchEvent");
   takeShot();
   
   return true;
}

Let's complete all the connections. Add a call to draw and some debugging text into takeShot as per the flowchart and shown next.

/*
   The code here will execute when
   the player taps the screen It will
   calculate the distance from the sub'
   and determine a hit or miss
 */
void takeShot(){
   Log.d("Debugging", "In takeShot");
   draw();
}

In the draw method, we will just print to Android Studio to show it is being called. Remember that on the flowchart after we do the drawing we wait for touches. As the onTouchEvent method handles this and receives a call directly from Android there is no need to connect draw to onTouchEvent.

Note

The connection between Android and onTouchEvent is permanent and never broken. We will explore how this works when we talk about threads in Chapter 9, The Game Engine, Threads and The Game Loop.

Add the highlighted code shown next to the draw method.

/*
   Here we will do all the drawing.
   The grid lines, the HUD,
   the touch indicator and the
   "BOOM" when a sub' is hit
 */
void draw() {
   Log.d("Debugging", "In draw");
}

Note that we haven't added any code to printDebuggingText or boom. Neither have we called these methods from any of the other methods. This is because we need to learn some more Java then do more coding before we can add any code to these methods.

In our tests when the screen is clicked, onTouchEvent which is analogous to the "Wait For Input" phase will call takeShot, which in turn will call the draw method. Later in this project takeShot will make a decision to either call draw or boom depending upon whether the player taps on the grid square with the sub' in it or not.

We will also add a call to printDebugging text once we have some data to debug.

Start the emulator if it isn't already running by following these same steps from Chapter 1, Java, Android and Game Development:

  1. In the Android Studio menu bar select Tools | Android AVD Manager.
  2. Notice there is an emulator in the list. In my case, it is Pixel API 25. If you are following this later it will likely be a different emulator that was installed by default. It won't matter. Click the green play icon.
  3. Now you can click the play icon in the Android Studio quick-launch and when prompted choose Pixel API 25 (or whatever your emulator is called) and the game will launch on the emulator.

Now open the logcat window by clicking the Android Monitor tab at the bottom of the screen as shown in the next image.

Linking up our methods

In the logcat window, we can see that when we start the game that lots of text has been output to logcat. This next image is a snapshot of the entire logcat window to make sure you know exactly where to look.

Linking up our methods

This next image is zoomed in on the three relevant lines, so you can clearly see the output even in a black and white printed book.

Linking up our methods

In future, I will show only the most relevant part of the logcat output as text in a different font like this.

Debugging: In onCreate
Debugging: In newGame
Debugging: In draw

Hopefully, the font and the context of the discussion will make it clear when we are discussing logcat output and when we are discussing actual code.

What we can gather from all this is that:

  • When the game was started the onCreate method was called (by Android)
  • Followed by the newGame method which executed then returned to onCreate
  • Which then called draw

The game is now currently at the "Wait For Input" phase, just as it should be according to the flowchart.

Linking up our methods

Now, go ahead and click the screen. Then we should see that the onTouchEvent, takeShot and then draw methods are called, in that order. The logcat output might not be exactly what you expect, however. Here is the logcat output I received after clicking the screen of the emulator.

Debugging: In onTouchEvent
Debugging: In takeShot
Debugging: In draw
Debugging: In onTouchEvent
Debugging: In takeShot
Debugging: In draw

As we can see from the output, exactly the correct methods were called. However, they were called twice.

What is happening is that the onTouchEvent method is very versatile and it is detecting a touch when you click the mouse button (or finger) down and it is also called when the mouse button (or finger) is released. To simulate a tap, we only want to respond to releases (finger up).

To code this functionality, we need to learn some more Java, specifically, we need to learn how to read and compare variables then make decisions based on the result.

Variables are our game's data. We will cover everything we need to know about variables in the next chapter and we will make decisions based on the value of those variables in Chapter 7, Making Decisions with Java If, Else and Switch when we put the finishing touches (pun intended) to Sub' Hunter.