Home Game Development Learning Java by Building Android Games - Third Edition

Learning Java by Building Android Games - Third Edition

By John Horton
books-svg-icon Book
eBook $30.99
Print $38.99
Subscription $15.99
$10 p/m for first 3 months. $15.99 p/m after that. Cancel Anytime!
What do you get with a Packt Subscription?
This book & 7000+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook + Subscription?
Download this book in EPUB and PDF formats, plus a monthly download credit
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook?
Download this book in EPUB and PDF formats
Access this title in our online reader
DRM FREE - Read whenever, wherever and however you want
Online reader with customised display settings for better reading experience
What do you get with video?
Download this video in MP4 format
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with video?
Stream this video
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with Audiobook?
Download a zip folder consisting of audio files (in MP3 Format) along with supplementary PDF
What do you get with Exam Trainer?
Flashcards, Mock exams, Exam Tips, Practice Questions
Access these resources with our interactive certification platform
Mobile compatible-Practice whenever, wherever, however you want
BUY NOW $10 p/m for first 3 months. $15.99 p/m after that. Cancel Anytime!
eBook $30.99
Print $38.99
Subscription $15.99
What do you get with a Packt Subscription?
This book & 7000+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook + Subscription?
Download this book in EPUB and PDF formats, plus a monthly download credit
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook?
Download this book in EPUB and PDF formats
Access this title in our online reader
DRM FREE - Read whenever, wherever and however you want
Online reader with customised display settings for better reading experience
What do you get with video?
Download this video in MP4 format
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with video?
Stream this video
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with Audiobook?
Download a zip folder consisting of audio files (in MP3 Format) along with supplementary PDF
What do you get with Exam Trainer?
Flashcards, Mock exams, Exam Tips, Practice Questions
Access these resources with our interactive certification platform
Mobile compatible-Practice whenever, wherever, however you want
  1. Free Chapter
    Chapter 2: Java – First Contact
About this book
Android is one of the most popular mobile operating systems today. It uses the most popular programming language, Java, as one of the primary languages for building apps of all types. Unlike most other Android books, this book doesn’t assume that you have any prior knowledge of Java programming, instead helps you get started with building Android games as a beginner. This new, improved, and updated third edition of Learning Java by Building Android Games helps you to build Android games from scratch. Once you've got to grips with the fundamentals, the difficulty level increases steadily as you explore key Java topics, such as variables, loops, methods, object-oriented programming (OOP), and design patterns while working with up-to-date code and supporting examples. At each stage, you'll be able to test your understanding by implementing the concepts that you’ve learned to develop a game. Toward the end, you’ll build games such as Sub Hunter, Retro Pong, Bullet Hell, Classic Snake, and Scrolling Shooter. By the end of this Java book, you'll not only have a solid understanding of Java and Android basics but will also have developed five cool games for the Android platform.
Publication date:
March 2021
Publisher
Packt
Pages
686
ISBN
9781800565869

 

Chapter 2: Java – First Contact

In this chapter, we will make significant progress with the Sub' Hunter game even though this is our first lesson on Java. We will explore, in detail, exactly how Sub' Hunter will be played and the steps/flow that our completed code will need to take to implement the game.

We will also learn about how Java uses code comments to document the code, take a brief initial glimpse at methods to structure our code, and an even briefer first glimpse at Object-Oriented Programming (OOP), which will begin to reveal the power of Java and the Android API.

The autogenerated code that we referred to in Chapter 1, Java, Android, and Game Development, will also be explained as we proceed and add more code. In this chapter, we will cover the following topics:

  • Planning the Sub' Hunter game
  • Introducing Java methods
  • Structuring Sub' Hunter with methods
  • Introducing OOP
  • Using Java packages
  • Linking up the Sub' Hunter methods

First, let's do some planning.

 

Planning the Sub' Hunter game

