Chapter 4

Dissecting an Android App

In This Chapter

arrow Creating a new Android project

arrow Understanding the parts of a project

arrow Modifying the manifest and adding image resources

When you’ve got your development environment set up, you’re ready to start building the next great addictive blockbuster game. This chapter gives you the tools you need to understand how to create a project from the ground up, understand how all the parts fit together, and modify the right settings so that everything works the way it’s supposed to.

An Android project is a lot like a standard Java project, but with some important differences. The Android SDK does most of the work for you in building the project structure and adding the necessary files — but as you work on your game, you’ll often need to add to this structure and make modifications, so it’s important to know where everything is and how it works.

Before you do anything else, you’ll have to create a new project, which is really only a few clicks away. So . . . first things first.

Creating a New Project

The Android SDK and Eclipse make it simple to create a new Android project, with a wizard that walks you through the process. Most of the important parts of your game (such as its name and its range of targeted devices) are defined in this creation process.

To create a new project, follow these steps:

1. Select FileNewAndroid Project.

The New Android Project Window (Figure 4-1) will display.

Notice the default location of the workspace. This directory is where all the project files will be located.

2. In the Project Name field type Crazy Eights, and then click Next.

remember.eps The project name is a unique identifier for your project in the Eclipse workspace.

3. Click Android 4.0 for the Target Name, and then click Next.

The New Android Project/Select Build Target window appears, as shown in Figure 4-2.

The build target refers to the SDK level you will be using to develop your game. For example, if you choose a build target of Android 2.2, you can use only the features included in that and earlier levels.

Figure 4-1: New Android Project/Create Android Project window.

9781118235997-fg0401.eps

Figure 4-2: The New Android Project/Select Build Target window.

9781118235997-fg0402.eps

tip.eps Choose the latest SDK available to develop with. You don’t always have to use new features included in the latest SDK, but using the latest version as your build target gives you that option.

4. In the Package Name field type com.agpfd.crazyeights, then click Finish.

The package name is used to identify the Java package of your app. Once published to the Android Market, two apps cannot have the same package name, so this must be unique.

Package naming for Android follows a general convention established for Java package names:

• Typically, a package name is organized like a reverse URL, with com or org appearing first, followed by the domain name of the authoring organization.

• When you choose a package name for your own apps, you might want to use your company name or website domain (if you have one). Otherwise you can simply choose a domain name that is unique and meaningful to you.

The Minimum SDK option (see Figure 4-3) is the minimum version of Android that a user’s device must be running in order to see your app in the market, install it, and run it. In general, you want this option to be set to the lowest possible value to target as many devices as possible.

Figure 4-3: The New Android Project/Application Info window.

9781118235997-fg0403.eps

Your new project is now created! The package and its associated structure shows up in Eclipse’s Package Explorer and should look something like Figure 4-4.

Figure 4-4: A newly created project in Eclipse’s Package Explorer.

9781118235997-fg0404.eps

Taking the Bird’s Eye View of a Project

An Android project is organized similar to other Java projects, with a few important exceptions. The Android SDK automatically generates certain features specific to an Android project. As with any other Java project, this one has a source directory where all the Java files that handle all the logic of your game are located.

Here are a few other Android-specific aspects of the project, with a brief description of each:

check.png The R.java file: An auto-generated index that assigns unique variables to all the resources in your app. If you open this file, you’ll notice a warning saying that you shouldn’t manually modify this file.

tip.eps Sometimes the R.java file can get out of sync with the actual resources you’ve declared, causing errors. A quick way to resolve common errors of this type is to

• Delete the R.java file.

• Clean the project (Project⇒Clean).

Doing so regenerates the R.java file and sometimes fixes the problem.

check.png Resources: The resources directory is where things like graphics, sounds, layouts, and strings are typically located:

• Graphics are located in one or more drawable subdirectories, typically organized by their intended screen size.

• XML resources for layouts are located in the layout subdirectory.

• Strings and styles are in the values subdirectory by default.

check.png The Manifest: This file, called AndroidManifest.xml, is located in the root directory of the project. The file is where you specify the app name, all activities, permissions, and device targeting.

Editing the Manifest

The manifest is generated automatically when a new Android Project is created.

The New Android Project wizard prompts you for some options that are included in the manifest, but this section demonstrates how to manually edit the manifest file, a useful task that will come up often as you work on your game.

