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:
- In the Android Studio menu bar select Tools | Android AVD Manager.
- 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.
- 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.
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.
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.
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 toonCreate
- Which then called
draw
The game is now currently at the "Wait For Input" phase, just as it should be according to the flowchart.
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.