The objective of this game is to find and destroy the enemy sub' in as few moves as possible. The player takes a shot and each time guesses the location of the sub' by taking into account the distance feedback (or sonar ping) from all of the previous shots.

The game starts with the player facing an empty grid with a randomly placed (hidden) submarine lurking somewhere within it:

Figure 2.1 – The Sub' Hunter game screen

Figure 2.1 – The Sub' Hunter game screen

The grid represents the sea, and each place on the grid is a possible hiding place for the submarine that the player is hunting. The player takes shots at the sub' by guessing where it might be hiding and tapping one of the squares on the grid. In the following screenshot, the tapped square is highlighted, and the distance to the sub' from the tapped square is shown as a number at the top of the screen:

Figure 2.2 – Taking shots in the Sub' Hunter game

Figure 2.2 – Taking shots in the Sub' Hunter game

This feedback means the sub' is hiding somewhere on (not within) the radius of 15 squares, as demonstrated in the previous screenshot.

Important note

Note that the dashed circle in the previous screenshot is not part of the game. It is my attempt to explain the possible hiding places of the sub' based on the distance.

As a player takes more shots, they can build up a better mental picture of the likely location of the sub' until, eventually, they guess the exact square and the game is won:

Figure 2.3 – Taking a shot to start the game again

Figure 2.3 – Taking a shot to start the game again

Once the player has destroyed the sub', the next tap on the screen will spawn a new sub' in a random location and the game starts again.

In addition to the game itself, we will be writing code to display debugging information so that we can test the game and check whether everything is working as it should be. The following screenshot shows the game running with the debugging information enabled:

Figure 2.4 – The debugging information of the game

Figure 2.4 – The debugging information of the game

Let's look more closely at the player's actions and how the game will need to respond to them.

The actions flowchart/diagram

We need to plan our code before we start hammering away at the keyboard. You might be wondering how you can plan your code before you have learned how to code, but it is quite straightforward. Study the following flowchart; we will discuss it and then introduce a new Java concept to help us put the plan into action. Follow the path of the arrows and note the diamond shape on the flowchart where our code will make a decision, and the execution of the code could go either way:

Figure 2.5 – Planning the game using a flowchart

Figure 2.5 – Planning the game using a flowchart

The flowchart shows the steps the game will take, as follows:

  1. The game is launched by tapping on its icon in the app drawer (or running it in Android Studio).
  2. The sub' is placed in a random location by generating random horizontal and vertical numbers. The score is set to zero if this is not the first play of the game.
  3. Next, everything is drawn to the screen: the grid-lines and the text (heads-up display or HUD), including the debugging text (if enabled).
  4. At this point, the game does nothing. It is waiting for the player to tap on the screen.
  5. When the player taps on the screen, the pixel that has been tapped is converted into a location on the grid, and that location is compared to the location of the sub'. The Hit? diamond illustrates this comparison. Here, the program could branch back to the drawing phase to redraw everything, including the grid location.
  6. Alternatively, if there was a hit, then the BOOM! screen is shown.
  7. In fact, the BOOM! part isn't exactly as we see it there. The Wait for Input phase also handles waiting for a screen tap at this point. When the screen is tapped again, it is considered the first shot of the next game; the flow of the code moves back to the Spawn Sub Reset Score code, and the whole process starts again. This will become clearer as the project progresses.

The next two sections of this chapter will show you how to flesh out this design with real Java code. Then, in the next chapter, we will be able to view real results on the screen.

Code comments

As you become more advanced in writing Java programs, the solutions you use to create your programs will become longer and more complicated. Furthermore, as you will see in this chapter and following on throughout the book, Java was designed to manage complexity by having us divide our code into separate chunks and, very often, across multiple files.

Comments are a part of the Java program that does not have any function in the program itself. The compiler ignores them. They serve to help the programmer to document, explain, and clarify their code to make it more understandable to themselves later (maybe even a long time later) or to other programmers who might need to refer to or modify the code. So, a good piece of code will be liberally sprinkled with lines like this:

// This is a comment explaining what is going on

The preceding comment begins with the two forward slash characters, //. The comment ends at the end of the line. This is known as a single-line comment. So, anything on that line is for humans only, while anything on the next line (unless it's another comment) needs to be syntactically correct Java code:

// I can write anything I like here
but this line will cause an error unless it is valid code

We can also use multiple single-line comments:

// Below is an important note
// I am an important note
// We can have many single line comments

Single-line comments are also useful if we want to temporarily disable a line of code. We can put // in front of the code and it will not be included in the program. This next code is valid code, which causes Android to draw our game on the screen. We will see it in many of the projects in this book:

// setContentView(gameView);

In the preceding scenario, the code will not run, as the compiler considers it to be a comment and the screen will be blank. There is another type of comment in Java – the multiline comment. This is useful for longer comments and to add things such as copyright information at the top of a code file. Additionally, like the single-line comment, it can be used to temporarily disable code – in this case, it is usually multiple lines.

Everything in between the leading /* signs and the ending */ signs is ignored by the compiler. Here are some examples:

/*
A Java expert wrote this program.
You can tell I am good at this because
the code has so many helpful comments in it.
*/

There is no limit to the number of lines in a multiline comment. Which type of comment is best to use will depend upon the situation. In this book, I will always explain every line of code explicitly, but you will also find liberally sprinkled comments within the code itself that add further explanation, insight, or clarification. So, it's always a good idea to read all of the code:

/*
The winning lottery numbers for next Saturday are
9,7,12,34,29,22
But you still want to learn Java? Right?
*/

Tip

All the best Java programmers liberally sprinkle their code with comments.

Let's add some useful comments to the Sub' Hunter project.

Mapping out our code using comments

Now, we will add some single-line and multiline comments to our code, so we know where we will be adding code throughout the project and what its intended purpose is.

In Chapter 1, Java, Android, and Game Development, we left the code with just a couple of lines to the AndroidManifest.xml file in order to lock the player's screen to landscape and use the full screen.

Open Android Studio and click on the SubHunter.java tab in the Editor window. You can now see the code in the class file.

Referring to our flowchart, we have the One-off Setup element. In Android, the operating system dictates where some parts of our program must take place. For this reason, add the highlighted multiline comment, as shown next, among the existing code. We will explore why this part of the code is where we do the One-off Setup element later, in the Linking up our methods section.

Important note

The complete code for this chapter can be found on the GitHub repo in the Chapter 2 folder.

Now, add the highlighted code shown here:

package com.gamecodeschool.c2subhunter;
import android.app.Activity;
import android.os.Bundle;
public class SubHunter extends Activity {
    /*
        Android runs this code just before 
        the player sees the app.
        This makes it a good place to add 
        the code for the one-time setup phase.
     */
    
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
}

Next, immediately before the final curly brace, }, of the code, add the following highlighted comments. I have highlighted some of the existing code before the new comments to make it clear where exactly to add the new comments:

   …
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
    /*
        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.
     */
    /*
        Here we will do all the drawing.
        The grid lines, the HUD and
        the touch indicator
     */
    /*
        This part of the code will
        handle detecting that the player
        has tapped the screen
     */
    /*
        The code here will execute when
        the player taps the screen. It will
        calculate the distance from the sub'
        and decide a hit or miss
     */
    // This code says "BOOM!"
    // This code prints the debugging text
}

The preceding comments serve a few purposes. First, we can see that each aspect of our flowchart plan has a place where its code will go. Second, the comments will be a useful reminder of what the code that follows does, and, finally, when we get around to adding the code for each section, I will be able to demonstrate where you need to type in the new code because it will be in the same context with these comments.

Tip

Ensure you have read the comments and studied the flowchart before moving ahead.

We will also add more comments to explain specific lines of code within each of the sections.

I keep mentioning sections. Java has a word for that: methods.

 

Introducing Java methods