tip.eps Think of the manifest as a specification of everything important about your app. In maritime travel, a ship’s manifest describes everything important about that ship: A list of all the crew and passengers, details about the cargo, its country of origin, places it has traveled, and where it is headed. Believe it or not, your app has a lot in common with a ship! When it’s ready, you’ll be launching it into the high seas of one or more app stores. The manifest will tell everyone what’s inside and what devices it is headed for.

View the contents of the manifest by double-clicking the file in the Package Explorer, which will open the file in Eclipse’s editor view. Select the AndroidManifest.xml tab in the editor view to see the XML, which should look something like the following code:

<?xml version=”1.0” encoding=”utf-8”?>

<manifest xmlns:android=”http://schemas.android.com/apk/res/android”

     package=”com.dummies.androidgame.crazyeights”

     android:versionCode=”1”

     android:versionName=”1.0”>

   <uses-sdk android:minSdkVersion=”3” />

   <application android:icon=”@drawable/icon” android:label=”@string/app_name”>

       <activity android:name=”.CrazyEights”

                 android:label=”@string/app_name”>

           <intent-filter>

              <action

                 android:name=”android.intent.action.MAIN” />

              <category

                 android:name=”android.intent.category.LAUNCHER” />

           </intent-filter>

       </activity>

   </application>

</manifest>

Naming and versioning your game

The <manifest> tag has attributes that indicate what the package name, version code, and version name are.

Every time you update your game

check.png The package name remains the same.

check.png Increment the version code by 1.

check.png Change the version name to a higher value.

For example, your second version could be version code “2” with a version name of “1.1”.

warning_bomb.eps The Android Market allows apps with the same app name, but not the same package name. If the package name of your app is already in use by an existing app, you’ll need to rename your package.

Targeting versions

The <uses-sdk> tag indicates the minimum version of the Android OS that can run your game. Currently, Android SDK versions range from 3 (Android 1.5) to 13 (Android 3.2). A lower value for this attribute will allow your app to be visible to Android devices running older versions of the OS.

tip.eps The wider the range of devices you target, the larger your potential audience, so you’ll only want to specify a higher minimum SDK if your game uses features of the SDK that aren’t available in older versions.

None of the examples in this book use such features, so you can safely use a value of “3” to target as many devices as possible.

tip.eps You can designate a target SDK version, to indicate that your game has been extensively tested and is therefore targeted for that version. Add the following attribute to the <uses-sdk> tag:

android:targetSdkVersion=”8”

Declaring activities

The <application> tag contains attributes indicating the image used for

check.png Your game’s icon (android:icon), which points to an image in your project’s drawable directory

check.png Your game’s name (android:label), which points to a string in your project’s values directory.

All the activities within your application are declared within the <application> tag:

check.png When you create a new project, there is only one activity by default.

check.png As you add new activities in your source, you must declare each one in the manifest file, or an error will occur.

For each activity, you can define attributes that control the behavior of the activity. When a device is rotated 90 degrees, by default an app changes orientation to try to match the device.

tip.eps Often you want to prevent this automatic rotation with games, usually because a game looks and plays well in a specific orientation.

For the Crazy Eights example, edit the main activity so that it will always display in portrait mode, even when the device is rotated, by adding the following attribute to the main activity:

android:screenOrientation=”portrait”

Your edited main activity should look like this:

<activity

   android:label=”@string/app_name”

   android:name=”.CrazyEightsActivity”

   android:screenOrientation=”portrait”>

   <intent-filter >

      <action

           android:name=”android.intent.action.MAIN” />

      <category

           android:name=”android.intent.category.LAUNCHER” />

   </intent-filter>

</activity>

Each activity may also have an <intent-filter> which further defines what it can and cannot do. By default, the activity created when you make a project from scratch has the action MAIN and the category LAUNCHER. This tells an Android device that this activity should be started when the app is launched.

Setting permissions

Sometimes you may want your app to use certain features that require permissions. For security reasons, some features need to be declared explicitly in the manifest so that upon installation, a user can see that an app is doing certain things behind the scenes. They can then decide whether or not they are comfortable installing such an app.

For example, your game may want to display all the user’s contacts so that they can choose a contact to invite to a multiplayer game. If so, the following permission would need to be added to the manifest:

<uses-permission

         android:name=”android.permission.READ_CONTACTS” />

If you don’t have this permission declared in your manifest, your game won’t work properly. In fact, you’ll see a runtime error.

