- Learning Java by Building Android Games
- John Horton
- 938字
- 2021-07-23 19:02:35
Coding the PongActivity class
In this project, as discussed previously, we will have multiple classes. Four to be exact. The Activity
class provided by the Android API is the class that interacts with the operating system. We have already seen how the OS interacts with onCreate
when the player clicks the app icon to start an app (or our game). Furthermore, we have seen how the operating system calls the onTouchEvent
method when the user interacts with the screen, giving us the opportunity to make our game respond appropriately.
As this game is more complicated and needs to respond in real-time it is necessary to use a slightly more in-depth structure. At first this seems like a complication but in the long run, it makes our code more simple and easy to understand.
Rather than have a class called Pong
(analogous to SubHunter
) that does everything, we will have a class which just handles start-up and shutdown of our game as well as help a bit with initialization by getting the screen resolution. It makes sense that this class will be of type Activity
.
However, as you will soon see, we will delegate interacting with touches to another class, the same class that will also handle almost every aspect of the game- kind of like a game engine. This will introduce us to some interesting concepts that will be new to us.
Let's get started with coding the Activity
-based class. We called this class PongActivity
and it was auto-generated for us when we created the project in the previous chapter.
Add the first part of the code for the PongActivity
class.
import android.app.Activity; import android.graphics.Point; import android.os.Bundle; import android.view.Display; public class PongActivity extends Activity { private PongGame mPongGame; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Display display = getWindowManager().getDefaultDisplay(); Point size = new Point(); display.getSize(size); mPongGame = new PongGame(this, size.x, size.y); setContentView(mPongGame); } }
Notice it all looks very familiar. In fact, except for the mPongGame
object of type PongGame
all the code in the previous block, we saw the same in the Sub' Hunter project. I won't go through again how we get the screen resolution with display
, size
, and getSize
. I will go through in full detail what we are doing with this new object. It might look quite strange at first.
The first new thing is that we are declaring an instance of our PongGame
class. Currently, this is an empty class.
private PongGame mPongGame;
In the previous code, we begin using the m
prefix for member variables. This is a code formatting convention to avoid getting confused about the scope of our variables. Also notice it is declared as a member should be, outside of any methods.
Tip
Now that we will be creating lots of classes, including with constructors and methods with parameters, prefixing m
to the start of all member variables will avoid getting confused about which variables belong to the instance of the class and which only have scope within a method.
In onCreate
after we have done our usual thing with display
etc, we initialize mPongGame
like this
mPongGame = new PongGame(this, size.x, size.y);
What we are doing is passing three arguments to the PongGame
constructor. We have obviously not coded a constructor and as we know the default constructor takes zero arguments. Therefore, this line will cause an error until we fix this soon.
The arguments passed in are interesting. First, this
, which is a reference to PongActivity
. The PongGame
class will need to perform actions (use methods) that it needs this reference for.
The second and third arguments are the horizontal and vertical screen resolution. It makes sense that our game engine (PongGame
) will need these to perform tasks like detecting the edge of the screen and scaling the other game objects to an appropriate size. We will discuss these arguments further when we get to coding the PongGame
constructor.
Next look at the even stranger line that follows
setContentView(mPongGame);
This is where in the SubHunter
class we set the ImageView
as the content for the app. Remember that the Activity
class' setContentView
method must take a View
object and ImageView
is a View
. This previous line of code seems to be suggesting that we will use our PongGame
class as the visible content for the game? But PongGame
isn't a View
. Not yet anyway.
We will fix the constructor and the not-a-View
problem after we add a few more lines of code to PongActivity
.
Note
Reader challenge
Can you guess which OOP concept the solution might be?
Add these two overridden methods and then we will talk about them. Add them below the closing curly brace of onCreate
but before the closing curly brace of PongActivity
.
@Override protected void onResume() { super.onResume(); // More code here later in the chapter } @Override protected void onPause() { super.onPause(); // More code here later in the chapter }
What we have done is to override two more of the methods of the Activity
class. We will see why we need to do this, what we will do inside these methods and just as important, when Android will call these methods, later in this chapter. The point to note here is that by adding these overridden methods we are giving the OS the opportunity to notify us of the player's intentions in two more situations. What exactly resuming and stopping entails will be fully explained later in this chapter.
It makes sense at this point to move on to the PongGame
class, the main class of this game. We will come back to PongActivity
near the end of the chapter.