Java methods are a way of organizing and compartmentalizing our code. They are quite a complex topic, and a full understanding of them requires knowledge of other Java topics. By the end of the book, you will be a method ninja. However, for now, a basic introduction will be useful.

Methods have names to identify them from other methods and to help the programmer identify what they do. The methods in the Sub' Hunter game will have names such as draw, takeShot, newGame, and printDebuggingText.

Note that code with a specific purpose can be wrapped inside a method; for example, take a look at the following snippet:

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

The preceding method, named draw, could hold all the lines of code that draw our game. When we set out a method with its code, it is called the method definition. The curious-looking prefixed void keyword and the postfixes, (), will be explained in Chapter 4, Structuring Code with Java Methods. However, for now, you just need to know that all of the code inside the draw method will be executed when another part of the code wants it to be executed.

When we want to initiate a method from another part of the code, we say that we call the method. And we would call the draw method with the following code:

draw();

Take note of the following, especially the last point, which is very important:

  • Methods can call other methods.
  • We can call methods as many times as we want.
  • The order in which the method definitions appear in the code file doesn't matter. If the definition exists, it can be called from the code in that file.
  • When the called method has completed its execution, the program execution returns to the line after the method call.

So, in our example program, the flow would look like this:

…
// Going to go to the draw method now
draw(); // All the code in the draw method is executed
// Back from the draw method
// Any more code here executes next
…

Important note

In Chapter 8, Object-Oriented Programming, we will also explore how we can call methods to one file from another file.

By coding the logic of the Sub' Hunter game into methods and calling the appropriate methods from other appropriate methods, we can implement the flow of actions indicated in the flowchart.

Overriding methods

There is one more thing that you need to know about methods before you do some more coding. All the methods I mentioned earlier (for example, draw, takeShot, newGame, and printDebuggingText) are methods that we will be coding. They are our very own methods, and they are for our use only.

Some methods, however, are provided by the Android API and are there for our (and all Android programmers) convenience – we can either ignore them or adapt them. If we decide to adapt them, then this is called overriding.

There are lots of methods that we can override in Android, but one method is overridden so often that it was automatically included in the autogenerated code. Take a look at this part of the code again:

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

In the preceding code, we are overriding the onCreate method. Notice that the prefix and postfix to the name are quite complicated. Exactly what is going on here will be explained when we more thoroughly deal with methods in Chapter 4, Structuring Code with Java Methods.

Important note

The super.onCreate… code will also be discussed in depth. But if you can't wait, here is a brief explanation: the super.onCreate… part of the code is calling another version of the onCreate method that also exists, even though we cannot see it. This is the one we are overriding.

Now we can add the method definitions to the Sub' Hunter code.

 

Structuring Sub' Hunter with methods

As we add the method definitions to the code, it should come as no surprise where each of the methods will go. The draw method will go after the comment about do all the drawing… and so on.

Add the newGame method definition after the appropriate comment, as shown here:

/*
     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.
 */
void newGame(){
}

Add the draw method definition after the appropriate comment, as highlighted here:

/*
     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() {
}

Add the onTouchEvent definition after this comment, as follows:

/*
     This part of the code will
     handle detecting that the player
     has tapped the screen
 */
@Override
public boolean onTouchEvent(MotionEvent motionEvent) {
}

Note that the onTouchEvent method is another overridden method. Android provides this method for our benefit, and when the player touches the screen, it will call this method. All we need to do now is work out how to handle a touch when the onTouchEvent method gets called. There is also an error in this code, but we will resolve this when we begin learning about OOP later.

Now, add the takeShot method definition after the comment, as follows:

/*
     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(){
}

Add the boom method definition after the comment, as follows:

// This code says "BOOM!"
void boom(){
}

Now, add the printDebuggingText definition after the comment about the debugging text:

// This code prints the debugging text
void printDebuggingText(){
}

As the project progresses, we will add code to each of the method definitions because, at the moment, they are empty and, therefore, don't do anything. Furthermore, as we learn more about methods, the postfixes and prefixes of the method names will also evolve and become easier to understand.

A concept that is very closely related to methods and useful for understanding them better is OOP.

 

Introducing OOP

OOP makes it easy to do exceptional things. A simple analogy could be drawn using a machine, perhaps a car. When you step on the accelerator, a whole bunch of things are happening under the hood. We don't need to understand what combustion or fuel pumps are because a smart engineer has provided an interface for us. In this case, a mechanical interface, that is, the accelerator pedal.

Take the following line of Java code as an example; it might look a little intimidating so early on in a book for beginners:

locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER)

However, once you learn that this single line of code searches Space for available satellites, and then communicates with them in orbit around the Earth while retrieving your precise latitude and longitude on the planet, it is easy to begin to glimpse the power and depth of OOP. Even if that code does look a little bit long and scary, imagine talking to a satellite in some other way!

Java is a programming language that has been around a lot longer than Android. It is an object-oriented language. This means that it uses the concept of reusable programming objects. If this sounds like technical jargon, another analogy will help. Java enables us and others (such as the Android development team) to write Java code that can be structured based on real-world "things," and here is an important thing to note: it can be reused.

Classes and objects

So, using the car analogy, we could ask the question: if a manufacturer makes more than one car in a day, do they redesign each part before fitting it to each individual car?

The answer, of course, is no. They get highly skilled engineers to develop exactly the right parts that have been further honed, refined, and improved over a number of years. Then, that same part is reused repeatedly, as well as occasionally improved further. Now, if you want to be picky about my analogy, then you could argue that each of the car's components must still be built from raw materials using real-life engineers, or robots. This is true. Just stick with my analogy a bit longer.

The important thing about OOP

What software engineers do when they write their code is they build a blueprint for an object. We then create an object from their blueprint using Java code, and, once we have that object, we can configure it, use it, combine it with other objects, and more.

Furthermore, we can design our own blueprints and make objects from them as well. The compiler then translates (that is, manufactures) our custom-built creations into working code that can be run by the Android device.

Classes, objects, and instances

In Java, a blueprint is called a class. When a class is transformed into a real working thing, we call it an object or an instance of the class.

Tip

In programming, the words "instance" and "object" are virtually interchangeable. However, sometimes, one word seems more appropriate than the other. All you need to know at this point is that an object/instance is a working realization of a class/blueprint.

We are almost done with OOP – for now.

A final word on OOP, classes, and objects – for now

Analogies are useful only to a certain point. It would be more useful if we simply summarize what we need to know right now:

  • Java is a language that allows us to write code once that can be used over and over again.
  • This is very useful because it saves us time and allows us to use other people's code to perform tasks. Otherwise, we might not have the time or knowledge to write it for ourselves.
  • Most of the time, we do not even need to see other people's code or even know how it works!

Let's consider one last analogy. We just need to know how to use that code, just as we only need to learn how to drive a car, not manufacture one.

So, a smart software engineer up at Google HQ writes a desperately complex Java program that can talk to satellites. He then considers how he can make this code easily available to all the Android programmers out there who are writing location-aware apps and games. One of the things he does is that he turns tasks, such as getting a device's location on the planet's surface, into simple one-line tasks. So, the one line of code we saw previously sets many more lines of code into action that we don't see. This is an example of using somebody else's code to make our code infinitely simpler.

Demystifying the satellite code

Here it is again:

locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER)

locationManager is an object built from a class, and getLastKnownLocation is a method defined in that class. Both the class that the locationManager object was built from and the code within the getLastKnownLocation method are exceptionally complex. However, we only need to know how to use them, not code them ourselves.

In this book, we will use lots of Android API classes and their methods to make developing games easier. We will also make and use our own reusable classes.

Reusable classes

All methods are part of a class. You need an object built from a class in order to use methods. This will be explained in more detail in Chapter 8, Object-Oriented Programming.

If you are worried that using these classes is somehow cheating, then relax. This is what you are meant to do. In fact, many developers "cheat" much more than simply using classes. They use premade game libraries, such as libGDX, or complete game engines, such as Unity or Unreal. We will teach you Java without these cheats, leaving you well prepared to move on to libraries and engines should you wish to.

But where are all of these classes? Do you remember this code from when we were typing the method definitions? Take a closer look at the following code:

/*
     This part of the code will
     handle detecting that the player
     has tapped the screen
 */