remember.eps Always check the log output when you run your game to check for errors. You can either

check.png View the output in the LogCat view in Eclipse.

check.png Open a command prompt and type adb logcat.

If the error is due to the lack of proper permissions, the log will let you know, and you can then simply add the appropriate permission to fix the problem.

For a full list of permissions see

http://developer.android.com/reference/android/Manifest.permission.html

Targeting different screen sizes

Declarations for the specific screen sizes your game is intended to be played on aren’t generated by default. Chapter 2 discusses the wide variety of Android hardware configurations.

tip.eps Once you decide which screen sizes you want to try to target, a good practice is to explicitly declare that information in your manifest.

The following is an example of using the <supports-screens> tag:

<supports-screens

                  android:smallScreens=”false”

                  android:normalScreens=”true”

                  android:largeScreens=”true”

                  android:xlargeScreens=”true”

                  android:anyDensity=”true”

</supports-screens>

check.png Small screens generally refer to devices such as QVGA, which are generally 320x240.

check.png Normal screens are most often HVGA, with a screen size of 480x320.

check.png Large screens are WVGA, and are most typically 800x600 or 854x600.

check.png X-large screens are typically XWVGA, usually tablet-size.

The following website is the official Android resource for developing for multiple screen sizes:

http://developer.android.com/guide/practices/screens_support.html

And that’s it! You can either

check.png Edit parts of the manifest by clicking the appropriate tabs at the bottom of the editor view (as shown in Figure 4-5).

check.png Edit the XML directly, which is what we do throughout this book as needed.

Figure 4-5: Viewing the AndroidManifest.xml.

9781118235997-fg0405.eps

Organizing Resources

The resources directory of a project is where all images and sounds are located, along with files that modify the look and feel of your game. The directory is abbreviated res and is located in the root directory of your project.

Figure 4-6 shows the resources directory expanded, with each of its subdirectories.

Figure 4-6: The resources directory, expanded to view sub-directories.

9781118235997-fg0406.eps

Depending on the SDK version you used to create your project, your resources directory might look a little different. But the basic structure should be the same.

Drawables

There should be at least one drawable subdirectory in the /res directory. This is where all images, including your game’s icon, should be placed.

In the preceding example, three subdirectories were automatically generated:

check.png drawable-hdpi will hold images for high-density screens.

check.png drawable-ldpi will hold images for low-density screens.

check.png drawable-mdpi will hold images for medium-density screens.

If your directory structure is set up the same way, you’ll notice that the Android SDK placed the default Android app icon of the appropriate size in each directory:

check.png The ldpi icon is 36x36.

check.png The mdpi icon is 48x48.

check.png The hdpi icon is 72x72.

tip.eps If you want to target tablets and other very high-resolution devices, you should create another directory at the same level as the three just mentioned (ldpi, mdpi, and hdpi):

1. Right-click the res directory.

2. Select NewFolder.

3. Type “drawable-xhdpi” as the Folder name.

4. Click Finish.

The dimensions for an extra-high-density icon should be 96x96.

The first thing you’ll want to do with regard to drawables is create your own icons and replace the default ones.

For the Crazy Eights example, I’ve provided a sample icon in four different sizes for you to use (as shown in Figure 4-7). However, I’d encourage you to create your own, using your favorite graphics software.

Figure 4-7: Sample icon for Crazy Eights.

9781118235997-fg0407.tif

Once you have your new icons, place them in the appropriate drawable directory. Delete the icons provided by the SDK and rename each of your icons “icon.png”.

When you design your game, one of the first decisions you need to make is the range of device hardware you want to target. If you want to target as wide a range as possible in order to maximize your audience size, you’ll need to develop your game so that it explicitly supports specific screen sizes, or so that it scales automatically to whatever screen sizes you want to support.

Render graphics to the screen in a relative way, so that no matter what the screen size, the game will have a consistent look and feel:

check.png Include images that look good on the highest-resolution device you want to support.

check.png Scale the images down when they’re viewed on lower-resolution devices.

Layouts

A layout file is an XML document that defines how a given view looks. The layout

check.png Specifies all the elements that will be displayed, such as

• Text

• Images

• Input fields

check.png Determines how they are laid out with respect to each other.

You’re not going to be using layouts in game development as much as an Android developer who is building other types of apps, since you’re going to be creating your own custom view and directly drawing text and images to the screen. But you will be using layouts for some things, like the layouts of dialog boxes, so you’ll need to know how they work.