@Override
public boolean onTouchEvent(MotionEvent motionEvent) {
     return true;
}

There are two reasons why the previous code had an error. The first reason is that Android Studio doesn't know anything about the MotionEvent class – yet. Additionally, note that in the previous code, I have added a line of code, as follows:

return true;

This is the second reason there is an error. This will be fully explained in Chapter 4, Structuring Code with Java Methods. For now, just add the highlighted line of code, return true;, exactly where it appears in the preceding code. Don't miss the semicolon (;) at the end.

We will solve the MotionEvent error when we discuss packages next.

 

Using Java packages

Packages are grouped collections of classes. If you look at the top of the code that we have written so far, you will see these lines of code:

import android.app.Activity;
import android.view.Window;
import android.os.Bundle;

These lines of code make available the Activity and Bundle classes along with their methods. Comment out two of the preceding lines like this:

//import android.app.Activity;
import android.view.Window;
//import android.os.Bundle;

Now look at your code, and you will see errors in at least three places. The word Activity has an error because Activity is a class that Android Studio is no longer aware of in the following line:

public class SubHunter extends Activity {

The word onCreate also has an error because it is a method from the Activity class, and the word Bundle has an error because it is a class that since we commented out the previous two lines, Android Studio is no longer aware of. This next line highlights where the errors are:

protected void onCreate(Bundle savedInstanceState) {

Uncomment the two lines of code to resolve the errors, and we will add some more import… code for the rest of the classes that we will use in this project, including one to fix the MotionEvent class error.

Adding classes by importing packages

We will solve the error in the onTouchEvent method declaration by adding an import statement for the MotionEvent class, which is causing the problem. Underneath the two existing import statements, add this new statement, which I have highlighted:

package com.gamecodeschool.subhunter;
// These are all the classes of other people's
// (Android) code that we use for Sub Hunter
import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;

Check the onTouchEvent method, and you will see that the error is gone. Now, add these further import statements directly underneath the one you just added, and that will take care of importing all of the classes that we need for this entire game. As we use each class throughout the next five chapters, I will introduce them formally. In the preceding code, I have also added some comments to remind me what import statements do.

Add the highlighted code. The syntax needs to be exact, so consider copying and pasting the code:

// These are all the classes of other people's
// (Android API) code that we use in Sub'Hunt
import android.app.Activity;
import android.view.Window;
import android.os.Bundle;
import android.view.MotionEvent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.view.Display;
import android.util.Log;
import android.widget.ImageView;
import java.util.Random;

Notice that the new lines of code are grayed-out in Android Studio. This is because we are not using them yet, and at this stage, many of them are technically unnecessary. Additionally, Android Studio gives us a warning if we hover the mouse pointer over the little yellow indicators to the right of the unused import statements:

Figure 2.6 – Indicating unused import statements

Figure 2.6 – Indicating unused import statements

This isn't a problem, and we are doing things this way for convenience as it is the first project. In the next project, we will learn how to add import statements as and when needed without any fuss.

We have briefly mentioned the Activity class. However, we need to learn a little bit more about it to proceed. We will do so while linking up our methods with method calls.

 

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 referred to, as well as mentioned in our comments, that the onCreate method (provided automatically by Android) will handle the One-off 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 the onCreate method.

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

Important note

In fact, 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 how to put the One-off Setup code in onCreate, and we can be sure it will be executed before any of our other methods.

If you look at the flowchart, you will notice that 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. Add this highlighted code, as follows:

/*
     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);
     
     requestWindowFeature(Window.FEATURE_NO_TITLE);
     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 the newGame method followed by the draw method, but it also contains the following 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 we intended.

Now, let's print some text in the newGame method, so we can see it being called as well. Add the following 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");
     
}

Following this, to implement the course of our flowchart, we need to call the takeShot method from the onTouchEvent method. Additionally, note that we are printing some text for tracking purposes here. Remember that the onTouchEvent method is called by Android when the player touches the screen. Add the highlighted code to the onTouchEvent method:

/*
     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 the draw method along with some debugging text into the takeShot method, as per the flowchart:

/*
     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 that it is being called. Remember that on the flowchart, after we complete 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 the draw method to the onTouchEvent method.

Important note

The connection between Android and the onTouchEvent method is permanent and never broken. We will explore how this is possible when we discuss threads in Chapter 9, The Game Engine, Threads, and the Game Loop.

Add the following highlighted code 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 the printDebuggingText or boom methods. Neither have we called these methods from any of the other methods. This is because we need to learn some more Java, and then do more coding before we can add any code to these methods.

When we run our game and the screen is clicked/tapped on, the onTouchEvent method, which is analogous to the Wait for Input phase, will call the takeShot method. This, in turn, will call the draw method. Later in this project, the takeShot method will make a decision to call either 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 the printDebuggingText method 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 | AVD Manager.
  2. Click on the green play icon for the emulator.
  3. Now you can click on the play icon in the Android Studio quick launch bar, and, when prompted, choose whatever your emulator is called and the game will launch on the emulator.

Now open the Logcat window by clicking on the Logcat tab at the bottom of the screen, as shown in the following screenshot.

In the Logcat window, when we start the game, lots of text has been output to Logcat. The following screenshot shows a snapshot of the entire Logcat window to make sure you know exactly where to look:

Figure 2.7 – The Logcat window

Figure 2.7 – The Logcat window

The following screenshot zooms in on the three relevant lines, so you can clearly see the output even in a black and white printed book:

Figure 2.8 – Debugging output in the Logcat window

Figure 2.8 – Debugging output in the Logcat window

Moving forward, I will only show 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 the Logcat output and when we are discussing Java code.

Here is what we can gather from all of this:

  1. When the game was started, the onCreate method was called (by Android).
  2. This was followed by the newGame method, which was executed and then returned to the onCreate method.
  3. This then executed the next line of code and called the draw method.

The game is now currently at the Wait for Input phase, just as it should be according to our flowchart:

Figure 2.9 – The game is at the Wait for Input phase

Figure 2.9 – The game is at the Wait for Input phase

Now, go ahead and click on the screen of the emulator. We should see that the onTouchEvent, takeShot, and 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 on the screen of the emulator just once:

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

As you 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 on the mouse button (or tap a finger), and it is also called when the mouse button (or a finger) is released. To simulate a tap, we only want to respond to releases (that is, a 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) on the Sub' Hunter game.

 

Summary

The phone screen is still blank, but we have achieved our first output to the Logcat window. In addition, we have laid out the entire structure of the Sub' Hunter game. All we need to do now is learn more about Java, and then use it to add code to each of the methods.

In this chapter, we learned that Java methods are used to divide up the code into logical sections, each with a name. We don't know the full details of Java methods yet. However, if you understand that you can define methods and then execute them by calling them, then you know all you need to make further progress.

We also took a first glimpse at OOP. It doesn't matter whether OOP seems a little baffling at this stage. If you know that we can code a class and create usable objects in our code based on that class, then you know enough to continue.

In the next chapter, we will learn about our game's data, for example, how the game "remembers" values such as the position of the submarine or the size of the grid. We will learn that our data can take many forms but can generally be referred to as variables.

About the Author
Learning Java by Building Android Games - Third Edition
Unlock this book and the full library FREE for 7 days
Start now