In the res/layout directory of your project, you’ll see that there is a file called main.xml,. as shown in Figure 4-8. This file was automatically generated when you created the project. Double-click the file in the Package Explorer to view it in Eclipse.

Figure 4-8: The layout file for main.xml.

9781118235997-fg0408.eps

When you open a layout file, there are two tabs at the bottom of the file in the editor view in Eclipse. One is the Graphical Layout, which lets you view and modify the layout in a graphical mode, allowing you to drag and drop different interface elements to and from your layout. If you click the tab with the filename, you’ll see the XML code itself (Figure 4-8).

tip.eps Get used to modifying things like your manifest and your layout files directly in XML. With layouts, you can preview them using the Graphical Layout tab, but editing the XML directly will give you a better understanding of how the code actually works.

In the case of the default main.xml layout file, you should only see two elements: LinearLayout and TextView. The different types of layouts are

check.png FrameLayout. Generally for holding a single element, like an image.

check.png LinearLayout. Aligns elements in one direction, either horizontally or vertically.

check.png TableLayout. Arranges elements according to a table configuration, with rows and columns.

check.png RelativeLayout. Gives the most flexibility, allowing you to align specific elements relative to one another.

LinearLayout is sufficient for most simple cases, but if you’re interested in learning more about other layouts, check out:

http://developer.android.com/guide/topics/ui/layout-objects.html

In the case of the default XML generated for main.xml, the LinearLayout element includes an orientation attribute, which can be either horizontal or vertical for linear layouts. In your case, it should be vertical by default. This means that all the elements inside the LinearLayout tag will be displayed vertically down the screen next to each other.

The LinearLayout also includes attributes determining its width and height, both of which are “fill_parent”. This means that this layout will stretch itself to fit the height and width of whatever screen it is displayed on.

The layout only has one child element, a TextView, which also has width and height attributes. The width is “fill_parent”, but the height is “wrap_content”, which means that this element will only fill up as much vertical space as its contents, in this case the text it is displaying. The text attribute references a string called “hello”.

You’ll see where that string is stored in the next section, but for now, try making some small changes to this file and either previewing it in the Graphical Layout tab of the editor view, or running it on a device or emulator.

Some suggested changes include these:

check.png Copy the TextView and paste a copy just below the current one, so that you have two exact copies of the same TextView.

check.png Change the orientation attribute of the LinearLayout tag from “vertical” to “horizontal”.

check.png Use the android:textColor attribute for the TextView to change the default color of the text.

Strings

All the text that appears in your game that is not part of an image, from button text to tutorials, can be specified in the strings.xml file located by default in the res/values directory.

technicalstuff.eps You can hard-code the text into either your Java or layout files, and this is usually okay as long as you don’t intend to reuse text much or target more than one language. Hard-coding text is generally not a recommended practice, though you’ll still find a lot of apps and games that do it.

The recommended practice is to keep all text in the strings.xml file, giving each string a unique name, then referencing the strings from your code. By default, two strings are generated when you create a new app:

hello

app_name

For the example, open the strings.xml file in your new Crazy Eights project under res/values. You should see something like Figure 4-9.

Figure 4-9: Default contents of strings.xml.

9781118235997-fg0409.eps

The “hello” string is used to display sample text when an app is first run. The “app_name” string is used to display the name of the app under the icon in the launcher.

tip.eps Any time you want to add new text to your game, add another entry into this file, which can then be referenced from your code.

If you reuse the same text in multiple places in your game, you only have to change it once in the strings.xml file. This organization also makes localizing your game a lot easier. For each other language, you add a new values directory appended with the country code for that locale. For example, if you wanted to add support for Spanish, you would create a new directory in res/ called values-es (for Español). You would need a file called strings.xml in that directory, with the same string names, though the contents would be in Spanish. For example:

<string name=”app_name”>Los Ochos Locos</string>

If a player on a device has its locale settings set to ES, then when they play your game, all the text will be populated from the contents of the values-es directory. You can add support for as many languages as Android supports, and as many as you want to get translations for.

Check supported locales in the Android documentation on their website before you invest in a translator.

Styles

Styles allow you to apply a particular look and feel throughout your app. Styles are applied to views, and work a lot like cascading stylesheets (CSS) in web design. You define styles in XML, and they reside in the res/values directory of your project. You then reference them from other views to apply the style to that view.

Themes

A theme is just a broader use of styles, applying them across an entire activity or application. If you apply a style as a theme, every view in an activity will have that style automatically applied to it.

technicalstuff.eps We won’t be using styles or themes in this book, but if your game takes a different tack from the one covered here you might want to explore this topic more on your own. See the official Android documentation on Styles and Themes at

http://developer.android.com/guide/topics/ui/themes.html

Sounds

You may or may not want to include sound effects and music in your game. A lot of games work fine without them, especially on the mobile platform where players often play games in public areas where they may not want to be heard. If you do use sounds in your game, by default they should be located in the res/raw directory. If it doesn’t exist, you’ll need to create it.

You can find a list of supported media types at

http://developer.android.com/guide/appendix/media-formats.html

tip.eps For sounds, I always use Ogg Vorbis (.ogg), which is an open audio-compression format. The compression and quality are excellent, and .ogg files are supported by a large number of sound-editing software programs.

Organizing the Source Directory

The source directory (/src) contains the Java files where you will write all the logic that makes your games go. Source files reside in a package. When you create an Android project, a default package is created, but you can add as many new packages as you like. If your game is particularly complicated, you may want to separate your source files into logical groupings, such as files that handle persisting data, sounds, or other subcategories.

To create a new package in Eclipse

1. Right-click the /src directory.

2. Select NewPackage.

The New Java Package dialog box will appear, as shown in Figure 4-10.

Just enter a name for the package with the same domain name as your other packages, with the new extension name — here’s an example:

“com.agpfd.crazyeights.sound”

Figure 4-10: The New Java Package dialog box.

9781118235997-fg0410.eps

You can then add or move source files to this new package. The games we work on in this book won’t be that complex, so we’ll keep all the source files in one package. But if your project starts piling up Java files, you can save yourself a lot of headache by organizing them in a logical, easy-to-find way. Anyone else who looks through your code will appreciate the effort as well!

Below the source directory (see Figure 4-11), you may have also noticed the /gen directory. This directory contains files automatically generated for you by the Android SDK.

Figure 4-11: The source directory of an Android project.

9781118235997-fg0411.tif

check.png The BuildConfig.java file contains settings for build configurations. You shouldn’t encounter any issues with this file and you should never have to look at it.

check.png The R.java file contains references to all your resources (layouts, images, etc.). Every time you add a new resource it is automatically added to this file, assigning a unique identifier to the resource. The R.java file acts as a master index for your resources.

warning_bomb.eps Don’t modify the contents of generated files yourself. Doing so can often lead to nasty bugs if these files get out of sync with your project. You may encounter problems with the R.java file in particular. Although you don’t want to modify it manually, sometimes a good practice is to delete it and clean your project (Project⇒Clean), which causes the file to be generated again.

Understanding Activities

An activity is a running process within an application. One of the first big decisions you’ll make as an Android developer is how to design how your game will handle transitions — for example, moving from the title screen to the main play screen, or to a new level after completing the previous one. Your game will always have at least one activity, the one that is the first to start when your game launches.

If you look in the AndroidManifest.xml of one of your apps, you’ll see this XML nested inside one activity:

    <intent-filter >

       <action android:name=”android.intent.action.MAIN” />

       <category android:name=”android.intent.category.LAUNCHER” />

    </intent-filter>

This XML designates that activity as the main activity, the first one to be started when the app is launched. You can have multiple activities in your game, but only one main activity.

warning_bomb.eps Every activity in your game must be declared in the manifest. If you don’t declare one of your activities in the manifest, you’ll get a runtime error.

check.png A new activity can be launched from within the main activity, and another after that, so that you can have a stack of activities running in your game.

check.png Another option is to only have one activity, while transitioning between views. This is the approach we’ll take in this book, but it doesn’t mean it’s the only (or the best) way of doing things.

The lifecycle of an activity

Each activity has its own lifecycle as it is created, started, used, then killed. Figure 4-12 shows this lifecycle and when transitions are made between states.

It’s important to understand what happens when with activities, since they’re the backbone of any Android app or game. Figure 4-12 shows when each method within an activity is called (for example, onCreate is called when the activity is launched).

Figure 4-12: The lifecycle of an activity.

9781118235997-fg0412.eps

technicalstuff.eps An activity can be running in the background, still using system resources even though the user can’t see it. If too many activities are running in the background, and the system runs out of memory, Android will prioritize them and kill off the less important ones.

You’ll want to consider the kinds of cases a player may encounter when playing your game. Since many Android devices are phones, they may get a phone call while playing your game. In this case, the phone activity will get priority, become visible to the user, and your game and all its activities will be put in the background. How will your game handle this? You’ll want to strongly consider

check.png Saving the game state when onPause() is called

check.png Restoring the game state in one of the early methods, such as onResume().

Get familiar with the lifecycle of activities, and when you test, make sure you think about what kind of scenarios your game needs to handle. When someone is playing your game on a mobile device, they’re using that device for lots of other things besides playing games!

Creating an activity

Whenever you make a new Android project in Eclipse, the main activity will be generated with a single class with a single method, onCreate(), as shown in Figure 4-13.

Figure 4-13: Default contents of the main activity of a new Android project.

9781118235997-fg0413.tif

The onCreate() method takes a Bundle as input.

technicalstuff.eps A Bundle is an object that maps string values to parcelable types. Basically it’s a way for you to store certain types of information to pass between activities.

The onCreate() method is where the content view is set, which determines what the user sees on the screen. In this case, this is done by the line:

setContentView(R.layout.main);

This sets the content of the current view to the main.xml file in the res/layout directory.

check.png For games, we’ll be creating our own custom views and setting the content view to those.

check.png Because onCreate() is the first method called in any activity, it’s the place where you’ll want to initialize variables used throughout this activity.

Resuming an activity

Suppose someone is playing your game and gets a phone call. Follow the flow in Figure 4-12, starting with Activity Running. Your game will call onPause(), which is typically where you’ll want to store any information (such as the game state).

tip.eps When someone opens or closes a hardware keyboard or reorients a device, this action causes a configuration change that also interrupts your application. Make sure you test your game to handle these cases.

If the user finishes a phone call and then navigates back to your game, note that

check.png onRestart(), onStart(), and onResume() are all called before the activity actually starts again. Any code that restores saved information could be placed in one of these methods.

check.png onStart() and onResume() are called whenever the activity is started from scratch.

You’ll want to be careful about when and how you try to restore the game state.

If this all seems overwhelming, don’t worry. In the case of Crazy Eights, I show you how to handle your game state in the context of the activity lifecycle. For now, just make sure you’re familiar with the basic flow in Figure 4-12.

Destroying an activity

The onDestroy() method is called when the activity is finished and ready to shut down.

This can happen in a number of instances, such as when your game is not visible, running in the background, and the Android OS runs out of memory and kills your activity:

check.png If the player is playing your game and presses the Home button on their device, this will not actually kill your activity; instead, it displays the Home screen.

check.png If the player presses the Back button, doing so kills the current activity.

In most game-development environments, the developer customarily includes menu items to allow the user to quit the game to return to the Home screen of whatever platform the game is being played on.

This question is sometimes asked in forums by beginning game developers new to mobile platforms. While you can include a UI element that kills the activity, such as a Quit button, this approach is not recommended by the Android development guidelines.

remember.eps Android apps and games should be developed to work similarly; the default behavior should be to leave an activity running in the background by pressing the Home button on the device and to kill the activity by pressing the Back button. Thus you don’t need to explicitly include a Quit menu item or button in your game.

Using Views

The View object in Android is the basic class for drawing and handling input.

Views can be defined using XML, but for our games, we’re going to implement our own custom views so that we can have more control over what is drawn and how the player interacts with our game.

Differences between View and SurfaceView

The View object is the simplest way to handle drawing and user interaction in Android, and the official documentation recommends using it if you’re implementing a game without heavy animation.

For simplicity’s sake, we’re going to use the View object for the first full game we implement, Crazy Eights. The game does not require significant animation, so it should be well-suited to the simplest case. In the View object, the drawing is handled in the same thread as all other processing, which is not particularly efficient.

The SurfaceView is a special type of view that handles drawing in a dedicated thread, so that it can draw whatever is on the Canvas concurrently with other things happening. This makes SurfaceView more efficient than View, and better at handling heavy drawing demands, such as in a real-time arcade-style game. Using the SurfaceView is also more complicated than using a normal view, so consider the tradeoff when implementing your own game.

We’ll be using SurfaceView for the second game covered in this book, Whack-a-Mole.

Instantiating a custom view

Okay, let’s get back to developing your game. To create a custom view, all you need to do is create a new class and have it extend View.

1. Right-click the package (com.agpfd.crazyeights) in which you want to create the new view.

2. Select NewClass.

3. Enter a name, such as MyView and then click Finish.

tip.eps Naming conventions for classes in Java use uppercase for each word, with no spaces.

Listing 4-1: Starting Custom View for Crazy Eights

package com.agpfd.crazyeights

 

import android.content.Context;

import android.view.View;

 

public class CrazyEightsView extends View {

 

     public CrazyEightsView(Context context) {

          super(context);

          // TODO Auto-generated constructor stub

     }

}

4. Next to the class name in the code view, add extends View.

You’ll need to add

• Imports for both Context and View

• A constructor

tip.eps Eclipse will add these automatically if you click the warning symbols on the left margin of the code view and select the appropriate items to add.

Your bare-bones custom view should look something like the one in Listing 4-1.

Drawing in a view

Once we have a custom view, to draw what we want in it, all we need to do is override the onDraw() method. We’re going to modify our custom view to draw a red circle.

To do so, add the code from Listing 4-2 to your custom view.

/9781118235997-tb0402a.png

/9781118235997-tb0402b.png

Lines 3-7: These are the imports you need for the various classes from the Android graphics package we’ll be using.

Line 11: We need a Paint object that defines the attributes of how our circle will be painted on the canvas.

Lines 12-14: Variable declarations for the size and location of the circle.

Lines 18-23: In the onCreate() method we’re going to initialize our variables with the desired values. The coordinate system in Android places the origin (0,0) in the upper-left corner. These values will draw our circle 100 pixels to the right and 100 pixels down from the upper left corner of the screen, with a radius of 30 pixels.

Line 28 actually draws the circle. The drawCircle() method takes in the x and y coordinates, the radius, and the Paint object.

The last thing we need to do is modify our main activity to set our custom view as the content view. Modify the contents of your main activity to look like Listing 4-3.

/9781118235997-tb0403.png

Line 11 creates a custom view, passing in the main activity as context. Line 12 sets the content view to our custom view. And that’s it! Run this app, either in an emulator or on an Android device, and you should see something like the screenshot in Figure 4-14.

Figure 4-14: Screenshot of a Galaxy Nexus running the “red circle” app.

9781118235997-fg0414.tif

Your results may vary. We’re not controlling for screen sizes or densities at all, so your circle may look smaller or larger relative to the display properties of the device you’re using. But this simple example shows the basics of how something is drawn to the screen. When we begin handling user input and changing the state of the screen in response to the input, we’re well on our way to making a game!

Handling input

There are many potential input methods for Android devices. The touchscreen is the most common and reliable method for input for games. So while it’s possible to use the keyboard, accelerometer, trackball, and such for input, we’re going to keep things simple and focus on the touchscreen for our games.

You can always refer to the official Android site (developer.android.com) for insight into how to implement other input methods, but let’s look at how to use the touchscreen for input.

Add the code from Listing 4-4 to CrazyEightsView.java, just after the onDraw() method.

/9781118235997-tb0404.png

Line 2: Gets an integer associated with whatever action the user is taking (for example, pressing down on the screen).

Lines 3-4: These lines get the x and y coordinates on the screen for where the event is happening.

Lines: 6-15: We’re using a switch to handle three possible cases, when the user

Puts a fingertip down on the screen (ACTION_DOWN)

Drags the fingertip across the screen (ACTION_MOVE)

Removes the finger from the screen (ACTION_UP)

Line 17: Invalidate is the command to the view to tell it that a change has occurred and that the canvas needs to be redrawn.

Let’s add some logic that will change the location of our red circle when the user touches the screen. Modify your ACTION_UP case to look like the following:

case MotionEvent.ACTION_UP:

   circleX = X;

   circleY = Y;

   break;

What these two lines do is assign the coordinates for the center of our circle to the point on the screen where you lifted your finger. After adding this code, save your project, then run it and see the results. If you’re using an emulator, wherever you click the screen, the dot should move. With a real device, wherever you touch the screen, the dot should move. Cool, huh?

You might find that you’ll want to make changes based on ACTION_UP, because if you make them on ACTION_DOWN the finger can obscure what’s being displayed on the screen at that point. You can always experiment and see what feels the most intuitive to you.

tip.eps Try moving the logic we just added to the ACTION_MOVE case and see how the app behaves as you drag your finger across the screen. Get familiar with this logic; it gets a lot of use in our games.

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

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