IntroductionWelcome| 00:00 | (music playing)
| | 00:03 | Hi! I am Todd Perkins.
| | 00:06 | Welcome to Building and
Monetizing Games Apps for Android.
| | 00:11 | Throughout this course you'll see how
you can build an Android Game from scratch.
| | 00:16 | We'll start the course by discussing how to
install and setup Eclipse to use Cocos2d-X.
| | 00:22 | Then we'll cover how Cocos2d-x works to
create individual game elements, so you
| | 00:29 | can become familiar with the gaming engine.
| | 00:31 | Then we will create the Game classes,
then we will have an overview of some
| | 00:36 | prewritten code, and write all of
the game played code from scratch.
| | 00:41 | We'll look at how to monetize your game by
adding things like Ads, and In-App Purchases.
| | 00:47 | And finally, will discuss where you can
go after this course to better improve
| | 00:52 | your game development skills.
| | 00:54 | Now we can move forward with Building
and Monetizing Game Apps for Android.
| | Collapse this transcript |
| Using the exercise files| 00:00 | If you have access to the Exercise
Files for this course, you can use the same
| | 00:04 | files that I used when developing the course.
| | 00:07 | In the Exercise Files folder you will
see a folder called assets, which contains
| | 00:11 | all the assets used throughout the
course, and then folders broken up into
| | 00:15 | Chapters that correspond to the
table of contents for the course.
| | 00:19 | Some Chapters don't have any Exercise
Files. You'll see that when you see a
| | 00:24 | plain text file named, there are
no Exercise Files for this chapter.
| | 00:28 | Most chapters are broken up into
folders. Each folder is connected to a movie
| | 00:33 | and has a start and a final state,
that way you can see the starting code and
| | 00:38 | the finish code to check it against your own.
| | 00:40 | The start and final folders
have subfolders called the Classes.
| | 00:44 | You can use these Classes to
override the Classes in Eclipse.
| | 00:48 | Finally, some chapters, like Chapter
5, do not make any modifications to
| | 00:54 | the Exercise Files.
| | 00:55 | For those chapters I included all of the
files that I modified, and you can just
| | 01:00 | drop them in with the project,
as I'll show you in those movies.
| | 01:03 | Let's look at how to use the
assets and Classes folders.
| | 01:07 | I'm going to open up Eclipse.
| | 01:09 | To import the assets into Eclipse,
select all the files in the assets folder, and
| | 01:14 | click and drag them into
the assets folder in Eclipse.
| | 01:18 | Note that you can also copy these files
into the assets folder in your project
| | 01:22 | files on your hard drive as well.
| | 01:24 | You will then be then asked if you
want to copy your link to files.
| | 01:28 | Choose Copy and click OK and then hit Yes
To All to override all the files in there.
| | 01:33 | Those files will then be
imported into your project.
| | 01:35 | I'll just hit Cancel.
| | 01:37 | For the Classes you can do the same thing.
| | 01:39 | So for Chapter 4 for example, you
grab all the Classes in there, select them
| | 01:45 | All, drag them right on to Classes. Then I'll
be asked if I want to Copy or Link to files.
| | 01:51 | Again choose Copy, hit Yes To
All to override all the files.
| | 01:54 | Just make sure to backup
your files before doing that.
| | 01:58 | The Classes folder can be found
inside of your Android project folder.
| | 02:01 | Also remember that when you import
new classes, you'll need to update the
| | 02:05 | android.mk file. That can be found
in the Jni folder in your project.
| | 02:10 | This folder needs references to all of
the classes that you use in your project.
| | 02:14 | So don't forget to add those
as you go through the course.
| | 02:17 | If you don't have access to the
Exercise Files, don't worry, you could
| | 02:20 | still follow along.
| | 02:21 | Throughout the course, I'll show you
what files you need and you can setup the
| | 02:26 | assets in the same way to create your own game.
| | 02:29 | Knowing how these Exercise Files are
setup will help save a lot of time when
| | 02:33 | developing the app throughout this course.
| | Collapse this transcript |
| What you should know before starting this course| 00:00 | Due to the advanced nature of this course, you
should come in already knowing a few things.
| | 00:06 | You should have experience with the C
++ Language, because that's what we are
| | 00:10 | going to be using; and you should have
experience with Java and the Android
| | 00:14 | platform in general.
| | 00:15 | Of course, any other program
experience will help, but it's not necessary.
| | 00:20 | Remember, the more prepared you are
for this course, the more you'll get out
| | 00:24 | of it.
| | Collapse this transcript |
| Viewing the finished game| 00:00 | Here's the finished game on a device.
| | 00:03 | At the title screen you'll notice a
Play button and you'll see there is a High
| | 00:07 | Score area at the top left.
| | 00:09 | If you play the game, you can tap on
the moles and they play a little animation
| | 00:15 | when they come up, and you
tap them, and when they go down.
| | 00:19 | Notice the score at the top left of the
screen goes up as you are playing the game.
| | 00:25 | If you miss a mole, you'll
see that the carrot disappears.
| | 00:28 | Once all the carrots disappear, you
get a game over where you can choose to
| | 00:31 | REPLAY the GAME, or to start from
the beginning, go to the MAIN Menu.
| | 00:35 | If you go to the MAIN Menu you will
see that your HIGH score is saved, this
| | 00:39 | value is saved to the device's memory
and will be retained if you leave the
| | 00:43 | device and come back later.
| | 00:45 | You can pause the game as well using
the Pause button, and Exit to the Main
| | 00:49 | Menu from the Paused screen.
| | 00:51 | Throughout this course we will look at
how to build all of these elements to
| | 00:54 | make the basic game play, and we will
also look at how to monetize the game
| | 00:58 | using Ads and In App Purchases.
| | Collapse this transcript |
|
|
1. Installing Cocos2d-xUnderstanding and downloading Cocos2d-x| 00:00 | The Game Engine I have chosen to do
Android Games is called Cocos2d-X.
| | 00:06 | Cocos2d-X is a Cross-
Platform version of Cocos2d iPhone.
| | 00:11 | You can use the same code base for
your iOS app, your Android app, a Windows
| | 00:17 | app, and a MacOS app.
| | 00:19 | Cocos2d-X uses the same method calls as
Cocos2d, so it's basically, exactly the
| | 00:25 | same, except it's written in C++.
| | 00:27 | As such, you'll need to make some
changes to Eclipse to support C++ and you'll
| | 00:33 | need to some other things to
allow Android to support C++.
| | 00:37 | So to download and install Cocos2d-X, go to
cocos2d-X.org and then click on the Download link.
| | 00:47 | The version of Cocos2d-X that I'm
using for this course is 2.0.1. Likely when
| | 00:53 | you're watching this course, there
will be a newer version of Cocos2d, but I
| | 00:57 | highly recommend using
this version for this course.
| | 01:02 | All the code is not guaranteed to
work if you're using a later version of
| | 01:06 | Cocos2d, because things may be
deprecated and you just open yourself up to
| | 01:10 | problems in that way.
| | 01:11 | To find older versions of Cocos2d,
just look at the link at the bottom of my
| | 01:15 | screen this says More historical versions.
| | 01:18 | You can search then by the date; the date
that 2.0.1 was released was in June 2012.
| | 01:25 | If you choose to use a different
version of Cocos2d, just know that you'll need
| | 01:30 | to find your own solutions if you run
into any problems, because it's likely
| | 01:34 | that some steps along the way
will be different from mine.
| | 01:37 | So, you'll need to look up
differences in your version of Cocos2d.
| | 01:42 | For that reason I highly recommend using 2.0.1.
| | 01:48 | Once you've made your own game using
Cocos2d-X, you might feel more comfortable
| | 01:53 | using a newer version and
solving those problems on your own.
| | 01:56 | So when you click to download that you'll see
that it shows up in a folder on your computer.
| | 02:02 | Now I've just copied all the files
into my Android folder, which is inside of
| | 02:07 | my documents folder.
| | 02:08 | So now that we have downloaded
Cocos2d-X, we're ready to start creating
| | 02:13 | a Cocos2d-X project.
| | Collapse this transcript |
| Downloading the Android NDK| 00:00 | Using C++ and Android requires something
called the Android NDK, which stands for
| | 00:07 | Native Development Kit.
| | 00:08 | So here you'll find the downloads of
the NDK, so you can click the appropriate
| | 00:13 | download for your platform.
| | 00:15 | Note that you can get the old version
of NDK by right clicking the link for the
| | 00:20 | current version of the NDK and copying
and pasting that link into your browser
| | 00:26 | window, and changing the version number
to like. So if it's r8b or e, change it
| | 00:33 | to r8b in the link and that should
take you to the appropriate file.
| | 00:37 | If you're working with a future version
of the NDK, some features that are shown
| | 00:42 | in this course might not be supported.
| | 00:44 | So now let's go the System and Software
Requirements Section of this document.
| | 00:48 | I'm just going to click link,
near the top of the page.
| | 00:51 | Now most of this is pretty
straightforward. Yyou're going to need the Android
| | 00:55 | SDK already installed.
| | 00:57 | I'm not going to cover that in
this course, because it's been covered
| | 01:00 | extensively in multiple other
Online Training Library courses.
| | 01:03 | And you'll need the
Requirement Development Tools on Windows;
| | 01:07 | you'll need Cygwin version 1.7; so
you can click this link, and go over to
| | 01:15 | Cygwin.com and download it and install it there.
| | 01:18 | So this will enable you to run the
Shell commands that you'll need to create
| | 01:23 | your Android cocos2d-x project.
| | 01:25 | So once you've got the Android NDK
downloaded and downloaded and installed
| | 01:30 | Cigwin if you're on Windows, just
confirm that it's in the appropriate place.
| | 01:35 | Mine is in my Android folder, which is
in my Documents directory, so I've that
| | 01:38 | Android NDK, r8b folder right here. And it
has all the necessary files inside of it.
| | 01:45 | So now we have NDK setup and ready to use.
| | Collapse this transcript |
| Creating a Cocos2d-x project template for Eclipse| 00:01 | Unfortunately creating a Cocos2d-X
project for Android is not as easy as just
| | 00:06 | going to File>New Cocos2d-X project.
| | 00:09 | You actually need to create the project
in your file system, and then import the
| | 00:13 | project into Eclipse.
| | 00:15 | And by the way, if you're missing
Eclipse or the Android SDK inside of Eclipse,
| | 00:21 | you'll need to make sure to download and
install those based on the instructions
| | 00:25 | in the Android Essential Training Course.
| | 00:27 | So to do that, start with the cocos2d-x
folder, and that's where I have cocos2d-x
| | 00:34 | installed on my hard drive.
| | 00:36 | And there are two files in there,
create-android-project.bat and
| | 00:39 | create-android-project.sh. Bat is what
you're going to use on Windows and sh is
| | 00:44 | what you are going to use on Mac.
| | 00:46 | I'll show the Mac version first, and
then we'll look at the Windows version
| | 00:50 | in just a few seconds.
| | 00:51 | So I'm going to open this file with
TextEdit, and I'll right-click it to open up
| | 00:55 | that menu. And then I'm going to
need to change these two variables
| | 00:58 | NDK_ROOT_LOCAL and ANDROID_SDK_ROOT_LOCAL.
| | 01:00 | I'm changing NDK_ROOT_LOCAL to /User/
ldc/Documents/android/android-ndk-r8b.
| | 01:03 | Now I am going to make the change to
Android_SDK_Root_Local change it to
| | 01:18 | /User/ldc/Documents/android/android-
sdk-macosx. I can just check that path
| | 01:30 | against what's in my Documents folder,
android-sdk-macosx, and then I can save
| | 01:36 | this file and close it.
| | 01:38 | Now let's go back to that
cccos2d-x folder and open up
| | 01:42 | create-android-project.bat if you're
on Windows. And I'm going to right click
| | 01:47 | and open it with Other and
I'm going to choose TextEdit.
| | 01:51 | Now in here you're going to do the
same thing that you did on the Mac side of
| | 01:55 | things, and just modify the appropriate
files, so there are three variables here
| | 01:59 | though, instead of two.
| | 02:00 | So if you look in this section here,
you're going to need to tell the path to
| | 02:04 | the bin folder inside of the Cygwin
folder where you installed Cygwin. And then
| | 02:09 | you're going to need to set the path
that where you installed the Android SDK
| | 02:13 | and the tools folder inside of
it, and then set the NDKROOT.
| | 02:17 | So this is where you installed the Android NDK.
| | 02:20 | If you're on Windows, you can
just double click this bat file here.
| | 02:23 | If you're on a Mac you'll need to
open up a Terminal window, change the
| | 02:27 | directory to this
directory and run the Shell script.
| | 02:30 | So let's open up Terminal now. I'm
going to press Command+Space and open up
| | 02:34 | Terminal, and in Terminal I'm going to
change the directory to my cocos2d-x
| | 02:38 | directory. So I'm going to type cd space,
and then I'm just going to drag in the
| | 02:44 | cocos2d-x folder, and press
Return to change the directory.
| | 02:48 | And now I'm going to run that script,
so it's ./create-android-project.sh, and
| | 02:58 | you can see that I am just running
this file right here, and then if I press
| | 03:02 | Enter, it's going to ask me a few
questions, so Input the package path.
| | 03:06 | And this is your reverse domain structure.
| | 03:08 | So I'm going to type com.
| | 03:10 | You can type your domain name here, I'm
going to type toddperkins.moleitx, and
| | 03:16 | then you should see a list
of supported Android versions.
| | 03:19 | So it's going to ask you to input an id,
so there's 1 which is Android-10, which
| | 03:25 | is Android 2.3.3. And you may get a few
more depending on how many versions of
| | 03:31 | Android you have installed with SDK.
| | 03:33 | So I'm just going to type in 1, and then
press Enter, because that applies to Android-10.
| | 03:39 | Now that might not be the same number
that you need to type in, so you might
| | 03:43 | need to look at your list of Android
SDKs and find Android-10, it might be 2
| | 03:49 | or 3 or 4, but just make sure that the
number that type in is associated with Android-10.
| | 03:55 | And then I need to create a project name
and I'm going to call this moleitx, I'm
| | 03:59 | going to press Enter. And if everything
worked okay, then you're going to see a
| | 04:04 | Created file Created directory.
| | 04:05 | If something goes wrong, you are going
to see messages like file does not exist.
| | 04:09 | So if that happens, just make sure
that you follow all these steps correctly.
| | 04:13 | Now what I want to do is look inside the
cocos2d-x folder, and I should see a moleitx folder.
| | 04:19 | Now the way that these folders get
created is inside of your cocos2d-x
| | 04:25 | installation folder.
| | 04:26 | So if you're following the tutorials in
this course, I'm going to show how to do
| | 04:30 | it assuming you're creating all
the files using this default way.
| | 04:35 | So if you look in the moleitx folder,
you'll see all the Classes, so the basic
| | 04:38 | HelloWorld classes, and the project.
android folder and the Resources folder.
| | 04:44 | So we successfully created this
project template and we're one step away from
| | 04:48 | being able to import it into Eclipse.
| | Collapse this transcript |
| Finishing the project template| 00:00 | The last step in creating our project
template is to go into the moleitx folder
| | 00:05 | that we created, go into project.android
or proj.andriod. We're going to run the
| | 00:12 | build_native script.
| | 00:14 | Now to run this script, you're going
to need to use Cygwin on Windows or
| | 00:18 | Terminal on the Mac.
| | 00:20 | So open up the appropriate app and in
Terminal, I'm going to change the directory.
| | 00:24 | You're going to need to do
the exact same thing in Cygwin.
| | 00:27 | So I would use the cd command and a
space and change the directory to the
| | 00:31 | appropriate directory; and then once
you're in the appropriate directory, you're
| | 00:34 | going to run that build_native script.
| | 00:36 | To do that type ./build_native.sh. Now
this should take a minute or two and it
| | 00:44 | will just run through creating all the
appropriate files, and once that's done,
| | 00:48 | you'll be able to import this project
into Eclipse and run a cocos2d-x project.
| | 00:56 | So the script is complete and
everything is setup as far as the file system is
| | 00:59 | concerned, and this project is
ready to be imported in Eclipse.
| | Collapse this transcript |
| Preparing Eclipse to use C++| 00:00 | Since Cocos2d-X uses C++;
| | 00:03 | we will need to add that to Eclipse.
| | 00:06 | My version of Eclipse is actually
Eclipse Classic and did not come with C++
| | 00:10 | functionality out-of-the-box.
| | 00:12 | However, I did add it and
I'll show you how that works.
| | 00:15 | I am going to go to Help>Install New
Software, and then in the drop-down menu at
| | 00:19 | top, choose the appropriate version for
your Eclipse Release, mine is juno. And
| | 00:24 | you can wait for a minute for this
area here in the middle of the screen to
| | 00:28 | populate and this process is probably
actually very familiar to you if you have
| | 00:31 | installed the Android Platform. And
then scroll down to Programming Languages.
| | 00:36 | So what I done here is I've checked
all of these ones that are grayed out,
| | 00:41 | except for auto tool support for CDT.
| | 00:43 | So don't check that one, but check
the rest of the ones that are grayed out,
| | 00:47 | and then install them.
| | 00:49 | And then you can click next, and make
sure you read the agreement and agree to
| | 00:53 | it before you click to Install and then
you can have all the C++ libraries that
| | 00:58 | you need to create your Cocos2d app for Andriod.
| | 01:02 | Once you have C++ connected to Eclipse,
you are ready to bring in your Android
| | 01:07 | project and start building your games.
| | Collapse this transcript |
| Importing the project into Eclipse| 00:00 | We're going to import the project into
Eclipse as an existing Android project.
| | 00:05 | So we go to File>New and choose Other,
and under Android, choose Android Project
| | 00:11 | from Existing Code and click Next.
| | 00:13 | For the Root Directory hit Browse,
and then we are going to find the
| | 00:17 | project.androiddirectory.
| | 00:18 | So open up that Cocos2d-X folder
where you created the moleitx folder and
| | 00:23 | in there just double-click on project.android
and click Open, and then click Finish.
| | 00:27 | So, now we have created the project.
| | 00:29 | The next step is to convert it into a
hibrid C++ project, so right-click, and
| | 00:35 | choose New> Convert to a C/C
++ Project (Add C/C++ Nature).
| | 00:42 | You can also go to File>New and do the
same thing, or you can go to Other and
| | 00:48 | then choose that option.
| | 00:50 | Okay, so I am choosing Convert to C/C++
project, and I have a project checked
| | 00:55 | here, we got C++ here.
| | 00:58 | And then I'm going to get a Makefile
project on the left side and choose
| | 01:02 | Other Toolchain on the
right side and click Finish.
| | 01:05 | Now we have made this a hybrid project
and we have to modify a few of the settings.
| | 01:10 | So, I am going to right-click my
project, and I'm going to choose Properties.
| | 01:14 | The first place I am going to ago is
under C/C++ Build. I'm going to uncheck Use
| | 01:20 | Default Build Command, and I'm going to
type bash space ${workspace_loc:/} name
| | 01:32 | of my project which is
com.toddperkins.moleitx.moleitx}/ and then
| | 01:45 | build_native.sh space NDK_DEBUG goes -
1 and a space V=1, hit Apply.
| | 01:58 | Next I am going to go to Code
Analysis, under C/C++ General;
| | 02:02 | I am going to choose Use project settings.
| | 02:04 | And I'm going to actually hide all
of these errors and warnings, because
| | 02:08 | Eclipse tends to give you inaccurate errors
and warnings that stop your app from running.
| | 02:14 | And so we are just going to let log
cat handle all of our errors and warnings
| | 02:18 | and not worry about what
Eclipse has to say about them.
| | 02:21 | Click Apply and then hit on over to
Path and Symbols. In the Includes section,
| | 02:26 | hit Add and we are going to include two
sets of files, we're going to go to where all
| | 02:31 | my android files are stored.
| | 02:33 | And in the android-ndk, under platforms,
android-9 arch-arm user include, I am
| | 02:42 | going click Open, hit OK and we are
also going to include the Cocoas2d files.
| | 02:48 | So, we'll hit Add again, then
File system, and then android, under
| | 02:52 | cocos2d_x, I'm going to go to cocos2d_x
and find the Include folder, choose
| | 02:59 | that one and hit Open, hit OK.
| | 03:01 | And next we'll go to Source Location,
that's the tab inside of Paths and Symbols.
| | 03:06 | We are going to hit Link Folder.
| | 03:08 | I am going to link to the Classes folder.
| | 03:10 | So, check the boxes that says Link to
folder and File system, and hit Browse,
| | 03:14 | and go to your Projects Classes folder.
| | 03:16 | So, I am going to open up moleitx and
just double-click the classes folder and
| | 03:21 | click Open, hit OK and then Apply.
| | 03:24 | And it says I need to rebuild my
projects, so I am going to hit Yes, hit OK.
| | 03:29 | And at this point your app should
actually run on a device, there are a few extra
| | 03:35 | changes you'll have to make
to run it in the simulator.
| | 03:37 | But we'll take a look at that in another movie.
| | 03:40 | So, at this point, if you can test this
app on a device and get the HelloWorld
| | 03:44 | Cocoas2d app launching, then you're in business.
| | Collapse this transcript |
| Adding GLES 2.0 support to your emulator| 00:00 | There are three things that you need to
do in order to get your app running in
| | 00:04 | the Android Emulator.
| | 00:06 | This all stems because Cocos2d uses
OpenGl ES 2.0 and that's not supported by
| | 00:13 | default in the Android Emulator.
| | 00:15 | So step one is to tell the Emulator
to support it, step two is to tell the
| | 00:20 | Manifest that your application requires
it, and step three is to add something
| | 00:26 | to your code to resolve a potential bug.
| | 00:29 | So, first let's open up the
Android Virtual Device Manager.
| | 00:33 | I am going to select my 4.1
device and click Edit.
| | 00:36 | And here you can see I have a Hardware
feature called GPU emulation; you can add
| | 00:41 | that by clicking New. Make sure you
set the value to yes, and then edit your
| | 00:45 | current AVD, or create a new one.
| | 00:48 | I am going to Cancel out of these
menus, and then I'm going to open up
| | 00:51 | AndroidManifest.xml.
| | 00:52 | In here in the Manifest Extra section,
I am going to click Add, and then choose
| | 00:57 | Uses Features and click OK.
| | 00:59 | Now I need to say that I
require OpenGl ES Version 2.0.
| | 01:03 | Here I'm going to write the
hexadecimal value in GL es version field.
| | 01:07 | At 0X00020000, for Required choose
true, Save the file, and close it.
| | 01:17 | Then open up moleitx.java, you'll find
that inside the source folder. Scroll
| | 01:23 | down to the detect OpenGl ES 2.0 method.
| | 01:26 | This method is bugged, because
sometimes info.req.GLEsVersion returns
| | 01:32 | an incorrect value.
| | 01:33 | So, to cover for that, we will add an
or condition to this Return value, and in
| | 01:40 | there we will type BUILD.FINGERPRINT.
startsWith and in the parentheses () passed
| | 01:45 | in the string "generic," and before I
save the file, I am going to click on the
| | 01:51 | error and then just double-click to
Import the Build Class. And the error should
| | 01:54 | go away and I'll save the file.
| | 01:56 | Now before I test this in the
emulator, I want to show you something.
| | 02:00 | I am going to click onCreate on the right
side of the screen to go to that method.
| | 02:04 | And then I'm going to scroll down where
it says mGLView setTextField. We can go
| | 02:11 | down a few lines and I am going to
paste some code that I have already written.
| | 02:15 | Just check to see if BUILD.FINGERPRINT.
starts with ("generic") just like we just wrote.
| | 02:19 | What that does again is make
sure that we are in the emulator.
| | 02:23 | So, it is in the emulator,
we're going to run this method.
| | 02:27 | mGLViewsetEGLConfigChooser,
passing in 8, 8, 8, 8, 16, 0.
| | 02:33 | Now the reason why I am showing
this code is because on the forums for
| | 02:39 | Cocos2d-X, some people found this to work
to get their apps to run in the emulator.
| | 02:45 | However, when I run this code on my
computer, it crashes the emulator.
| | 02:51 | So, it didn't work for me,
but it may work for you.
| | 02:55 | So, it just depends on your case.
| | 02:57 | So, I'm showing you this code in case
you still have problems getting the code
| | 03:01 | to run in the emulator.
| | 03:03 | But I'm going to undo that change,
and then click the Run button to test it
| | 03:08 | out in the emulator.
| | 03:09 | After awhile the app should launch in the
emulator, keep in mind it might take a while.
| | 03:14 | The Android Emulator is
infamous for being pretty slow.
| | 03:17 | So, here I have the app, it says
Hello World, it's running in the Android
| | 03:21 | Emulator. I have it in landscape mode, which
you can do by pressing Ctrl+F11 and there it is.
| | 03:28 | So, I'll just make sure that if you
want to test this in Emulator, you have to
| | 03:32 | account for the Cocos2d debug that
gives you inaccurate information about the
| | 03:36 | OpenGl ES Version, declare it in
your Manifest and set your Emulator to
| | 03:42 | support GPU emulation.
| | Collapse this transcript |
| Fixing additional compiler issues| 00:00 | It is possible that after you've done
all of these steps that you still can't
| | 00:05 | run your Android application.
| | 00:08 | If you're having problems,
here are two more things to try.
| | 00:11 | You can go in the Project Properties
menu, click on Java Compiler, and then you
| | 00:16 | can Enable project specific settings and
make sure that your Compiler compliance
| | 00:20 | level is set to 1.6.
| | 00:23 | You can also go, if you're on Windows to C/C++ Build,
Build Variables and click Add.
| | 00:30 | If you already see one called path, then
add the path to the Cygwin bin folder there.
| | 00:39 | If you don't see path, click Add to add a
new variable called it PATH, in all caps.
| | 00:45 | You can change the Type to a
Directory, click Browse, and then browse to
| | 00:50 | where you installed Cygwin. And then click
on the bin folder, and choose the bin folder.
| | 00:57 | You'll need that to run the bash
command when you compile your app.
| | 01:01 | So if you are having those problems,
try these solutions and they should
| | 01:06 | help out.
| | Collapse this transcript |
|
|
2. An Introduction to Cocos2d-xUnderstanding scenes, layers, and sprites| 00:00 | To create a Game with Cocos2d, you'll
have to have a good understanding of how
| | 00:04 | scenes, layers, and sprites work's together.
| | 00:07 | You'll also need to know how to organize
your projects and how to use the various
| | 00:12 | tools that are built in the Cocos2d
to make creating a game easier for you.
| | 00:16 | Throughout this chapter we are going
to explore all of those things, that way
| | 00:20 | when we start creating a game you'll
have an idea of all the concepts and then
| | 00:25 | you'll just see how they
work together to create Game.
| | 00:27 | The first thing we need to look at is
scenes, layers, and sprites. These objects
| | 00:33 | are the fundamental building blocks of Cocos2d.
| | 00:35 | Think of a scene as a state of your game.
There is only one scene running at a
| | 00:41 | time, and a scene is controlled by the director.
| | 00:45 | The classes in Cocos2d have the prefix CC.
| | 00:48 | So, for example you might have one CCScene
that's the MainMenu, and you might
| | 00:53 | have another CCScene that represents your Game.
| | 00:57 | Again only one may be running at a time.
| | 01:00 | Within a scene you have objects called Layers.
| | 01:03 | A layer is a visual object that
can group other visual objects.
| | 01:09 | Visual Objects are called sprites.
| | 01:12 | In a slide here you see the green outline
around the blueMole that represents a CCSprite.
| | 01:17 | In the layer, there are three different
Sprites. As you move your Layer around, the
| | 01:23 | moles move around as well.
| | 01:25 | When you're working with a game, all
of your visual elements are going to be
| | 01:29 | organized in layers on the scene.
| | 01:31 | You're not going to be sub-classing
CCScene, but rather you'll be sub-classing
| | 01:36 | CCLayer and putting all your visual
elements in there and organizing them
| | 01:41 | similar to organizing layers in Photoshop.
| | 01:44 | So for example you may have one
layer that has all of your game play, and
| | 01:48 | other layer that's in front of that
layer its has your heads-up display that
| | 01:52 | includes things like the score, maybe
a pause button, the number of lives a
| | 01:56 | character has left, etc,.
| | 01:59 | So, again a scene is a state of your
application and only one may be running at a time.
| | 02:04 | Scenes are organized into layers,
which can be placed in front of or in back
| | 02:09 | of each other just like Photoshop,
and layers contain individual graphic
| | 02:13 | elements called sprites.
| | Collapse this transcript |
| Using scenes, layers, and sprites| 00:00 | Let's walk through our Cocos2d
HelloWorld project and see how scenes, layers,
| | 00:05 | and sprites, work together in co.
| | 00:07 | If you don't have access to the
Exercise Files, you can just use the
| | 00:10 | default HelloWorld project.
| | 00:12 | So, I have the AppDelegate and
HelloWorldScene class files open right now.
| | 00:17 | In AppDelegate I am going to scroll
down to applicationDidFinishLaunching; here
| | 00:21 | we have a reference to the Director.
| | 00:23 | Remember, the Director controls which
scene is playing and only one scene can
| | 00:29 | be playing at once.
| | 00:30 | The Director is a singleton
instance that you can access through the
| | 00:34 | SharedDirector method of the CCDirector class.
| | 00:38 | Through the Director you can control
whether to display the frames per second
| | 00:42 | using setDisplayStats, you can
control the frames per second that your
| | 00:47 | application runs at using setAnimationInterval.
| | 00:50 | So, here we have (1.0 / 60),
which is 60 frames a second.
| | 00:54 | And then here we have a reference to a Scene.
| | 00:58 | The Scene is coming from the value
returned from HelloWorld::scene method.
| | 01:04 | Then the Director is told to
runWithScene and the Scene values passed in.
| | 01:08 | So, that's what starts the process
of running the Cocos2d app. We use
| | 01:14 | runWithScene and the scene starts.
| | 01:16 | So, the scene is a static
method in a HelloWorldclass.
| | 01:20 | Let's go to the HelloWorldscene.cpp.
| | 01:23 | In the Scene method we create a blank
scene using CCScenes::create() method,
| | 01:30 | than we create an instance of a
HelloWorld class using its create method.
| | 01:36 | Think of create method almost like new
HelloWorld or new CCScene; we are creating
| | 01:41 | an instance of the object.
| | 01:42 | And then we use the scenes->addChild()
method to add the layer to the screen.
| | 01:46 | Add child works like add child works
in Flash; this is how you get visual
| | 01:52 | objects onto the screen.
| | 01:54 | Once an object is set as a child
object, if you move the parent object, the
| | 01:59 | child object moves along with it.
| | 02:01 | So we are putting the layer inside of
the scene and then we return the scene.
| | 02:07 | So again that's scene is just a generic
CCScene and thing that's custom is the Layer,
| | 02:12 | which is the HelloWorld Layer. It's
going to store all of our visual objects.
| | 02:16 | When the create() method runs, the
init () method is called as well; that's
| | 02:20 | part of what the create method does is it
initializes the instance using its init () method.
| | 02:26 | In the init () method we are running
the super init through CCLayer and then we have
| | 02:31 | some objects created.
| | 02:32 | CCMenuItemImage, which is a button with
an image file, CCMenu which organizes a
| | 02:38 | set of buttons and puts them on the
screen. And keep in mind these visual objects
| | 02:43 | like the Menu item are subclasses of sprites.
| | 02:46 | So then we use addChild to put the
Menu with the button on the screen
| | 02:52 | scrolling down to CCLabelTTF*,
that's a TrueType font label running it's
| | 02:58 | create () method passing in value of "
Hello World" which is a string that will
| | 03:02 | display in the text field.
| | 03:04 | The font used in the font size, the
CCSize holds a width and height values. We
| | 03:10 | can get the width and height of the
screen using the Directors getWindSize
| | 03:14 | method. The position of the label is set,
and the label is added to the screen
| | 03:20 | by calling the Layers addChild method.
| | 03:22 | The numberthat's passed in as a second parameter
represents the Z positioning of the object.
| | 03:28 | So a higher value means closer to the
front, a lower value means closer to the back.
| | 03:32 | And we have a Sprite using it's create
() method and passing again the value of
| | 03:37 | an image in our assets.
| | 03:39 | We can create a sprite based on the image,
set it's position, and again add it to
| | 03:43 | the screen with is the Z-index of 0.
| | 03:47 | So we have our Scene that is the state
of the application, the Layer where all
| | 03:51 | the visual others are organized,
and the visual objects or sprites or
| | 03:55 | subclasses of sprites.
| | Collapse this transcript |
| Positioning sprites| 00:00 | Positioning a sprite is all about
understanding the x, y coordinates of the
| | 00:04 | screen and of the sprite itself.
| | 00:06 | The x, y coordinates of a screen begin
at the bottom left, and increas as they go
| | 00:10 | up and right, so the origin
at the bottom left here 00.
| | 00:17 | And if you were to look at a screen
that's 480 pixels wide by 320 pixels high,
| | 00:21 | it would look like this.
| | 00:22 | So, 0,320 for the top left, 480,320 for the
top right, and 480,0 for the bottom right.
| | 00:28 | So, let's take a sprite for example.
| | 00:31 | Let's say we wanted to
position sprite on the screen.
| | 00:34 | A sprite actually has a
centered x, y origin or anchor point.
| | 00:39 | Of course this can be changed by
adjusting the sprite anchor point, but the
| | 00:43 | default position is in the center.
| | 00:45 | So, if you don't position the sprite
it will show up at the bottom left of
| | 00:48 | the screen like this.
| | 00:50 | You can place it in any of the corners by
using the same values as the corners have.
| | 00:55 | So, just remember now the x, y origin
of the screen is at the bottom left and
| | 01:00 | the x, y position of the
sprite is based on its center.
| | Collapse this transcript |
| Adjusting basic sprite properties| 00:00 | The main graphic elements you are going
to be working with in Cocos2d are Sprites.
| | 00:04 | So, it's important to take some
time to understand how a sprite works.
| | 00:08 | Also I have some assets imported to my project.
| | 00:11 | And if you don't have access to
Exercise Files, you can just use the HelloWorld
| | 00:15 | files that are built in with the project.
| | 00:17 | So I've made some basic
changes to the HelloWorld app.
| | 00:21 | The first ones are in AppDelegant.cpp,
I just changed the setDisplayStats value
| | 00:27 | to (false) instead of true, so we
don't see the frame around the screen.
| | 00:31 | And let's go to HelloWorldScene.cpp and
I have deleted most of the code inside
| | 00:37 | of the init () method except for the
size variable; we are going to use it.
| | 00:41 | Now what we are going to do is create a
Sprite and place it at the center of the screen.
| | 00:46 | So CCSprite is going to call this *bg
for background, we are going to use that
| | 00:52 | create method () create the object, and
remember that we pass in the string of
| | 00:58 | the file that we want to load in, and
my file is called moles_bg.png. Of course
| | 01:04 | if you have a different file
then you type that name in there.
| | 01:07 | On the next line we're going to
set the position of the background,
| | 01:10 | so bg->setPosition. And the value that
we pass in is a point, which is in x,
| | 01:16 | y-coordinate and the shortcut to
create in x, y-coordinate in Cocos2d is ccp;
| | 01:21 | that's all lower case.
| | 01:23 | And the first value passed in is x-coordinate;
| | 01:25 | the second value is the y-coordinate.
| | 01:27 | Remember if we want to put this object
in the center of the screen, it's going to
| | 01:31 | be half the width and half the
height of the screen respectively.
| | 01:35 | So, we pass in (size.width,size.height
) and then remember before we can see it
| | 01:42 | we need to add it as a child. Not only
will you not see an object if you add it as a
| | 01:48 | child, but the object will
actually get removed from memory.
| | 01:51 | Now the way the Cocos2d memory works is
that objects that are added as children
| | 01:56 | are saved and once an object is
released from being a child of another object,
| | 02:01 | it's automatically released from memory
the next time garbage collection occurs.
| | 02:06 | So keep in mind that you
don't want to forget to addChild.
| | 02:11 | So, this->addChild, and remember we
don't just pass in the child name, we
| | 02:17 | also pass in z-position.
| | 02:18 | We are going to pass in -1, I want
this to be behind everything else.
| | 02:23 | Now keep in mind that if I put a
layer behind this HelloWorld layer, just
| | 02:27 | because I'm passing a value of -1
it's all relative to that layer.
| | 02:31 | So a layer behind another layer
sprites will not overlap. All the objects in
| | 02:37 | the back layer will be behind the front
layer no matter what their z-positions are.
| | 02:41 | So at this point this is would put
the background at the top right of the
| | 02:45 | stage, because we're using
size.width and size.height.
| | 02:48 | So I am going to divide them by 2 and
that will put the object right at the
| | 02:53 | center of the stage and so we can
save and test that in the Emulator.
| | 02:56 | And when you test it in the
Emulator it should look like this.
| | 03:00 | So we just have the object
right in middle of the screen.
| | 03:03 | Now let's say we want to change the
scale of it to fill the hole size of the
| | 03:08 | screen, that's actually knows
sprite property that you'd want to edit.
| | 03:10 | Now what we are going to do is grab the float
of the x-ratio and the y-ratio and then
| | 03:15 | we're going to apply the scale in that way.
| | 03:18 | Because unfortunately with Cocos2d you
can't just say, set the object to this
| | 03:22 | size, it doesn't work right.
| | 03:24 | So we are going to need to just use a
scale which is based on a percentage of
| | 03:29 | the size of our objects.
| | 03:30 | So, right below where we create a
background, I'm going to scroll down a little
| | 03:35 | bit and I'm going to create
two float values, rX and rY.
| | 03:40 | rX is going to be the x-ratio of the size
of the screen to the size of the background.
| | 03:46 | And so what we do is we take the size
of the screen, size.width and we
| | 03:52 | divide that by the size of the
background; to get the size of the background do
| | 03:56 | (background) bg->getContentSize().width.
| | 03:59 | So that's our ratio horizontally, I'm just
going to copy and paste this and change
| | 04:05 | rX to rY, and change size.
with to size.height, and then
| | 04:11 | bg->getContentSize().height.
| | 04:14 | Okay, so I have my ratio
and now I just scale it.
| | 04:17 | So what we do is on the next line we
go to bg->setScaleX(rX) and then we pass
| | 04:25 | in the horizontal value and
the same thing Y setScaleY(rY).
| | 04:32 | Right, I'll run the app in the Emulator
and here it is. So this is a way that we
| | 04:38 | can handle different screen sizes on
Android, we can pick an art size, or two
| | 04:43 | art sizes - maybe one high-resolution,
one low resolution one - and scale the art
| | 04:48 | depending on the size of the screen.
| | 04:50 | So we can easily get it to match the
screen size so the art looks pretty close
| | 04:55 | to the same on devices with
a variety of screen sizes.
| | 04:59 | So, back to the code, there are many
other methods that you look at, I recommend
| | 05:03 | looking at the documentation for Cocos2d-
X and just seeing what other properties
| | 05:07 | that you can modify in the same way.
| | 05:10 | So, far we have looked at the
position of a sprite with set position, the
| | 05:14 | size of a sprite with getContentSize,
and scale with getScale and X scale Y.
| | 05:18 | If you take way to X or the Y and those
methods, you can scale the whole object uniformly.
| | 05:24 | So, I recommend again looking at
documentation and just seeing which properties
| | 05:28 | you may want to modify as
you are working with sprites.
| | Collapse this transcript |
| Handling touches| 00:00 | The control schemes on most
touchscreen games are based on touch.
| | 00:05 | So obviously it's important to
understand how to handle touches in your games.
| | 00:10 | Let's go to HelloWorldScene.h and we
will create a void method, and this is going
| | 00:16 | to be called CCTouchesBegan.
| | 00:17 | What we're doing is we're
overriding the superclass method here.
| | 00:23 | ccTouchesBegan and it's going to
receive two parameters, the first one is a
| | 00:30 | cocos2d ::CCSet, call this *pTouches; and the
second is a cocos2d::CCEvent, call this *pEvent.
| | 00:40 | And then I am just going to copy and
paste this definition into the class files.
| | 00:48 | So, I am going to save, go
over HelloWorldScene.ccp.
| | 00:52 | And here at the bottom of the init()
method, I'm going to add one line of code
| | 00:57 | that's going to be this->
setTouchEnabled, then pass in a value of (true).
| | 01:03 | Once you set the TouchEnabled, the
ccTouchesBegan event will automatically be
| | 01:08 | fired off as soon as a Touch Begins.
| | 01:10 | Note that there is also a ccTouches ended,
moved, and canceled, which you can learn
| | 01:16 | about more in the documentation.
| | 01:18 | So, outside of init() method I'm going
to paste the code that I copied, and right
| | 01:22 | before ccTouchesBegan I
am going to add HelloWorld.
| | 01:25 | Now the first thing we need to do is
just capture a single *touch. Since we're
| | 01:29 | only worried about one touch for now,
| | 01:33 | I'm going to grab any object out of the CCSet.
| | 01:36 | So CCTouch, we'll call this touch, we
will set it equal to typecast in ccTouch
| | 01:43 | of pTouches any object.
| | 01:46 | And next we're going to create a
ccPoint, we'll call this Location, set it
| | 01:51 | =touch->locationInView. That's going
to return in x-y-coordinate, but it's not
| | 01:58 | align with a Cocos2d-X Y coordinate so we are
going to need to convert it to a GL location.
| | 02:02 | Let's go to the next line inside
Location=ccDirector sharedDirector
| | 02:09 | convertToGL() and then pass in the Location.
| | 02:14 | So, now we have the Location of our touch.
| | 02:17 | Now what we will do to just show that
it's working properly is we'll create
| | 02:21 | sprite at that Location.
| | 02:23 | So, each time we tab the
screen we'll just drop a mole there.
| | 02:26 | So, ccSprites just call it *sprite
set it =ccSprite::create passing the
| | 02:32 | string moles_icon.png.
| | 02:35 | Of course if you don't have that file
just, let's pass in the name of a file
| | 02:40 | that is in your project; sprites->
setPosition and positions is going to be
| | 02:44 | Location and then finally we need
to add it as a child of the layer.
| | 02:50 | So, this->addChild and remember we have
the two parameters, the first one is the
| | 02:56 | Child, Sprite, the second one
is the Z-position which is 1.
| | 03:00 | Keep in mind if you continue to add
objects at the same z position, they don't
| | 03:04 | overwrite each other; the
newer ones go in front of the older ones.
| | 03:08 | So let's save this and test it
out in Emulator and see what we get.
| | 03:13 | So, here's the app running in the
emulator and of course we see that blank
| | 03:17 | background with nothing on it in.
| | 03:18 | And if I click on the screen I
should see moles popping up where I click.
| | 03:22 | So there we go our Touches
are working just as they should.
| | 03:25 | So remember if you want to support
Touches you are going to have to set the
| | 03:29 | TouchEnabled property to (true)
using this-> setTouchEnabled, then you're
| | 03:33 | going to have to implement the
ccTouchesBegan() method or any of the other
| | 03:37 | touch handling methods.
| | 03:39 | You can grab the location using a
TouchesLocationInView () method and
| | 03:43 | converting that to a GL point by using
the Director is convertToGL() method.
| | 03:50 | After that you can handle the
Touch information however you like.
| | Collapse this transcript |
| Accessing accelerometer data| 00:00 | Another popular control scheme for
Android devices is Accelerometer control.
| | 00:05 | To add Accelerometer control to your app,
go inside of your layer subclass and
| | 00:10 | then implement the super
class method called didAccelerate.
| | 00:14 | It's going to receive an object in
the cocos2d namespace and that's called
| | 00:19 | CCAcceleration, and we'll name
that parameter *pAccelerationValue.
| | 00:22 | I'm just going to save this file, and
then I'm going to copy this code and paste
| | 00:28 | it right into our class.
| | 00:30 | So far it's pretty close to what we've
looked at before with the touches, and
| | 00:35 | we're going to implement a super
class method, and we're also going to
| | 00:41 | setAccelerometerEnabled in init.
| | 00:44 | You also notice that I have an
existing Sprite that I created in header file,
| | 00:48 | so I have the CCSprite here called mole
and in the class file I've initialized
| | 00:54 | it, and just set it to be in the middle
of the screen. Below that I am going to
| | 00:58 | type this->setAccelerometerEnabled.
We're going to set that true and scroll
| | 01:06 | down to didAccelerate.
| | 01:08 | And now this pAccelerationValue
parameter has the values that we need.
| | 01:12 | There are two general ways that people
look at acceleration in games, so let's
| | 01:16 | say you have an object that you want to
tilt, and it's going to move across the
| | 01:20 | screen based on how much you tilt it,
so once you've tiled it all the way to
| | 01:25 | the left, then the object should be all
the way to the left of the screen, once
| | 01:29 | you tilt it all the way to right the object
should be all the way to the right of the screen.
| | 01:34 | So let's look at how to do that first.
The first thing we need to do for that is
| | 01:39 | to grab the percentage that the
device has been tilted, the values in
| | 01:42 | pAccelerationValue range from -1 to +1,
so to get the percent, we're going to
| | 01:46 | need to manipulate that a little bit.
| | 01:47 | Let's first create a CCSize variable
called s and we'll set that to be the size
| | 01:52 | of the screen; so CCDirector,
sharedDirector, and then getWinSize.
| | 01:57 | Okay on the next live we'll create a
float called percentsX and we're going to
| | 02:03 | set it equal to, in parentheses (
pAccelerationValue->x), and we're going to add 1 to
| | 02:12 | it. Remember I said it's from -1 to +1,
so this will make it from 0 to 2, and
| | 02:17 | after the parenthesis, we'll just divide
that number by the total range which is to 2.
| | 02:22 | (pAccelerationValue->x +1)/2; so we
have the percent that the device is tilted
| | 02:25 | here. Let's just copy and paste this line
to the next line, change X to Y in each
| | 02:31 | instance, and then we'll apply that to
the position of the mole. So we'll go
| | 02:35 | down a few lines, and then run mole->
setPosition, then we're going to pass in
| | 02:39 | the ccp and that's going to be
percentsX times * s.width, and then percentY
| | 02:48 | times * s.height. This will put the
mole, just like I was saying earlier, at the
| | 02:53 | position on the screen that's directly
coming from acceleration value. You tilt
| | 02:58 | the device all the way to the left, the
mole will be all the way to the left of
| | 03:02 | the screen; tilt it all the way to
right and mole will be all the way to the
| | 03:07 | right of the screen, all the
way front, back, and so on.
| | 03:10 | Keep in mind there is also acceleration Z,
if you want to grab that data for anything.
| | 03:14 | At this point I would show you this
app running in the Android Emulator, but
| | 03:18 | acceleration is not supported in the Emulator.
| | 03:20 | So if you want to test it, you
actually have to test it on a device, and just
| | 03:24 | make sure before you test it that you
add that HelloWorld namespace to the
| | 03:28 | method, just like that. So you can save
and you can test that on the device and
| | 03:33 | it should work just like I've stated.
| | 03:34 | So, I mentioned that there's
another method that the people use for
| | 03:37 | accelerometer control and that is
grabbing the accelatationValue and
| | 03:41 | manipulating the object based on the value.
| | 03:44 | So when you tilt to the left, the object
will slide to the left at a speed based
| | 03:50 | on the tilt of the device.
| | 03:52 | A steeper tilt means faster movement,
but it doesn't correspond to the exact
| | 03:58 | position of the Sprite, it's
actually relative to where it is currently.
| | 04:03 | Think of it like a labyrinth game. You
tilt the labyrinth a little bit and the
| | 04:07 | ball doesn't automatically go all the
way to the end of labyrinth if you tilt it
| | 04:11 | all the way to the side; rather you
tilt it and the ball moves at the speed
| | 04:16 | relative to the angle of the labyrinth.
| | 04:18 | So we're going to do that here. I'm
going to comment out this line of code
| | 04:22 | where we set the position of the mole,
and then we're going to grab the current
| | 04:26 | position of the mole and hold it in a
variable.So CCPoint, I'm going to call
| | 04:30 | this P, and we'll set it equal to the
position of the mole, so mole->getPostion,
| | 04:34 | and then we're going to go to the next
line and we'll set the position of the
| | 04:39 | mole. So mole->setPosition, and we're
going to use a new method this I called
| | 04:45 | ccpAdd capital A. And now this
actually adds one point to another point, so
| | 04:52 | it's an easy way to manipulate the position
of an object on the screen, which is nice.
| | 04:57 | So the first value is a ccPoint so
I'll pass in p and then a comma and then a
| | 05:03 | second value is a ccPoint as well. So
for this one I'm going to type ccp and in
| | 05:08 | the parenthesis I'll pass in the
accelerationX value, so pAccelerationValue->x
| | 05:14 | and then for the Y value I'll do
the same this, pAccelerationValue->y.
| | 05:23 | At this point you should be able to
test it on a device and the speed at which
| | 05:27 | the mole moves will depend
on the tilt of your device.
| | 05:30 | If it's going too slow, you can just
multiply the x and y values by 10 for
| | 05:35 | example, or whatever value
you want, to adjust the speed.
| | 05:39 | Those are the main two ways you'll
handle acceleration in your games. Either you
| | 05:43 | make it exactly correspond to the
position of the device or you have an object
| | 05:47 | move based on the tilt of your device.
| | 05:50 | Remember that when you're implementing it,
to implement the didAccelerate method
| | 05:54 | and to setAccelerometerEnable to true,
and then you can grab the accelerometer
| | 05:59 | values using the pAcceleration value
parameter and its x, y and z members.
| | Collapse this transcript |
| Understanding Cocos2d actions| 00:01 | Cocos2d Actions enabled you to run
commands over a period of time or in a sequence.
| | 00:07 | For example, you could animate just
about any property inside a Sprite.
| | 00:12 | You can animate its position,
rotation, scale, opacity and others.
| | 00:17 | Let's look at how Actions work.
| | 00:19 | At the bottom of ccTouchesBegan, I'm
going to run an action on the mole, so
| | 00:23 | mole->runAction, and then inside the
parentheses, it's going to be CCMoveTo
| | 00:29 | static method create.
| | 00:31 | And here I just pass in a time and a position;
| | 00:35 | now the time is in seconds, so if I want it to
be 1 second, pass in a 1, and then location.
| | 00:41 | So I have the mole move to wherever I click.
| | 00:45 | Now let's look at that in the Emulator.
| | 00:47 | And here it is, in the Emulator. You'll
notice that if I click anywhere that the
| | 00:51 | mole moves to that point.
| | 00:53 | Let's say I wanted something to happen
when I actually click on the mole; to do
| | 00:58 | that I can create an if statement.
| | 00:59 | What you want to check in the if
statement, is to see if the bounding box of the
| | 01:04 | mole contains the location that was touched.
| | 01:06 | So to do that, let's type CCRect,
that's the namespace, and method is
| | 01:10 | CCRRectContainsPoint. And the first
thing passed in is the rectangle which is
| | 01:15 | the bounding box of the Sprite, so mole
boundingBox, that's a rectangle with z
| | 01:22 | width a height and xy coordinates.
And second parameter is the point that
| | 01:28 | represents the location you're testing against.
| | 01:30 | So pass in location and if that's
inside of the mole's bounding box, then
| | 01:35 | we'll run the Action.
| | 01:36 | So let's just cut and paste this
MoveTo action inside the if statement and
| | 01:41 | we'll change move to CCScaleTo.
| | 01:43 | You'll see that it works in exactly
the same way; you creat it with a create
| | 01:49 | method, and then you pass in the scale value.
| | 01:52 | So let's say I wanted it to be 10%
bigger than the default size, we'll just pass
| | 01:57 | in that 1.1 in there and I can test this
after I save it; so I'll just Save, and
| | 02:04 | then go and open up the Emulator.
| | 02:07 | So here's the app running in the
Emulator, I should be able to click outside of
| | 02:11 | the mole, and see nothing happens. And
then if I click right one the mole, then
| | 02:15 | it scales up just a little bit.
| | 02:16 | So that's the basic idea of Actions.
They generally modify some type of property
| | 02:21 | on an object over a period of time.
| | 02:23 | There are many different Actions in
Cocos2D, many more than we can list in one
| | 02:28 | movie for that matter.
| | 02:29 | So I recommend going into the
documentation and looking at the Actions that are
| | 02:33 | available just to get an idea
of what you have to work with.
| | Collapse this transcript |
| Working with sprite sheets| 00:00 | Up to this point all the graphics
that we've used are individual files. The
| | 00:05 | problem with that is many platforms
bloat up individual files to the nearest
| | 00:10 | power of 2, so 2, 4, 64, 128 etcetera.
| | 00:16 | So that creates all of this
empty space and wasted memory.
| | 00:19 | Enter SpriteSheets.
| | 00:20 | SpriteSheets enable you to pack your
Sprite images into one big file that
| | 00:26 | confines itself to the powers of 2
and eliminates those memory problems.
| | 00:31 | I'm at codeandweb.com/texturepacker
now; if you want to learn more about
| | 00:37 | SpriteSheets, just click this
SpriteSheet movie link, and there is an animated
| | 00:40 | video that shows how
SpriteSheets work that's quite informative.
| | 00:44 | So TexturePacker is actually the one
that I use personally for my games, just
| | 00:48 | because you get a lot of excellent
features for a relatively low price.
| | 00:53 | Another one I used to use is
called zwoptex, which you can find at
| | 00:56 | zwopple.com/zwoptex.
| | 00:58 | Zwoptex also has a free Flash version, if
you click the download link at the bottom.
| | 01:04 | That version includes an HTML file that
will load in a Flash movie that enables
| | 01:09 | you to bring in some Sprite.
| | 01:11 | Now of course this is a very water down
version of the full SpriteSheet creator.
| | 01:16 | But if you want to do something for
free this is your best bet for now. You can
| | 01:21 | go to File>Import Images, select the
Sprites you want to import; once you've
| | 01:25 | imported them, you can arrange them,
so that they're spaced out. And then you
| | 01:29 | can choose File>Export Texture and
File Export Coordinates, and bring both of
| | 01:33 | those files into your Eclipse project.
| | 01:35 | Now the features in Zwoptex and
TexturePacker are a little bit different, but
| | 01:39 | they're generally the same and I'll
leave their respective documentations and
| | 01:44 | instruction manuals for
how to use them specifically.
| | 01:47 | But basically it's the same situation;
we're going to import Sprites and you're
| | 01:51 | going to export a texture and coordinates.
| | 01:54 | And you're going to need
to bring those into Eclipse.
| | 01:57 | Your texture file should be .png file or
in TexturePacker it could be a .pvr.ccz.
| | 02:04 | And your coordinates will be a .plist
file which is a Raw text XML file that
| | 02:09 | contains the coordinates for all of the images.
| | 02:11 | So let's go over to Eclipse and
look at how a SpriteSheet works.
| | 02:15 | Of course now assuming that you do
have a SpriteSheet ready, and all we need
| | 02:20 | to do is go to our HelloWorldScene and
we're going to need to add the Sprites
| | 02:24 | from the SpriteSheet.
| | 02:25 | So right above where we
created the mole, I'm going to type
| | 02:28 | CCSpriteFrameCache::
SharedSpriteFrameCache->addSpriteFramesWithFile.
| | 02:36 | And in the
addSpriteframesWithFile method I'm going to pass in the
| | 02:39 | string moles.plist.
| | 02:42 | Now obviously if you have a different
plist file, you're going to pass in the
| | 02:46 | name right there, and then I'm
going to change the create method to
| | 02:50 | createWithSpriteFrameName, now this
is on the line of code where we're
| | 02:55 | instantiating the mole.
| | 02:56 | Now I'm going to change this frame
name to c0011.png.Now this is the name of
| | 03:05 | one of the Sprite files that I
loaded in when I crated the SpriteSheet.
| | 03:09 | And when you Export it you could open
up that plist file in a TextEditor or
| | 03:14 | Xcode if you have it, and you could
look at the names of the different Sprites.
| | 03:17 | But they're going to be exactly the
same as the files that you imported into
| | 03:22 | your SpriteSheet creator,
| | 03:24 | unless of course you change the setting
inside of the SpriteSheet creator app.
| | 03:28 | So I have c0011.png and I'm going to put
it right in the middle of the screen and we
| | 03:35 | should see a mole graphic
when we test it in the Emulator.
| | 03:38 | I am going to Save this file and tab
over to the Emulator, and there it is.
| | 03:42 | Now I'll go back to Eclipse. So when you
unload Sprites, you're going to need to
| | 03:47 | create the SpriteSheet in the
SpriteSheet trading app, whether that's the Flash
| | 03:51 | version of Zwoptex or another
app that you decide to purchase.
| | 03:55 | You can add the Sprites to your project,
you can add your SpriteFrames to the
| | 04:00 | sharedSpriteFrameCache using
CCSpriteFrameCache::sharedSpriteFrameCache,
| | 04:06 | addSpriteFramesWithFile and passing in
the name of the plist file. And then you
| | 04:11 | can create a Sprite using a
SpriteFrame with createWithSpriteFrameName and
| | 04:16 | passing in an
appropriate name for a SpriteFrame.
| | 04:19 | Now remember, using SpriteSheets will
save on memory and thus enable you to add
| | 04:24 | more artwork to your applications
and allow them to run more smoothly.
| | Collapse this transcript |
| Creating simple frame animations| 00:00 | We've already looked at doing an
animation by modifying Sprite's properties with
| | 00:05 | an Action, but if you want to create an
animation of frames, you'll have to go a
| | 00:11 | slightly different route.
| | 00:13 | You can grab these animation frames
using an animation program like Flash or
| | 00:18 | AfterEffects, or you can take still
images from a program like Photoshop.
| | 00:23 | Once you have the Animation frames, make
sure they're in your SpriteSheet and
| | 00:27 | loaded into your app.
| | 00:28 | In the touchesBegan method, the first
thing I do is stop all currently running
| | 00:32 | actions using stopAllActions method.
| | 00:35 | That way we don't get any conflicts,
when we run the animate action.
| | 00:39 | So here I'm going to create a
CCArray, that's below stopAllActions.
| | 00:43 | We'll call this frames, and we'll
set it equal to CCArray::create.
| | 00:48 | The CCArray class is an array that holds
any type of data, so it's very easy to
| | 00:53 | work with when you're making a Cocos2D game.
| | 00:56 | You can create one using the create
method, and you can add objects to it, using
| | 01:00 | the addObject method.
| | 01:01 | Now we'll create a for loop. In the for
loop we'll run a loop from 1 to 11, so I
| | 01:09 | have for integer i<=1 as long as i
is less then or equal to 11, i++.
| | 01:15 | All of my animation frames are stored in
order, and they're numbered from 1 to 11.
| | 01:20 | So they're b0001, b0002
all the way up to b0011.png.
| | 01:29 | So we'll use a string to grab a string name for
each frame, we'll hold that in a CCString object.
| | 01:36 | Just like CCArray, CCString is an easy
way to create and manipulate strings.
| | 01:42 | We'll call this frame and we'll it set
equal to CCString::createWithFormat, and
| | 01:48 | then we'll pass in the string, "b%04d.png".
After the string we'll pass in i, so
| | 01:57 | that will give us the
appropriate name for each frame.
| | 02:02 | And now we need to put the
frame inside of the frames array.
| | 02:06 | Now to create our animation frames, we need
to pass in CCSpriteFrames and not CCStrings.
| | 02:13 | So we'll do that by doing frames->
addObject, and then we'll pass in
| | 02:19 | CCSpriteFrameCache::
sharedSpriteFrameCache, ->SpriteFrameByName, in the
| | 02:26 | parentheses pass in the frame, and we
are going to need to convert this to a
| | 02:31 | CString by running its method getCString.
| | 02:33 | Outside of the loop we'll run the
moles instance method runAction,
| | 02:40 | it's mole->runAction.
| | 02:42 | Now we're going to pass in one object,
that's a CCAnimatedObject, so we'll run
| | 02:46 | its create method, standard for Cocos2D.
| | 02:49 | And in the create method we're going to
pass in a CCAnimation, which is a series
| | 02:56 | of frames held in a CCArray and the
speed at which the animation should play.
| | 03:00 | So CCAnimation, we'll call its create
method, then we'll pass in the frames, and
| | 03:06 | then .15 for the speed. Now this is in
seconds and normally you do this a little
| | 03:11 | faster, but I'm keeping it sort of slow,
because I'm showing this movie in the
| | 03:16 | Emulator and I want to make sure
that you can see it in this movie.
| | 03:19 | So we'll tab over to the Android
Emulator and you'll see the animation here,
| | 03:23 | if I just click anywhere on the screen, so
there is the mole coming up from the bottom.
| | 03:27 | So if you want to create your own
frame by frame animations, you need to
| | 03:31 | CCArray, put each frame inside of the
array and then run the CCAnimate Action
| | 03:37 | passing in a CCAnimation object with
the frames and the speed at which you want
| | 03:42 | the animation to play.
| | Collapse this transcript |
| Setting a game to display in portrait mode| 00:00 | Now the app we're building in this
course is actually a landscape app, so
| | 00:04 | everything we have looked at so
far has been in landscape mode.
| | 00:08 | But what if you wanted to
do Cocos2D in portrait mode?
| | 00:10 | Well actually all you have to do is
go to AndroidManifest and find the main
| | 00:15 | activity for your app and just change
the screen orientation from landscape to
| | 00:19 | portrait and that is
literally all you have to do.
| | 00:22 | So just change it to the portrait, and
if you save the file and you check it out
| | 00:27 | in the Emulator, you'll see that
everything is scaled accordingly so that
| | 00:30 | background element is recognizing that
the app actually is a portrait app and
| | 00:34 | not a landscape app.
| | 00:35 | So it's incredibly easy, just like
you do for any of your other apps, just
| | 00:40 | change the screen orientation from
landscape to portrait and everything in
| | 00:43 | Cocos2D is going to work perfectly,
meaning the width and height of the screen
| | 00:48 | are going to adjust
because it's in portrait mode.
| | 00:51 | So, that's all you have to
do to work in portrait mode.
| | Collapse this transcript |
| Designing for multiple screens| 00:00 | On Android you have to
design for multiple screen sizes.
| | 00:04 | We've already looked at that just a
little bit in scaling our background, but
| | 00:08 | for a whole game the process is
just a little bit different than that.
| | 00:12 | Here in the init method right under
where I create size, what I'm going to do
| | 00:16 | here is to decide to use either my high
resolution artwork or my low resolution
| | 00:20 | artwork, because of course, you have
a higher resolution devices and lower
| | 00:24 | resolution devices, and you don't want
to use the high resolution art on every
| | 00:28 | single device, because it
might not perform that well.
| | 00:31 | So, here we'll create a CCString and
we're going to call this *file and we'll
| | 00:36 | set it equal a conditional statement
to check to see if size.width > 480.
| | 00:44 | Now of course, this is just an
arbitrary number, you can take any number you
| | 00:48 | want for your high resolution artwork.
| | 00:50 | But I'm choosing 480 her. And ideally
you would put this method in maybe a
| | 00:55 | Utility class so you can constantly
just check to see if you should use your
| | 00:59 | high resolution art.
| | 01:01 | So after the parentheses
I'll put a question mark (?)
| | 01:03 | and we'll do CCString::create and then
we'll use the high resolution version,
| | 01:08 | which is just a double
resolution version of the same image.
| | 01:11 | So, it's going to be "moles_bg-hd.png".
| | 01:17 | -hd setting comes from the iPhone
graphics in Cocos2D, which get picked
| | 01:22 | automatically when you're
on a high resolution device.
| | 01:25 | So I'm just using the same naming
convention here, so I can use the same files.
| | 01:29 | If the screen is not a high
resolution, then we're going to provide the
| | 01:33 | low resolution graphic.
| | 01:35 | So CCString::create and then we'll
pass in that low resolution graphic which
| | 01:41 | is just moles_bg.png.
| | 01:44 | And now in the create method on the
next line, when we create the background
| | 01:48 | Sprite, we'll pass in that file and
we'll use an instance method getCString and
| | 01:55 | we'll grab the CString for that.
| | 01:57 | And that's really all you have to do.
| | 01:59 | If you test it in the Simulator
right now, you're going to see a high
| | 02:03 | resolution background image.
| | 02:05 | So, what we'll do now is do the same
thing for a SpriteSheet and I'm going to
| | 02:10 | copy this whole line of code starting
right after the * and then we'll paste it
| | 02:15 | down right above where we add the
SpriteSheet. And I'm just going to change the
| | 02:19 | files to moles-hd.plist and moles.plist
respectively, same thing in
| | 02:27 | addSpriteFramesWithFile.
| | 02:30 | We'll do file, instance method getCString.
| | 02:34 | And now if we save and check this out
in the Emulator, here's what we get.
| | 02:38 | It's maybe hard to tell on your
screen right now, but this is a double
| | 02:42 | resolution background and Sprite graphic.
| | 02:44 | Note that I've also scaled up the mole.
| | 02:48 | If you look at the setScale here, I've
scaled that up based on the ratio of the
| | 02:53 | X size of the screen.
| | 02:54 | Of course, you could scale it up
however you want and I recommend saving the
| | 02:59 | scale value somewhere so that you
know the ratio that you should scale
| | 03:03 | everything up or down as appropriate.
| | 03:06 | And that's how you design for multiple screens.
| | 03:08 | You just have different sets of artwork,
one for lower resolution screens, one
| | 03:12 | for higher resolution screens and
you scale your artwork based on the
| | 03:15 | relationship of your art
size, to your screen size.
| | Collapse this transcript |
| Running Java code from C++| 00:00 | Let's say you wanted to add In-App
Purchase or a Link to a Web Browser App on
| | 00:05 | the device or you do
anything else that runs Java code.
| | 00:09 | In order to do that you're
going to use something called Jni.
| | 00:12 | You can use that to run Java
code from C++ and vice versa.
| | 00:17 | Right now, we're going to look
at running Java code from C++.
| | 00:20 | I am going to start by saying I
intentionally chose to use prewritten code in
| | 00:25 | this movie because most of it is semi-
copied from somewhere else or something
| | 00:30 | that you already know how to do
for being an Android developer.
| | 00:33 | The first step is to link to the jni files
just like you link to the Classes folder.
| | 00:38 | Remember in the C++ settings in the
Project Properties Window, you'll see paths
| | 00:44 | and symbols and there's a source location.
| | 00:47 | So just like we added
classes there, add the jni folder.
| | 00:51 | And the path to the jni files, I
can show you in the Android.mk file.
| | 00:58 | So, let's go in here; I am going to
double-click the tab to expand the view and
| | 01:02 | the path is cocos2dx/platform/android/jni.
| | 01:03 | You want to link to that folder
included in your local C includes, and then I
| | 01:14 | want you to create two new files called
JniURL.h and JniURL.cpp and to add them
| | 01:20 | to the Local Source files in Android.mk.
| | 01:23 | Now before we define what goes
in those files, let's go over to
| | 01:26 | Cocos2dxActivity.java.
| | 01:27 | If you want to know where this file is,
you can find it in your Source Folder.
| | 01:33 | So expand the Source Folder and then
open up the org.cocos2dx.lib package and
| | 01:40 | it's right in there.
| | 01:41 | So open that up and in here
just add a few lines of code.
| | 01:45 | Right after the property declarations,
declare private static Activity called me,
| | 01:50 | and set it equal to null.
| | 01:52 | And this is because we're running
a static method to open the URL.
| | 01:56 | And we want to save this instance,
because there is only one instance of this
| | 02:01 | Cocos2dActivity, and be able to call on
it in our static method. So in onCreate
| | 02:06 | set the value of me to this.
| | 02:08 | So, the static method openURL is very simple.
| | 02:12 | Create a new Intent, set the data to
parse the url and then we run start Activity.
| | 02:18 | So that's standard on Android there.
| | 02:20 | Now let's go over to JniURL.h and here
we declare external "C" and what that
| | 02:27 | does is it enables us to run a method
without referencing an instance of a
| | 02:32 | class or class itself.
| | 02:34 | So we have this method called
openURLJNI where you pass in string and then from
| | 02:39 | anywhere we want we can just
open up a URL in the web browser.
| | 02:43 | Let's go over to JniURL.cpp.
| | 02:46 | So now we're importing some classes.
| | 02:49 | One of them in particular is JniHelper.h
and that has some helper methods, so we
| | 02:55 | can easily run these Jni commands.
| | 02:57 | So this method is defined with a
JniMethodInfo and we check to see if the method
| | 03:03 | exists for the JniHelper::getStaticMethodInfo.
| | 03:07 | Then we pass in that JniMethodInfo
object and then a string to the class
| | 03:14 | where the method resides.
| | 03:15 | This is the fully qualified name
including the whole package separated by
| | 03:20 | slashes instead of dots.
| | 03:21 | Then next is the method name which is
openURL and the next is the data that
| | 03:26 | the method receives.
| | 03:27 | So, this is the Java qualified
name to that class, so the String.
| | 03:31 | And then there is a jstring right here
and that represents a Java string so this
| | 03:36 | is a C++ data type, represents a
Java string. And I set it equal to a
| | 03:42 | NewStringUTF passing in the
url received as a parameter.
| | 03:46 | Then I run CallStaticVoidMethod, passing
in the classID, methodID and the argument.
| | 03:53 | So, that's going to run
openURL in Cocos2dxActivity.
| | 03:57 | Now the last step is to go to
HelloWorldScene.cpp and then we're going to import
| | 04:01 | that JniURL object and in the click
handler, I passed in openURLJNI and a
| | 04:09 | website address. And when you
click on the screen, it should open.
| | 04:13 | Also notice that I've commented out
this line of code, showMessageBoxJNI and
| | 04:18 | there's two parameters, a title for the
MessageBox and the value in the field.
| | 04:22 | You can use that method
if you include MessageJni;
| | 04:24 | I got it from the MessageJni class, as
well as some help from the Coco2dx forums.
| | 04:31 | So if you want to show alert box, that's
how you do it, right now we'll test the
| | 04:35 | app and take a look at clicking on
the screen and how that opens up a URL.
| | 04:39 | And now I'll test this in the Emulator,
and if I click on the screen, you'll see
| | 04:43 | that it exits out of this app and
into the web browser and it goes to the
| | 04:48 | website that I passed in as
a string, back to the code.
| | 04:52 | So, there are a lot of steps using Jni,
but if you use it, you can run Java
| | 04:57 | commands quickly and easily from your C++ code.
| | 05:01 | If you're looking for more
information on how Jni works, take a look at
| | 05:05 | these linked files.
| | 05:06 | Just open them up and look at how these
files run Java commands from C++ and vice versa.
| | 05:12 | By being able to run Java commands
from C++, you have much more power in your
| | 05:17 | applications and you can
tap into native Android calls.
| | Collapse this transcript |
| Running C++ code from Java| 00:00 | Since it's important to know how to
communicate from C++ to Java, you should also
| | 00:06 | know how to communicate from Java to C++.
| | 00:09 | This will become significant later on in
this course when we do In-App Purchases.
| | 00:13 | The In-App Purchasing APIs
are all done through Java.
| | 00:16 | So you need some way to be able
to communicate to C++ if they've
| | 00:20 | completed successfully.
| | 00:21 | Here, we'll look at a simple example
of how to communicate from Java to C++.
| | 00:26 | I've created a file called JniExample.cpp.
| | 00:31 | Ofcourse, you'll need to add this to
your Android.mk file; and here I didn't
| | 00:36 | create a header file, it's just a CPP file.
| | 00:39 | And I declared this
method that returns a jstring.
| | 00:41 | jstring is a C++ data type
that corresponds to a Java string.
| | 00:46 | We're going to call this method from Java.
| | 00:49 | Note the name Java_org_cocos2dx_
lib_Cocos2dxActivity_nativeExample.
| | 00:59 | This long method name is
intentional and is necessary to run this code.
| | 01:05 | Start the method name out with Java
with capital J _ and then the fully
| | 01:10 | qualified class name separated by
underscores instead of dots and then an
| | 01:16 | underscore and then the
method that you're going to define.
| | 01:19 | It needs to receive the
JNI Environment and a jobject.
| | 01:24 | You can also receive additional parameters,
but remember that they are not C++ data types.
| | 01:30 | They're the C++ Java data type, so they're
going to be jint, jbool, jstring etcetera.
| | 01:36 | You can look that up in the JNI documentation.
| | 01:39 | So here what I'm doing is
I'm returning a new UTF String.
| | 01:43 | This is how I create a jstring.
| | 01:45 | I call on the environment,
NewStringUTF and I pass in the string.
| | 01:49 | So if I see this string through a Java
call, then I successfully ran C++ from Java.
| | 01:56 | Let's go to Cocos2dxActivity.java.
| | 02:00 | When you define one of these methods
that you want to run from Java, you define
| | 02:04 | it as a Java method using the keyword native.
| | 02:08 | So this is going to return a string
and the method is called, nativeExample.
| | 02:12 | I'm not defining what the method does here.
| | 02:15 | I'm just calling it out, so that's important.
| | 02:17 | And then I just updated showMessageBox.
| | 02:20 | I've commented this line and I've replaced it.
| | 02:23 | And so for the title, it shows the
title that's passed in and for the message,
| | 02:26 | it runs nativeExample.
| | 02:27 | So, it should get that C++ example.
| | 02:31 | And the way that we show that
MessageBox is the same as we've looked at before
| | 02:35 | with calling a Java method from C++.
| | 02:38 | So I've imported MessageJni.h, then
I'm just calling showMessageBoxJNI, then I
| | 02:44 | pass in first the message,
which is you shouldn't see this.
| | 02:48 | So when you run this in the Emulator,
"You shouldn't see that text" and then the
| | 02:52 | title, so Java->C++ and so, remember
this message should get replaced by that
| | 02:57 | code coming from C++,
it's being called from Java.
| | 03:01 | So, I'm going to open this up in the
Emulator and I'll click the button on the
| | 03:06 | screen and you should
see that pop up showing up.
| | 03:08 | So, there is the MessageBox; the title
is Java->C++ and then Hello from C++ text
| | 03:14 | tells us that Java is running C++
code and grabbing data from it.
| | 03:19 | So by being able to call Java code
from C++ and C++ from Java, we can
| | 03:24 | successfully incorporate all of the
APIs that are either Java only or C++ only.
| | Collapse this transcript |
| Using buttons| 00:00 | We've already looked at touching on the
screen and detecting whether that touch
| | 00:04 | is in the bounds of the Sprite.
| | 00:06 | But there is actually an easier
way to create objects with simple
| | 00:09 | interactivity like buttons.
| | 00:11 | To do that we are going to go in our
HelloWorldScene class and here I've created
| | 00:17 | a mole as the SpriteFrame.
| | 00:19 | If you have Exercise Files you can use any
SpriteFrame here, just name the object mole.
| | 00:25 | Make sure it's a variable that's
declared in your header. And then also in my
| | 00:29 | header I declared about that call
buttonHandler and I just set the mole's
| | 00:32 | visible property to the opposite of what
it is, so running this method will show
| | 00:37 | and hide the visibility of the mole.
| | 00:40 | Under where we add the mole to
the screen, I am going to create
| | 00:44 | a CCMenuItemsSprite.
| | 00:47 | The away that a button works is that
you have something that's a subclass of
| | 00:51 | a CCMenuItem. That goes inside of a
CCMenu which you add to the screen using
| | 00:58 | addChild, and a menu is basically a list of
buttons and a CCMenuItem is an individual button.
| | 01:05 | So CCMenuItemsSprite is a
button made from the Sprite.
| | 01:10 | So we'll call this btn and we'll
set it (=) CCMenuItemsSprite::create.
| | 01:15 | And here we pass in the normal Sprite,
selected Sprite, the target and then the selector.
| | 01:21 | So for the normal Sprite we'll
just create a Sprite in line here.
| | 01:25 | So CCSprite createWithSpriteFrameName
and then we'll pass in the SpriteFrameName
| | 01:32 | which is button_small.png.
| | 01:35 | The next parameter is the selected Sprite,
so if you wanted to change the Sprite
| | 01:40 | when you touch the button, you could
pass in the Sprite here or you can just put
| | 01:44 | in NULL like I'm going to do to keep
the Sprite the same when you touch it.
| | 01:48 | Next is the Target which is going to be this;
| | 01:50 | that's the instance that's going to run
the method that we pass in for the last
| | 01:55 | parameter and for the method or
selector, type menu_selector and then in
| | 02:01 | parenthesis we pass in the selector,
which is HelloWorld::buttonHandler.
| | 02:06 | Make sure you don't have the parentheses
because you don't want to run the method;
| | 02:09 | we're passing the method in as an argument.
| | 02:12 | So on the next line we're
going to create a CCMenu.
| | 02:15 | Remember a menu is what displays the buttons.
| | 02:18 | We'll call this menu and we'll set
it equal to (=) CCMenu create, then we
| | 02:22 | passed in the buttons and we use a null
terminator to say work done passing in
| | 02:28 | the button values, so btn and NULL.
| | 02:30 | And then finally on the next
line we just added as a child.
| | 02:33 | So this addChild and we'll pass in that
menu and the Z position which could be 1,
| | 02:38 | and then we'll save and test. And we
should see that when we test the app, you
| | 02:43 | can click on the button and the mole
shows and it's hidden, it's toggled each
| | 02:49 | time you press the button.
| | 02:50 | So we don't have to worry about
capturing the coordinates of the touch, we just
| | 02:55 | pass in a Sprite into the menu and
it accepts coordinates and runs the
| | 02:59 | appropriate selector.
| | 03:01 | So there is the button and the mole
Sprite down at the bottom, and so as I click
| | 03:05 | you can see that the
mole's visibility is toggled.
| | 03:09 | So creating a button for simple
interactivity like this is very easy, just
| | 03:14 | create a CCMenuItem subclass, you can
look them up in the cocos2d documentation,
| | 03:21 | run the create method, pass in the
Sprite, the selected Sprite, the target,
| | 03:26 | selector, and then add it to a CCMenu,
then you just run any method you want
| | 03:32 | whenever you tap on the Sprite.
| | Collapse this transcript |
| Playing audio| 00:01 | Cocos2D makes adding sound to your
games a simple process with a class
| | 00:05 | called SimpleAudioEngine.
| | 00:07 | To use SimpleAudioEngine, include it in the
class where you want to play a sound effect.
| | 00:12 | So I'll include SimpleAudioEngine.h
and then specify that you're using the
| | 00:17 | namespace CocosDenshion. Then you can
run an effect by using SimpleAudioEngine
| | 00:23 | shared singleton instance shared engine,
and run the method play affect, play
| | 00:29 | background music, etc.
| | 00:32 | Before you play in effect, you want to preload.
| | 00:35 | If you don't preload it, then it will
load into memory at the time that you want
| | 00:40 | the effect to play, and
there will always be a delay.
| | 00:44 | So in the init method we're
going to preload a sound effect.
| | 00:48 | So just SimpleAudioEngine::
sharedEngine()->preloadEffect and the effect is
| | 00:54 | going to be splat.wav.
| | 00:55 | I am just going to copy and paste this
into the buttonHandler and buttonHandler
| | 01:02 | is going to run when we click the
button on the screen and just change
| | 01:05 | preloadEffect to playEffect in the pasted code.
| | 01:09 | And that's all you need to do to play
an effect. It's very simple and it only
| | 01:13 | requires a line or two of code to use.
| | 01:16 | So remember that if you want more information
you can always look it up in the documentation.
| | 01:20 | I am going to Save and we
will test this in the Emulator.
| | 01:24 | Now I'll tab over to the Emulator so
you can see, and if I click on the button
| | 01:28 | you'll be able to hear that sound effect.
| | 01:30 | (music playing)
| | 01:33 | So to recap, if you want to use
SimpleAudioEngine, includ the class, use the
| | 01:37 | CocosDenshion namespace and run the easy
methods preloadEffect and playEffect to
| | 01:44 | addEffects your game anywhere you like.
| | Collapse this transcript |
|
|
3. Creating the Core ClassesViewing a flowchart of the game's core classes| 00:00 | Before we start building the code of
the game, I'd like to discuss how the
| | 00:04 | classes are going to be set up.
| | 00:06 | Now this is just referring to the main
game, so aside for the main menu, we have
| | 00:11 | the game class and this is how it's organized.
| | 00:14 | There is a CCScene, now it's created by the
game layer, and the CCScene has four children.
| | 00:21 | The four children are the GameOver Layer, the
Pause Layer, the HUD Layer and the Game Layer.
| | 00:26 | Now they are stacked
similarly to how they are here.
| | 00:29 | Game Layer is at the bottom, the HUD
Layer is above that, and the Pause and
| | 00:33 | GameOver Layers are in front of the HUD Layer.
| | 00:36 | That means the pop ups in the Pause
and GameOver Layers will display over the
| | 00:40 | rest of the game elements.
| | 00:42 | Each of those layers has its own children.
| | 00:44 | The game has Moles and it has
the Background, those are Sprites.
| | 00:49 | The Mole class is a subclass of CCSprite.
| | 00:52 | The HUD Layer has the score label at
the top left and the Carrots is at the top
| | 00:57 | right, representing lives.
| | 00:59 | The score label is an instance of
CCLabel TTF, that's the text field.
| | 01:04 | And the Carrots are CCSprites.
| | 01:06 | The Pause Layer contains the Pause
Button at the bottom right of the screen
| | 01:11 | and the Popup menu.
| | 01:12 | The GameOver Layer just contains the Popup menu.
| | 01:15 | So this chart is simply for your
reference to have a better idea of how the
| | 01:19 | classes are set up and how the visual
objects in those classes are connected
| | 01:24 | to each other.
| | Collapse this transcript |
| Creating constants and editing the AppDelegate and Main classes| 00:00 | One of the more difficult decisions I
had to make regarding this course was how
| | 00:04 | much code to have prewritten versus how
much code to write inside of the movies.
| | 00:10 | Normally I don't like to use
prewritten code, but this course is an exception
| | 00:16 | because it's so advanced.
| | 00:17 | It assumes that you already are
familiar with working with Android, App
| | 00:21 | development, Java, C++
and programming in general.
| | 00:26 | Since you're very likely an advanced
programmer and understand how a code works,
| | 00:32 | I don't want to waste time showing the
mundane things like creating a menu or
| | 00:37 | creating a certain utility that we've
already covered in the previous chapter.
| | 00:42 | Rather, the handwritten code will
all be relative to the game play.
| | 00:47 | So other utilities I'm going to have
prewritten, and that's what this chapter is all about.
| | 00:52 | I'm going to walk you through the
prewritten code that I have and you can see
| | 00:56 | what it takes to build
the foundation of your game.
| | 00:59 | So, let's go to Constants.h. I always have a
file called Constants.h when I make a game.
| | 01:05 | It just has any kind of constant
values I'm going to be using over and over
| | 01:09 | again like strings or enumerated
values that I can use for tags.
| | 01:13 | A tag in Cocos2D is an integer that
you can apply to just about any object
| | 01:19 | and reference it later.
| | 01:20 | We'll look at more about how that
works later on, but just know that I have
| | 01:24 | these set up in Constants.h.
| | 01:26 | In the AppDelegate file, I
made a few very small changes.
| | 01:31 | If you scroll down to
applicationDidFinishLaunching, you'll see that I edited
| | 01:36 | the setDisplayStats, change it to
false in the Hello World project, and then I
| | 01:41 | set CCTexture2D,
PVRImagesHavePremultipliedAlpha to true.
| | 01:46 | Now what that does is I'm using a Sprite
sheet that's from TexturePacker and the
| | 01:50 | file is a PVR.ccc file.
| | 01:53 | If you use that particular type of file,
then you need to use this line of code
| | 01:58 | in your AppDelegate, so that it works.
| | 02:00 | And that just make Cocos2D
compatible with that type of file.
| | 02:04 | And then finally the main scene that
I'm running is the MainMenu instead of
| | 02:09 | the Hello World scene.
| | 02:10 | Finally, let's go to main.cpp and
inside of that main native init method, I've
| | 02:18 | added these four lines of code.
| | 02:20 | I've mentioned earlier that this app
is a port of an iOS app that I've made.
| | 02:24 | In iOS, you have a retina display device
and a standard display device you develop for.
| | 02:29 | The retina display device is twice
the resolution of the standard display.
| | 02:33 | So, I'm using the same artwork here.
| | 02:35 | I just want to choose whether to use the
standard display or the retina display.
| | 02:39 | So artScale checks to see if the
height of the screen is greater than 400.
| | 02:45 | If it is, then I'm going to use the
retina display scale which is twice the size
| | 02:50 | of a normal scale, and if not,
I'll use 1 for the normal scale.
| | 02:55 | On the next line I have a
float that represents scale.
| | 02:58 | And this is going to decide, the scale that
I'm going to modify all of our objects at.
| | 03:03 | So, I'm going to apply this scale to
basically every visual object in the game
| | 03:09 | and we get the value by taking the
height casting it as a float and then I
| | 03:14 | divide it by also cast it as a float, 320,
which is the original standard height
| | 03:21 | of the art size times the artScale.
| | 03:24 | So, that's either going to be 1 or 2.
| | 03:26 | So basically, I'm just taking the height
of the screen compared to the height of
| | 03:31 | my artwork and that's going to tell me
the ratio at which I should scale all of
| | 03:34 | the artwork in the game.
| | 03:36 | And then I run a static method called
setScale and that's from my Utils class.
| | 03:41 | We're going to talk about the Utils
class in depth later on, but just know for
| | 03:45 | now this is just a setter method.
| | 03:46 | I have a value called scale and it just sets
that value to the value that I pass in here.
| | 03:51 | So basically, I'm just saving that
scale value so I can apply it later.
| | 03:55 | Same with setArtScaleFactor,
this is either going to be 1 or 2.
| | 03:58 | I'm just saving the value for use later.
| | 04:01 | So, there's my constants header file
and some changes that I've made to the
| | 04:05 | classes that come in the Hello World project.
| | Collapse this transcript |
| Building the GameButton class| 00:00 | The GameButton class is a pretty
simple class that's a subclass of CCSprite.
| | 00:05 | I use the GameButton for
all of the menu buttons.
| | 00:09 | So, that's the button graphic that's
green with the text inside that has a shadow.
| | 00:14 | So let's look at how that works.
| | 00:16 | In the header file, you'll see it is
just a subclass of CCSprite and I have
| | 00:21 | two public methods.
| | 00:22 | Let's go into GameButton.cpp and check them out.
| | 00:27 | First, we'll look at buttonWithText and
that's a static method and it returns a GameButton.
| | 00:32 | Here we receive some text
and a Boolean whether it's big.
| | 00:37 | We create the new GameButton, we run
initWithText, passing in the values and
| | 00:42 | then we run autorelease.
| | 00:44 | Autorelease means it will
automatically get removed from memory, if you just
| | 00:48 | remove it as a child that
is of the parent object.
| | 00:51 | And we'll scroll up and look at initWithText.
| | 00:55 | In initWithText, we run the
constructor for CCSprite and then we set the
| | 01:00 | btnFrame; now if it's a big button,
| | 01:02 | we use CCString::create that creates a
string, which is passed in button_big.png.
| | 01:09 | If not, we pass in, button_small.png.
| | 01:11 | The integer fSize represents font size
and that's 18 times the ArtScaleFactor,
| | 01:17 | so that's either going to be 18 or 36.
| | 01:20 | Then we run this->setDisplayFrame.
| | 01:23 | DisplayFrame is the SpriteFrame that
the object currently show, so you can
| | 01:28 | actually manually change the frame
that the Sprite shows at any time.
| | 01:32 | And of course, you could use this
over time if you wanted to it manually
| | 01:35 | create an animation.
| | 01:37 | So, this->setDisplayFrame, then we
grab the spriteFrameByName from the
| | 01:41 | FrameCache and we use btnFrame->getCString
to get the CString from that CCString object.
| | 01:49 | Now CCString is just a utility to quickly
and easily create a formatted string.
| | 01:54 | So that's generally what I use
when I work with a string in Cocos2Dx.
| | 01:58 | And I create a text label using the
create method passing in the text, which is
| | 02:03 | the title that we want to be in the label.
| | 02:06 | Then I have CCString::
createWithFormat to grab FONT_MAIN.ttf.
| | 02:11 | So, FONT_MAIN is from Constants.h.
The file is going to be Toonish.
| | 02:15 | That way if I change the font I want to
use, it's going to use this constant value.
| | 02:20 | So it's very easy to change the font,
I don't have to go through my code over
| | 02:25 | and over again to find every
instance that I use that font name.
| | 02:28 | So, I'll use getCString
again to get the CString.
| | 02:30 | And then I passed in the size of
the font so it's fSize+isBig*fSize.
| | 02:38 | So that gives us our button.
| | 02:40 | And then we have label->setPosition and
we set it to be the center of this object.
| | 02:45 | This object would be the button.
| | 02:47 | If we create that label, we put it on top.
| | 02:50 | This labelShadow here creates another
text label with the same text, the same
| | 02:55 | font and everything, but I offset the
position just a little bit to create the shadow.
| | 02:59 | And then I set the Color to black and
then I turn down the Opacity a little bit,
| | 03:04 | so that creates the shadow.
| | 03:05 | And then for this, I set the
scale based on a scale from Utils.
| | 03:10 | Remember I said earlier that it
was just a getter and setter method.
| | 03:12 | So this is just grabbing the value
that's set in main.cpp, scales the
| | 03:17 | button appropriately.
| | 03:18 | So, that's how the GameButton class works.
| | 03:20 | Just remember, if you ever want to add
a shadow to an object, you just create
| | 03:25 | essentially a copy of that object or
another object with the same properties,
| | 03:30 | offset it a little bit, change its
Color to black and then set the Opacity to
| | 03:34 | something between 0 and 255.
| | Collapse this transcript |
| Constructing the custom pop-up menu utility| 00:00 | The Popup class is another subclass of CCSprite.
| | 00:03 | It has one property called menu
and it has a few methods defined.
| | 00:08 | The addButtonWithText method receives
some text, a target object and a selector
| | 00:13 | to run when the object is clicked.
| | 00:15 | Let's go over to Popup.cpp.
| | 00:17 | Here we'll start in popupWithTitle,
create a new Popup, run initWithTitle,
| | 00:22 | autorelease, and return pop
just like the Button object.
| | 00:26 | In intiWithTitle, we run the Sprite
init and then we create an object called m.
| | 00:31 | This is the Sprite that is the menu graphic.
| | 00:33 | So we put that right in the middle of
the screen and then we give a title using
| | 00:38 | CCLabelTTF to create a TrueType font
title label and we put it on the screen,
| | 00:44 | set the font name and the font
size as we've looked at before.
| | 00:49 | And then I set its position using setPosition.
| | 00:52 | I use some math to place it near the top
of the menu, add it to the screen using
| | 00:59 | addChild and then run setVisible to false.
| | 01:03 | So we hide all of these objects.
| | 01:05 | That's the menu and the title.
| | 01:07 | And then we'll scroll down to addButtonWithText.
| | 01:11 | So we create a MenuItemSprite that puts
in a GameButton, which passes in false,
| | 01:18 | so a small game button.
| | 01:19 | NULL for the selected object, the
target that's passed in and then the same
| | 01:23 | selector that's passed in.
| | 01:24 | And then if a menu doesn't exist
already, we create the menu using the Button
| | 01:28 | and add it as a child.
| | 01:29 | If the many already exists,
we run addChild and then run
| | 01:33 | alignItemsHorizontallyWithPadding.
| | 01:35 | That way it keeps all the
menu buttons aligned properly.
| | 01:38 | And finally, we'll look at the show
method and the show method enables you to
| | 01:43 | choose to show or hide the popup.
| | 01:45 | If you show the popup, the game pauses
and if you hide the popup, the game resumes.
| | 01:51 | So we grab the Game layer from Utils.
| | 01:53 | Again, we'll look at that in just a minute.
| | 01:55 | And then we have if (shouldShow), we
run pauseSchedulerAndActions on the game
| | 02:01 | and that's not a method that I
created that's built into the Cocos2D and it
| | 02:05 | enables you to pause any
selector that's run on a scheduler.
| | 02:09 | So that it runs repeatedly over time
and pauses all the actions as well.
| | 02:14 | So it's a quick and easy method
to basically pause the whole game.
| | 02:17 | So then there is its
counterpart resumeSchedulerAndActions.
| | 02:20 | And then I loop through all the
children in the game and appropriately pause or
| | 02:25 | resume their scheduler and actions.
| | 02:28 | And then I set the Visible
property of the Popup to shoudShow so, it
| | 02:33 | either shows or hides.
| | 02:34 | And then pause or resume the
background music as appropriate.
| | 02:38 | So the Popup menu is a useful class
that pauses or resumes the game when you
| | 02:43 | show it, and you can add buttons and a
title to quickly and easily show a menu
| | 02:49 | to select various options in your game.
| | Collapse this transcript |
| Setting up the code in the MainMenu class| 00:00 | The MainMenu is a subclass of CCLayer
and you could see that it's pretty similar
| | 00:06 | to the HelloWorld default class.
| | 00:08 | I just have one property called S and
then the init, a playGame and mainMenu
| | 00:14 | methods, the same Scene static
method and then the LAYER_CREATE_FUNCTION
| | 00:17 | passing in (MainMenu).
| | 00:18 | Let's go over to MainMenu.cpp and in
here in the Scene menu just as you expect,
| | 00:25 | I create a blank CCScene and then I
create an instance of MainMenu and add that
| | 00:30 | as a child to the scene and return the scene.
| | 00:33 | The init () method initializes CCLayer.
| | 00:37 | Then I set the value S to
be the size of the screen.
| | 00:40 | And then the rest of this code here
preloads the appropriate audio and art files.
| | 00:45 | Now I'm choosing to load either ("moles
-hd.plist") or regular ("moles.plist").
| | 00:51 | Those are the large SpriteFrames for
high-resolution screens and the standard
| | 00:56 | SpriteFrames respectively; that's all
based on if the ArtScaleFactor(>1).
| | 01:01 | I do the same thing for the title screen,
I either load in ("title-hd.png") or
| | 01:06 | ("title.png") and then I load in that
background, setPosition to be the center
| | 01:11 | of the screen,
scaleSprite using Utils scaleSprite.
| | 01:15 | We'll look at that in another movie.
| | 01:17 | And then I add this as a child with this
(-1) as the z-position so that it's all
| | 01:22 | the way in the back.
| | 01:23 | And then I create a playButton using
the GameButton class to create the Sprite,
| | 01:29 | and then I run MainMenu::
playGame as the selector.
| | 01:33 | MainMenu playGame as the selector.
| | 01:35 | MainMenu::playGame runs the Director's
replaceScene method and passes in the
| | 01:38 | game scene. I create CCMenu, put it on the screen.
| | 01:43 | And then I have a method called
MainMenu, which I can run if I ever want to
| | 01:46 | change the game to the MainMenu without
having to write this whole line of code.
| | 01:50 | The MainMenu class is pretty simple
and pretty straightforward, we just have
| | 01:55 | all of our assets preloaded, we drop in the
background and the play button, and that's it.
| | 02:00 | So, the MainMenu class is pretty
simple, we preload all the appropriate
| | 02:04 | assets, we display the background, and
we have the play button play the game
| | 02:09 | when you tap it.
| | Collapse this transcript |
| Making the Utils class| 00:00 | Utils class just holds a whole lot of
static methods that enable us to easily
| | 00:06 | run commands we're going to run
repeatedly from various classes in the game.
| | 00:10 | So, here's the list, now let's go
over to Utils.cpp and take a look at what
| | 00:15 | all these methods do.
| | 00:16 | Now see I have a static float and
int, the float for scale and int
| | 00:22 | for artScaleFactor.
| | 00:23 | If you scroll down to the bottom, you'll
see that setScale and getScale are just
| | 00:28 | simple getters and setters, and same
thing for set and get artScaleFactor.
| | 00:32 | We have also looked at scaleSprite;
this is for background objects, it scales
| | 00:38 | the backgrounds to the
entire size of the screen.
| | 00:41 | Now I chose to do this because I
don't really care if the background is not
| | 00:46 | exactly the right aspect ratio, but
I really want my Sprites to be the
| | 00:51 | right aspect ratio.
| | 00:52 | So, for backgrounds, I just stretch
them to fit the screen and it's never going
| | 00:57 | to be off by that much so I'm not
really concerned about it; but for regular
| | 01:02 | Sprites I use setScale and
getScale to set their values.
| | 01:06 | They're going to be the same aspect
ratio that I created them at and the
| | 01:10 | backgrounds might change a
little bit, because of scaleSprite.
| | 01:12 | I have a method called
getAnimationWithFrames; we just passed in with start frame
| | 01:17 | and the end frame. And I
created a CCArray, and a loop.
| | 01:23 | And in the loop I created a CCString
and it's formatted, so it's a, and then a
| | 01:28 | four digit integer.png, and
then the integer comes from i.
| | 01:32 | So, the loop just goes from the start
frame to the end frame, and then I used
| | 01:37 | addObject method to add the frames to
the Array using CCstrings getCString
| | 01:43 | method and then I create an animation
that runs at 24 frames per second, and
| | 01:49 | then I create an animate object,
which is an action, and I'd simply return
| | 01:55 | the animated action.
| | 01:56 | I have a method called S, that returns
the screen size, layerWithTag grabs the
| | 02:01 | currently RunningScene using the
Directors getRunningScene method.
| | 02:06 | If that Tag=TAG__GAME_SCENE that's a
value that's set in our constants file,
| | 02:14 | then I'm going to use getChildByTag to
grab the appropriate CCLayer and return it.
| | 02:19 | And if we don't find that
layer, I'll return Null.
| | 02:22 | And then we have hudLayer and gameLayer,
they just run layerWithTag, but for the
| | 02:27 | hudLayer and the gameLayer respectively.
| | 02:29 | So, the Utils class is actually pretty
simple, but you'll see throughout the
| | 02:33 | rest of this course that it's very
useful for running commands from all kinds
| | 02:37 | of classes, because these are all static
methods and they are very easy to work with.
| | 02:41 | So once you have this class ready and
you understand it, you are ready to start
| | 02:46 | writing the code for your game.
| | Collapse this transcript |
|
|
4. Building the Basic Mole-Whacking GameAdding the game layers and the background| 00:00 | We'll start building the gamePlay
of our Game in the Game_header file.
| | 00:04 | Remember, if you have Exercise Files,
you can find out how to setup your project
| | 00:08 | to match mine in the Exercise Files
movie at the beginning of this course.
| | 00:12 | If you don't have Exercise Files, just
make sure you have the same class as I
| | 00:16 | do, and that you're referencing
them in your android.mk file.
| | 00:19 | And as we go along and you see that
I'm using a certain Sprite with a certain
| | 00:23 | name you can just add
that Sprite to your project.
| | 00:26 | Here in my class declaration you can
see that I've declared a few properties,
| | 00:30 | and some methods down here.
| | 00:32 | Let's go over to Game.cpp, make sure you
import the appropriate classes, and use
| | 00:38 | the appropriate namespaces.
| | 00:40 | And then scroll down to the bottom
and we are going to start in onExit().
| | 00:43 | I am going to release moles, so moles
->release. And this is just going to be
| | 00:48 | something that is going to be
necessary later on, because we're going to call
| | 00:52 | a method called retain on moles; we
will need to release it when the scene
| | 00:56 | changes back to the MainMenu.
| | 00:58 | And then we are going to call the super
onExit method, so CCLayer::onExit, and
| | 01:03 | then in Game onEnterTransitionDidFinish
this is the code that runs when a scene
| | 01:09 | transitions to another scene.
| | 01:11 | So, let's say you have a scene fade
into another scene, basically this means
| | 01:15 | that your whole scene is loaded and ready to go.
| | 01:18 | This is the best place to initialize
if you have a lot of objects to create.
| | 01:23 | If you do it in init, you might find that
the game starts and your objects are
| | 01:27 | not really created yet.
| | 01:29 | So, I highly recommend initializing
objects, meaning creating artwork and
| | 01:34 | everything in onEnterTransitionDidFinish.
| | 01:37 | So, the first thing we'll do is type
this->setTouchEnabled() and we will pass
| | 01:42 | in (true). And then we're going to initialize
the game on running this, initializeGame().
| | 01:48 | And then let's scroll up to the very
top and in the Scene method we're going to do the
| | 01:53 | same thing that we have done
for the scene and the Game.
| | 01:56 | Notice that we're running setTag after
the createscene, to setTag of the scene.
| | 02:03 | That's how you associate that
Tag integer with a cocos2d object.
| | 02:07 | You can run setTag and you can also
create an object and pass in a Tag as a third
| | 02:12 | parameter into the addChild () method.
| | 02:14 | So, we'll do that for the Hud layer,
call this H, set it =HUD::create() addChild
| | 02:20 | to the scene, give it z of 1,
and TAG is going to be (TAG_HUD).
| | 02:26 | If you are wondering why I picked a
weird name like HUD, it stands for Heads
| | 02:30 | Up Display, which is game talk for a layer
of objects that are user interface elements.
| | 02:36 | Like the score, and the lives,
and pause button, everything.
| | 02:41 | So, now Pause button we'll call it *p,
and we'll do the same thing, we'll set it
| | 02:46 | =Pause::create() addChild C of 1, the
TAG is going to be TAG_PAUSE and finally
| | 02:53 | we'll do the same thing for GameOver.
| | 02:55 | Pretty GameOver object called *go, set
it =GameOver::creates addChild C of 1
| | 03:03 | TAG is (TAG_GAMEOVER), remember these
values are coming from constants.h. And
| | 03:08 | then we'll scroll down to initializeGame, and
here we're just going to create the background.
| | 03:13 | And to create the background will
first need to grab the appropriate file.
| | 03:17 | So, create a CCString and we'll call
this File, and then we're going to put a
| | 03:22 | conditional statement in this line
and check to see the size of the art.
| | 03:26 | We're going to getartScaleFactor, we
are going to check to see if it's (>1), if
| | 03:30 | so, we're going to show the high-
resolution artwork, otherwise we will show the
| | 03:34 | low resolution artwork.
| | 03:35 | To create a ccstring shorthand, you can
use the Command ccs, we just pass in the
| | 03:40 | string in the parentheses (moles_bg-hd.png):
| | 03:48 | or and a same thing, ccs, and
then the string is going to be
| | 03:52 | just "moles_bg.png").
| | 03:56 | On the next line we'll create the
Sprite, so CCSprite, will call it *bg, so
| | 04:00 | it =CCSprite::create, and then we
need to pass in the string of the
| | 04:05 | appropriate filename.
| | 04:07 | So, we use file->getCString()).
| | 04:09 | Now we'll set the position
to the center of the screen.
| | 04:11 | So, bg->setPosition and we will pass in ccp.
| | 04:15 | For the width we'll grab (Utils::s),
it's going to get the screen size, as so
| | 04:21 | .width/2, and the same thing for height
(Utils::s() method, you get the size of
| | 04:26 | the screen .height/2.Now we'll scale
the background (bg), now usually you want
| | 04:31 | to scale an object before
you place it on the screen.
| | 04:34 | But position is centered to the middle
of the screen and its registration point
| | 04:39 | is in the middle of the screen as well.
| | 04:41 | So, scaling it down doesn't matter
whether you do it before or after setting the
| | 04:44 | position in this case.
| | 04:45 | So, we are going to set the scale by
typing Utils and we'll run the method
| | 04:49 | scalesScripte, we will pass in the
background (bg), and remember that we want to
| | 04:54 | stretch the background to
match the same size as the screen.
| | 04:58 | And then we are going to add it
as a Child of the main game layer.
| | 05:02 | If we'll run addChild, pass in (bg),
we give it a Z of 0 and that's it. So
| | 05:09 | save and test this in the Emulator and
what you should get is after you click
| | 05:13 | the MainMenu button to play the game, you
should just get the background on the screen.
| | 05:18 | And if you get the background in
the emulator, you're in business.
| | 05:21 | Great, that was a lot of code just to
get this graphic on there, but we're just
| | 05:25 | laying the scaffolding for the app right now.
| | 05:27 | So, we have the background on the screen,
we have all of the appropriate layers
| | 05:31 | added, and we have the things that
happen when the scene is entered and the
| | 05:35 | scene is exited as well.
| | 05:36 | Now with the setup, we're ready to
start laying out some of the assets in
| | 05:40 | the game.
| | Collapse this transcript |
| Laying out moles in the Game class| 00:00 | To lay out the Moles, we'll first define
what happens when you initialize a mole.
| | 00:05 | Remember that the mole is a subclass
of CCSprite and I have some precreated
| | 00:10 | properties and methods.
| | 00:11 | The only ones that I've defined thus
far are the getter and setter methods, so
| | 00:16 | for the Mole it's only getIsUp.
| | 00:18 | Let's go into the Moles init method
right under where we run the super init
| | 00:22 | method to initialize Sprite.
| | 00:24 | And in here we'll set upTime equal to 2
.0f and we'll set isUp equal to false,
| | 00:30 | and then we'll set the display frame
of the mole, so this->setDisplayFrame.
| | 00:35 | The DisplayFrame is the Sprite frame that
will show for that that particular Sprite.
| | 00:41 | So we'll set the DisplayFrame to
| | 00:43 | CCSpriteFrameCache::
sharedSpriteFrameCache->spriteFrameByName, and the name is
| | 00:50 | going to be the string a0001.png;
save the file and go over to game.cpp.
| | 00:57 | In the initializeGame method, at the
top we're going to initialize the moles
| | 01:02 | array; we'll set it equal to a CCArray create.
| | 01:05 | This will create an auto released
CCArray; that means it will be deleted from
| | 01:11 | memory if we don't choose to retain it.
| | 01:14 | So let's delete those extra parentheses
and go to the next line, and make sure
| | 01:17 | to retain the moles array.
| | 01:19 | So remember if you ever called retain
on the object in cocos2d, make sure you
| | 01:23 | also call an accompanying release
like we did in onExit in this case.
| | 01:28 | Go down a couple of lines, and
then we're going to create a Mole.
| | 01:31 | So we'll create mole called
Mole set it equal to type cast it
| | 01:36 | Mole, Mole::create.
| | 01:38 | Now we're creating the mole just so we
can get its size data, and then we're
| | 01:42 | going to delete it afterwards.
| | 01:43 | So we'll create a float called hPad
and we're going to set this equal to
| | 01:49 | Utils::s. It give us the size of the
screen .width/2 minus in parentheses
| | 01:55 | mole->getContentSize.width times
Utils getScale and after parentheses we're
| | 02:04 | going to multiply that by 3.5f.
| | 02:08 | That number comes from the first
position of the first mole, so we're taking the
| | 02:14 | middle of the screen;
| | 02:15 | we're shifting it to the left by 3.5
moles, relative to their scale.
| | 02:20 | Let's go to the next line and we'll
do the same thing for vertical padding.
| | 02:24 | So we'll call this vPad and we'll set
it equal to Utils::s.height/2 minus mole,
| | 02:32 | getContentSize.height times Utils::
getScale, we'll multiply that by 2.1.
| | 02:43 | Now we don't actually want this to be
in the center of the screen, I just made
| | 02:47 | it shifted up and that's where that .1 comes in.
| | 02:49 | Now go to the next line and just
call delete and delete the mole.
| | 02:53 | Now we'll create a nested
for loop to create the moles.
| | 02:56 | So in the outer loop create an
integer called i, set it equal to 1.
| | 02:59 | I'll run this as long as i is less than
or equal to 4; and of course, i++, and
| | 03:06 | the same thing for the inner loop
except for we'll use j for the iterator. So
| | 03:12 | integer called j equals 1, as long as
j is less then or equal to 6, then j++.
| | 03:19 | We're going to have a total of 24 moles.
| | 03:23 | Now in the loop, create a Mole, we'll
call it mole and we'll set it equal to
| | 03:27 | again a typecasted mole, run Mole::
create, and on the next line we'll set the
| | 03:33 | scale of the mole, so mole->setScale
and we will pass in Utils::getScale, and
| | 03:40 | then on the next line we're going
to set the position of the mole.
| | 03:43 | So mole->setPosition pass in a ccp,
remember that short for a CCPoint, and we
| | 03:49 | passed in an XY coordinates.
| | 03:50 | So the x-coordinate is going to be j
times mole->getContentSize.width times
| | 03:59 | Utils::getScale+hPad.
| | 04:02 | Now we'll do the same thing for the y position.
| | 04:06 | So it's going to be i times
mole->getContentSize.height times
| | 04:12 | Utils::getScale+vPad, and then on the
next line we're going to add the mole to
| | 04:19 | the moles array, so moles->addObject,
pass in mole, and then finally we'll have
| | 04:27 | the gameLayer, add the mole as a
child, so this->addChild mole z of 1.
| | 04:34 | So now you should be able to save and
test this in the Emulator and once you
| | 04:38 | click the Play button from the Main menu,
you should see your screen look like
| | 04:42 | this and all the moles are laid
out and centered on the screen.
| | Collapse this transcript |
| Animating the moles| 00:00 | To animate the Moles we'll begin at
the start method in the Mole class.
| | 00:04 | So in here the first thing we're
going to do is to stop all actions.
| | 00:10 | So, stopAllActions, and then we'll set
isUp equal to true, set didMiss equal
| | 00:14 | to true, and then we'll run an action,
so this->runAction. And this is going
| | 00:19 | to be a CCSequence.
| | 00:20 | A sequence is a series of
actions that run in order.
| | 00:24 | So CCSequence::create, and then it's
a NULL terminated series of actions.
| | 00:30 | So we just end the last one with NULL,
and then I'm going to break this up by
| | 00:35 | lines, so I have CCDelayTime::create
then we pass in the amount of time that we
| | 00:40 | want to delay. And the amount of time
that we want to delay is uptime, which
| | 00:45 | we've set at the top to 2.0f, so
CCDelayTime::create, pass in upTime.
| | 00:51 | Now after that point that person
playing the game has missed this particular
| | 00:55 | Mole after its been up long enough,
and so then we want to stop the mole from
| | 00:59 | animating, and basically this will
count as a miss, which we'll fully handle a
| | 01:03 | little bit later on.
| | 01:04 | Next method is going to call a
function, so CCCallFunc. This is another
| | 01:09 | action that calls a method, so pass
in create, and then we need to pass in
| | 01:14 | the target and the selector.
| | 01:16 | Target is this, that's the object that
has the method that we want to call, and
| | 01:20 | then we pass in the method that we want to call.
| | 01:22 | So pass in callfunc_selector and in the
parenthesis for that, pass in Mole::stop.
| | 01:29 | Make sure to not include the
parentheses, because the argument is actually a
| | 01:32 | method itself and not running the
method, and then I'm just going to copy and
| | 01:37 | paste this block of code that runs
the sequence, and in the pasted code I'm
| | 01:41 | going to change CCDelay time to Utils
::getAnimationWithFrames and the first
| | 01:48 | argument will be 1 and the second will
be 10, so we'll play the first animation
| | 01:53 | that's going to be the Mole coming up.
| | 01:55 | So if you don't have Exercise Files,
you'll need a 10 frame animation here or
| | 01:59 | you can just have a 2 frame animation,
| | 02:01 | however you want to do it. Just pass
the starting and ending numbers in here.
| | 02:05 | Make sure that you've named frames in
sequences well, so a0001, a0002 etc.
| | 02:12 | And then the method that we want to
call this time, in the pasted code is
| | 02:16 | Mole::startLoopAnimation.
| | 02:19 | So we have the mole shoot up and then he
starts the loop animation, and if after
| | 02:24 | the upTime has expired,
then the animation stops.
| | 02:27 | Let's go to startLoopAnimation
and we'll define what happens there.
| | 02:31 | First thing I want to do is check to
see if the Mole is not up; if so, we're
| | 02:35 | going to return, so if not, isUp return.
| | 02:38 | Then we're going to create a CCRepeatForever.
| | 02:42 | A CCRepeatForever is another action
that as you might guess runs forever.
| | 02:46 | We'll call this repeat and we'll set
it equal to CCRepeatForever::create, and
| | 02:50 | then we're going to pass in a CCSequence.
| | 02:54 | Now we're actually going to typecast it
as a sequence first. That's just because
| | 02:59 | of how CCRepeatForever works, it
maybe a bug with cocos2d, but you have to
| | 03:05 | typecast it as a sequence for it to work.
| | 03:07 | So we'll typecast it as a CCSequence,
and pass in CCSequence::create, use the
| | 03:13 | NULL terminator here.
| | 03:14 | So this sequence again is going to run
over and over and over again forever.
| | 03:19 | So Utils::getAnimationWithFrames, we
pass in the start and finish frames which
| | 03:25 | are 11 and 20, separate them with a
comma, and then I'm just going to copy and
| | 03:31 | paste that one of code. And after the
close parentheses, I'm going to run
| | 03:35 | reverse, and that's actually going to
give me a frame 20 through 11 animation.
| | 03:41 | So we'll reverse that animation, very
useful, so we can repeat this animation
| | 03:46 | back and forth and that will go forever,
and before we run it we're going to set
| | 03:50 | a tag on it. So repeat->setTag, and
then we pass in tag that we defined at the
| | 03:57 | top which is TAG_REPEAT_ANIM.
| | 03:59 | And we're going to copy that, pass it in there,
that way we can reference it later if
| | 04:05 | we need to stop it specifically.
| | 04:06 | So this so this->runAction,
and then we pass in repeat.
| | 04:11 | And if you do want to stop one
action in particular, you can
| | 04:14 | run stopActionByTag.
| | 04:16 | So we'll go into stop now to find
what happens when the Mole stops.
| | 04:20 | First thing we're going to do
is run this->stopAllActions.
| | 04:23 | Now in the next line I'm just going to
copy and paste the block of code from
| | 04:28 | start, where we run the Utils::
getAnimation and in the CallFunc, because this is
| | 04:33 | going to be pretty close to the same thing.
| | 04:35 | So the animation is going to frames 1
through 10 reversed, so we'll just run a
| | 04:40 | reverse on that 1 through 10 animation.
| | 04:42 | And the method we want to run is reset;
| | 04:44 | we'll just change startLoopAnimation to reset.
| | 04:47 | And finally we'll define reset. Here
we'll set isUp to false, check to see if
| | 04:53 | the person playing didMiss the
Mole, and if so, we'll run Utils
| | 04:57 | hudLayer()->missedMole.
| | 05:00 | We'll define what that does later on;
| | 05:02 | we're just telling it to run that method now.
| | 05:04 | So save this file and jump over game.cpp,
and then we're going to run the start
| | 05:10 | method on a Mole and should see that the
mole goes up and then goes back down at
| | 05:14 | the end after the time has passed.
| | 05:16 | So after the Moles are created in the
for loop, we'll create a Mole object
| | 05:20 | called m and we'll set it equal to
typecasted Mole, and it's going to be
| | 05:25 | moles->RandomObject.
| | 05:26 | In the next line we'll run m->start.
| | 05:29 | So you can save this file and test it
in the emulator and you should see that
| | 05:33 | one random mole animates up.
| | Collapse this transcript |
| Displaying moles at a specified time interval| 00:00 | Now that we have setup the mole
animation what we'll do is have the moles
| | 00:04 | randomly pop up as time goes on.
| | 00:06 | To do that scroll up to the init ()
method and then we are going to define
| | 00:10 | some property values.
| | 00:12 | And the first one is going to be molesAtOnce.
| | 00:15 | This is going to control how many moles
will show on the screen at one time; we
| | 00:19 | will start that out at 3, and then will
set timeBetweenMoles=0.5F, and then we'll
| | 00:26 | set increaseMolesAtTime=10.0F.
| | 00:31 | So let's scroll down to initialize
game and then what we are going to do is
| | 00:36 | something called schedule () a
selector. And when you schedule_selector it by
| | 00:39 | default runs a method along
with the frame rate of your app.
| | 00:44 | So, if your app is running at 60
frames a second, it will run this method at
| | 00:48 | 60 times per second.
| | 00:50 | So it enables you to control
things over a period of time.
| | 00:53 | So to do that type this->
schedule. and then we're going to pass in
| | 00:58 | (schedule_selector) and in parentheses
pass in (Game::tick). Remember not use
| | 01:04 | the parentheses () for tick as you are
passing in the function not running the function.
| | 01:10 | So, go down to tick and in tick what
we're going to in do is we're going to
| | 01:14 | add values based on the amount of
time that has passed, which is received
| | 01:19 | through this (float dt).
| | 01:21 | So, here timeElapsed += dt;
| | 01:25 | and then on same time we will go to
increaseElapsed += dt; totalTime += dt.
| | 01:33 | And now what we want to do is check to
see if() we should show another mole.
| | 01:37 | Basically we are just checking to
see if enough time is passed, and we're
| | 01:40 | checking the amount of moles on the screen.
| | 01:42 | So, in the if statement, the
first that you are going to type this
| | 01:46 | timeElapsed greater than(>) or equal
(=) to timeBetweenMoles && this->getMoles
| | 01:54 | then we pass in (true) because we want to
see how many moles are up and we get the
| | 01:59 | count of that array.
| | 02:00 | Remember getMoles returns an array of
either moles that are up, or moles that
| | 02:04 | are down, depending on the value you pass in.
| | 02:06 | So, true means moles that are up and
false means moles that are down. We'll
| | 02:10 | define exactly how that works in just a
minute and we want to check this to see
| | 02:14 | if the count is less than (<) molesAtOnce.
| | 02:17 | And if so, we want to show a
mole, so inside of the if ()
| | 02:20 | statement this->showMole().
| | 02:22 | And on the next line timeElapsed=0. So
as this method continues to run over and
| | 02:29 | over again, timeElapsed will increase
and as it's greater than (>)or equal(=) to
| | 02:34 | timeBetweenMoles and if we can
create a mole, we run showMole, we reset
| | 02:38 | timeElapsed and so on;this method
continues to run over and over again.
| | 02:43 | Let's scroll on the showMole, we'll
define that, then we'll defined getMoles.
| | 02:47 | So in showMole, we are just
going to grab a random mole.
| | 02:50 | Now we want to make sure that this mole is down.
| | 02:53 | So, we'll create a variable called
Mole, let's type *mole and we'll set it
| | 02:58 | =typecasted (Mole *), this->getMoles
pass in (false); we want to get a mole
| | 03:04 | that's down, because we're
going to make a mole pop up.
| | 03:06 | Remember that's an array, and the advantage of
CCArray is that it has a method called
| | 03:10 | randomObject, so you can easily
grab a randomObject out of your arrays;
| | 03:15 | So a randomObject that will give us a
mole that's down. And then the next thing
| | 03:19 | we need to do is have it start.
| | 03:21 | So moles->start and then will define getMoles.
| | 03:25 | So, inside of getMoles create a
CCArray and will call this *ary,
| | 03:29 | set it=CCArray::create.
| | 03:32 | So, we'll create the Array and then
we're going to loop through all the moles,
| | 03:36 | and if a mole matches is up
then we will put them in the array.
| | 03:40 | So, for(int i=0, i is <1 moles->count()i++).
| | 03:45 | So we're going to grab a Mole, we'll
call it *mole that's going to be moles
| | 03:50 | object index i, and you will
need to typecast it to a (Mole *).
| | 03:54 | So, you just type that in, moles->
objectAtIndex pass in (i) and then we want to
| | 04:01 | see if() the mole is up.
| | 04:02 | So, if() (mole and then we run getIsUp
() == isUp), now this can apply whether
| | 04:09 | the moles up or down based on
what we pass into this method.
| | 04:12 | Then we are going to add it to the array.
| | 04:14 | So, ary aaObject and pass in the mole.
And then instead of returning NULL, we
| | 04:19 | will just return the array, and that's it.
| | 04:22 | You should now be able to save and test,
and see that in the Android Emulator,
| | 04:27 | when you click play, those moles
randomly pop up everywhere on the screen.
| | 04:32 | So now you can see our game is
progressing to be more and more like a real
| | 04:36 | game. All we need now is interactive element.
| | Collapse this transcript |
| Handling touches in the game| 00:00 | Now we add interactivity to our game
and CCTouchesBegan. Here is the plan, we're
| | 00:05 | going to grab the touch information,
including the location information, loop
| | 00:09 | through all of the moles and see if
they touch touched one of the moles.
| | 00:13 | If so, we're going to send a
message to the Mole that it was tapped and
| | 00:17 | handle it from there.
| | 00:18 | So, inside CCTouchesBegan in the game
class, reference to CCTouch, we'll call it
| | 00:23 | *touch, and we're going to set it =
typecasted (CCTouch *), that's going to
| | 00:28 | pTouches any object.
| | 00:31 | Now a pTouches is a CCSet, which is
similar to an array, it's a set of objects
| | 00:37 | and so there are multiple
touches inside of pTouches.
| | 00:40 | This method is also called
CCTouchesBegan implying that multiple touches
| | 00:44 | could happen at one time.
| | 00:46 | You can use this to handle multi-touch,
but on Android I've seen it work very
| | 00:51 | sporadically. It worked fine for me on
iOS where I like to just loop through the
| | 00:56 | CCSet, but on Android, multi
touches will only work once in a while.
| | 01:00 | So I chose not to use it in this case.
| | 01:04 | If you find a very effective way to
handle multi-touch on android with
| | 01:08 | Cocos2d-X, let me know on Twitter.
| | 01:10 | Let's go to the next line and your
CCpoint, this is going to be the location, and
| | 01:15 | we are going to set it =touch->
locationInView. And then we are going to set
| | 01:19 | location again, and this is going to be
| | 01:23 | CCDirector::sharedDirector()->
convertToGL and then just pass in a (location).
| | 01:30 | Now this is going to be very familiar,
since we already handled Touches in
| | 01:33 | the exact same way.
| | 01:35 | So now what we are going to do is loop
through all of the moles, and to see if
| | 01:40 | this location overlaps any of the
bounding boxes of the moles, and if so, we
| | 01:45 | will just tell that mole that it was tapped.
| | 01:47 | So, I create a for Loop, standard here,
(int i=0) we are going to loop through
| | 01:52 | the count of the moles.
| | 01:54 | So, as long as (i) <moles->counts i++
and then inside of the loop we're going to
| | 02:01 | reference a mole based on the index
of the mole inside of the Moles array.
| | 02:06 | So, we are going to have to typecast it,
because it returns CCObject for each
| | 02:11 | object in the array.
| | 02:12 | So, it's going to be moles->
objectAtIndex pass in (i )and so there' is our mole.
| | 02:19 | Now we want to see if the mole is up,
so we're going to see if the mole is not
| | 02:25 | up, and if it's not up, we are just
going to continue to the next mole.
| | 02:29 | So, mole->getIsUp, so I continue
instead of that if () statement. And now we are
| | 02:33 | going to create another if() statement.
| | 02:35 | So we know now that the mole IsUp and
we want to check to see if the touch is
| | 02:39 | inside of the mole's bounding box and
you may remember how we do that before.
| | 02:43 | So, we just do (CCRect::
CCRectContainsPoint and we passed in the rectangle, which
| | 02:49 | is going to be the bounding box of the (mole).
| | 02:51 | So, (mole->boundingBox) and the
next parameter is the location.
| | 02:54 | And then in here we just tell the
mole that it was tapped and then we don't
| | 02:58 | need to go through any other moles
since we already have one, so we'll just
| | 03:02 | break out of the loop.
| | 03:03 | And now I am interested to find what
happens on the mole side when it's tapped.
| | 03:07 | So save and jump over to Mole.cpp and
we will handle that there, scroll down in
| | 03:13 | the Mole class to what
is tapped, should be empty.
| | 03:16 | And in here what we going to do is
just stop all the molesActions(), and then
| | 03:21 | we'll run the animated
actions have the mole animate down.
| | 03:25 | So this run action we want to pass in
(Utils::getAnimationWithFrames), when we
| | 03:33 | pass in 21 and 31 that's the mole hit
animation so it's going to turn red.
| | 03:39 | And then finally, we are going to set
isUp = false, so the mole is no longer
| | 03:43 | counted as up, once it's been tapped.
| | 03:45 | So, let's save the file and
just test it out in the emulator.
| | 03:49 | So now hit play, and you'll see that
Moles pop up and then I can tap them and
| | 03:56 | they play a little
animation and go down, excellent!
| | 04:00 | So, as expected, when you tap on the Mole,
the Mole animation plays and the Mole
| | 04:04 | goes back down and has the
opportunity come back up again, and now our game
| | 04:08 | finally feels like a game.
| | Collapse this transcript |
| Displaying the player's score| 00:00 | Now that we can handle tapping the
moles, we will look at giving the player a
| | 00:04 | point each time the player taps on a mole.
| | 00:07 | So go into ccTouchesBegan and inside
of the CCRectContainsPoint if statement
| | 00:13 | right under mole->wasTapped let's
tell the game that the players scored.
| | 00:17 | We will do that by
communicating to the hudLayer.
| | 00:19 | Utils::hudLayer()->didScore.
| | 00:23 | Save the file and go over to HUD.h. Here are
the properties and methods for the HUD class.
| | 00:29 | Let's go into HUD.cpp and you
will see that it's pretty much blank.
| | 00:33 | In the init method, we will set score
to 0 and we will create a float called
| | 00:37 | padding and set it equal to 10, and
that we will define the score label.
| | 00:41 | scoreLabel = CCLabelTTF::create and we
will start by passing in the string 0,
| | 00:48 | it's what's going to be
inside of the text field.
| | 00:50 | Next parameter is going to be a
string, so CCString and we will run it's
| | 00:56 | createWithFormat method, and first
we will pass in %s and then .ttf.
| | 01:02 | And we are going to grab that
font after the Comma (,) by using our
| | 01:08 | constant value FONT_MAIN.
| | 01:11 | After that close parentheses, we will
run getCString and then a comma after that
| | 01:16 | and the last parameter is
the size of the text field.
| | 01:20 | So it's going to be 24*Utils::getArtScaleFactor.
| | 01:21 | Go to the next line; here we are going to
set the anchor point, that's the XY origin.
| | 01:32 | scoreLabel->setAnchorPoint and this is
based on a percentage, so if you want to
| | 01:39 | have it be in the center it's 0.5, 0.5.
| | 01:43 | So there is the X origin and the Y
origin that we pass in as the ccp.
| | 01:48 | What we wanted to do is stick at the
top left of the screen, so we are going to
| | 01:52 | use a top left XY origin.
| | 01:54 | So X origin of 0 which represents the
left edge of the object and a Y origin of
| | 02:00 | one, which represents the top edge.
| | 02:02 | Now we do this because we have
less math to calculate if we give it a
| | 02:07 | registration point that's
appropriate for its position.
| | 02:11 | Let's go down to the
next line and set the scale.
| | 02:14 | So scoreLabel->setScale and
then we pass in Utils::getScale.
| | 02:19 | On the next line we are
going to set its position.
| | 02:23 | So scoreLabel->setPosition and the
position is going to be ccp of course, and
| | 02:30 | the X position is going to be padding.
| | 02:32 | Remember we have that left edge of the
stage as a registration point, so it's
| | 02:36 | going to be 10 points from the left
edge of the screen and then for its Y
| | 02:40 | position, we are going to get
the height of the screen, so
| | 02:43 | Utils::s().height-padding.
| | 02:44 | So it will be 10 points
from the top of the screen.
| | 02:51 | Now we want to add it as a child of
the hud, so this->addChild, pass in
| | 02:56 | scoreLabel and then the Z position
which we will set at 1, and then scroll down
| | 03:03 | to didScore; remember this is going
to run once the mole was tapped as we
| | 03:06 | defined in the game class.
| | 03:08 | So we are just going to increment score by
1 and then set the text to the scoreLabel.
| | 03:13 | So scoreLabel->setString and then we
are going to pass in the string which is
| | 03:19 | going to be a formatted CCString.
| | 03:21 | So CCString::createWithFormat and that's
going to be just the number of the score.
| | 03:26 | So %d and then after the close quotes
of the string, score after a comma and
| | 03:34 | then we are going to run getCString and
that's it, just pass in the score of the
| | 03:38 | string, it's going to increment every
time we tap a mole, so hit Save and test
| | 03:42 | this out in the Emulator.
| | 03:43 | So now I will run the app in the
Emulator and when I hit Play you will see
| | 03:49 | the moles moving up and down as they
should and when I click on them, you
| | 03:53 | will see the score going up.
| | 03:54 | Now I will go back into the code, and
now we have a system to calculate the
| | 03:59 | player's progress as they play through the game.
| | Collapse this transcript |
| Handling misses| 00:00 | Let's handle what happens when the
player misses a mole and it goes down
| | 00:04 | before the player taps it.
| | 00:06 | We will start in Mole.cpp in the reset method.
| | 00:10 | Remember that we already set to see if
the person missed the mole, and if so we
| | 00:15 | run the missedMole method in the hudLayer.
| | 00:19 | So let's go to the HUD now and
missedMole doesn't have anything in it yet.
| | 00:23 | What we are going to do is create a
system that has three different lives, so
| | 00:29 | each time the player misses a mole they
lose a life. And once they miss all the
| | 00:33 | moles and they get game over.
| | 00:34 | We need to create the lives which are going to
be a carrot graphic inside of the init method.
| | 00:39 | Under where you create the padding variable,
set the value of carrots = CCArray::create.
| | 00:46 | Now on the next line
retain it, so carrots->retain.
| | 00:51 | Remember that in cocos2d objects
automatically get released from memory if they
| | 00:57 | are not used for an amount of time.
| | 00:58 | So for things like CCArray, you
need to call retain if you are going to
| | 01:02 | reference it throughout your code.
| | 01:04 | So we will do the release at the bottom
of the code in the onExit event handler.
| | 01:08 | So here we will run carrots->
release and then we will call this a super
| | 01:13 | method, so CCLayer::onExit.
| | 01:15 | Scroll up to the init method and
here we are going to use a for loop to
| | 01:20 | create the carrots.
| | 01:21 | So standard int i= 0 and we are going to
run this as long as there are carrots left.
| | 01:28 | So we are going to set our carrotsLeft
variable right above the for loop. I'm
| | 01:32 | going to set that equal to 3.
| | 01:34 | So we'll run a loop as long as carrots are left.
| | 01:37 | So as long as i < carrotsLeft and then i++.
We are going to create them at the
| | 01:42 | top right of the screen so
we'll create a CCSprite in the loop.
| | 01:46 | Call it c, set it equal to CCSprite
::createWithSpriteFrameName, pass in
| | 01:53 | the string life.png.
| | 01:55 | Go to the next line, we're going to
setAnchorPoint to the top right, so
| | 02:00 | that's going to be a ccp with one for the x
anchor point and one for the y anchor point.
| | 02:07 | And then we are going to set the scale,
so c->setScale, pass in Utils::getScale.
| | 02:13 | Next line, set the position.
| | 02:15 | We are going to use the loop to set
them and create them from the top right
| | 02:19 | corner, moving outward to the left.
| | 02:21 | So setPosition, it's going to be another ccp.
| | 02:23 | We will start with Utils::s().width-
padding-i * size of the carrot times a scale.
| | 02:34 | So in parentheses c->getContentSize().
width*c->getScale, and then after the x
| | 02:45 | value we will do the y value.
| | 02:46 | So a Comma(,) and then we will
type in Utils::s().height - padding.
| | 02:53 | So the little carrot graphics will start
at the top right, and just build out to
| | 02:57 | the left as they go.
| | 02:58 | Go to the next line and we will run
carrots, that's our CCArray, addObject(),
| | 03:05 | pass in c. We are going to store them in
an array, then we are going to add them
| | 03:10 | to the hudLayer using addChild.
| | 03:11 | So this->addChild on the next
line, pass in c and a z value of 1.
| | 03:19 | Scroll down and now we are
going to the missedMole method.
| | 03:22 | The first thing we will do
is decrement carrotsLeft--;
| | 03:25 | then on next line we want to see if we
still have carrots in the carrots array.
| | 03:33 | So if statement, that's going to be carrots
->count()>0, then we will remove the child.
| | 03:40 | So this->removeChild and in the parentheses
we are going to pass in a typecasted CCNode.
| | 03:48 | It's basically a generic cocos2d visual object.
| | 03:56 | It's going to be carrots->objectAtIndex,
and it's going to be the last object.
| | 04:00 | So it's going to be carrots->count()-1.
| | 04:02 | So this will destroy the carrots
from the left going to the right.
| | 04:06 | After the closed parentheses for
objectAtIndex, we are going to pass in true,
| | 04:10 | and second parameter is clean up.
| | 04:13 | And if that carrot did have any
children, it will remove them as well.
| | 04:17 | Then carrots on the next line,
removeLastObject, we want to take it out of the
| | 04:23 | objects that are displayed as children
in the hudLayer and then we want to take
| | 04:27 | it out of the carrots array.
| | 04:29 | And finally, we are going to
check to see if the game is over.
| | 04:33 | So in if statement below that
statement, we are going to check to see if
| | 04:37 | carrotsLeft is <= 0, and we are not
going to handle the game over now, but
| | 04:43 | that's going to be the game over area of code.
| | 04:45 | If you like to mark it with a comment,
feel free to do so and then an else
| | 04:50 | statement below the if statement. So there are
still carrots left, the game is not yet over.
| | 04:54 | We are going to get all the moles that
are up, so CCArray, call this moles, set
| | 04:59 | it equal to Utils::gameLayer()->
getMoles, pass in true, so all the moles that
| | 05:05 | are up, and we are going to
loop through these moles.
| | 05:08 | So again, standard loop here. i<moles->count();
| | 05:12 | i++ and we will reference a mole
called m, we will set it to typecasted Mole.
| | 05:19 | It's going to be moles->
objectAtIndex, let's pass in i and we will tell
| | 05:26 | that mole to stopEarly.
| | 05:28 | Save the file and go back to the Mole
class and we will find stopEarly and we
| | 05:33 | will define what happens in this method.
| | 05:35 | So all we will do here, we will set
didMiss to false, set isUp to false,
| | 05:41 | stopAllActions and then we
will call stop, so this->stop();.
| | 05:45 | So that's it, so we will Save
and test this in a simulator.
| | 05:50 | What we should get is the carrots laid
out at the top right of the screen, when
| | 05:53 | you miss a mole a carrot disappears
and all the moles in the screen go down.
| | 05:59 | So let's save and test.
| | 06:00 | So I will click Play and I will look
for those carrots at top right and I won't
| | 06:05 | tap the mole but you will see all of
them go down and the carrot disappears.
| | 06:09 | And finally, last carrot is gone.
| | 06:12 | And of course, nothing happens after
that because we haven't defined exactly
| | 06:14 | what happens when you get a game
over, but it is working properly.
| | 06:18 | So we have successfully created what
happens when you miss a mole and now our
| | 06:22 | game is starting to get that stressful
element that happens when you feel like
| | 06:26 | you are going to lose.
| | Collapse this transcript |
| Controlling the number of moles on the screen| 00:00 | Our goal now is make the game get
more difficult as it progresses.
| | 00:04 | And to do that we want to increase the
number of moles allowed on the screen at once.
| | 00:09 | We will start in the Game::tick method.
| | 00:12 | At the very bottom, we will check to
see if increasedElapsed is greater than or
| | 00:17 | equal to increaseMolesAtTime, and here
we will control the number of moles that
| | 00:22 | can be on the screen at once and the
amount of time between the moles, so the
| | 00:26 | game will get progressively more difficult.
| | 00:28 | So the first thing we will do is
create an integer maxMolesAtOnce and set
| | 00:33 | that equal to 18 and then we will check to
see if molesAtOnce is less than maxMolesAtOnce.
| | 00:41 | If so we will increase molesAtOnce.
| | 00:42 | Then we will create a float called
minMoleTime, this is going to be minimum time
| | 00:48 | between moles. Set that equal to .1f,
so a tenth of a second is the minimum
| | 00:53 | time between moles.
| | 00:55 | On the next line, we will
subtract from time between moles.
| | 00:59 | timeBetweenMoles -=, in parentheses
will do a condensed if statement on this
| | 01:04 | line, so timeBetweenMoles > minMoleTime,
and if that's the case we are going to
| | 01:11 | subtract .05 from timeBetweenMoles,
if not we will subtract nothing.
| | 01:17 | Go to the next line, we are going to add
on to increaseMolesAtTime by ten seconds.
| | 01:23 | So += 10.0f.
| | 01:24 | So it will gradually get harder and
each time there are more moles on the
| | 01:29 | screen, it will take ten more
seconds to add an additional mole.
| | 01:32 | Outside of that inner if statement, we
are going to set increaseElapsed = 0.
| | 01:37 | Now we will save and test this in the
emulator, and what you should see is that
| | 01:43 | overtime the game becomes
more and more difficult.
| | 01:47 | So there are more and more
moles on the screen at once.
| | 01:49 | So now I will click Play and I will
play the game for over 10 seconds and after
| | 01:58 | that time we should start seeing
four moles on the screen at once.
| | 02:01 | There are our four moles.
| | 02:08 | So as you play longer and longer, the
game should get more and more difficult
| | 02:12 | and now it feels more challenging.
| | 02:13 | So it's more game like.
| | 02:16 | I just remember that if the game is
too easy or too hard for you then you can
| | 02:21 | adjust that simply by
controlling the values of these variables.
| | Collapse this transcript |
| Adding sound| 00:00 | Sound effects and music will
give more life to your game.
| | 00:04 | To do that, we are going
to use simple audio engine.
| | 00:07 | If you go to the MainMenu class, you
will see that I already have a few lines of
| | 00:11 | code where I used simple audio engine.
| | 00:13 | You can access the singleton instance
through sharedEngine and you can run
| | 00:16 | simple methods like
stopBackgroundMusic, preloadBackgroundMusic,
| | 00:18 | playBackgroundMusic,
preloadEffect and playEffect.
| | 00:24 | I am going to copy this preloadEffect line
of code and just paste it on the next line.
| | 00:28 | I am also going to preload moles_miss.wav.
| | 00:33 | Save this file and go over to Game.cpp.
| | 00:36 | In initializeGame(), I am
going to play the background music.
| | 00:40 | So it's SimpleAudioEngine and make
sure that you include this class if you
| | 00:44 | haven't already, sharedEngine()->
playBackgroundMusic and the BackgroundMusic is
| | 00:49 | going to be moles_bg.mp3.
| | 00:53 | I use mp3 files for background music
to conserve file size and WAV files for
| | 00:59 | effects to preserve quality.
| | 01:02 | And that's because the effects are
always very, very short, so an mp3 doesn't
| | 01:07 | save a ton of space in a half second.
| | 01:09 | Let's scroll down and we are going to
find the TouchesBegan method and where the
| | 01:15 | mole->wasTapped and we didScore, I
am going to play the Splat effect.
| | 01:20 | So SimpleAudioEngine:sharedEngine()->
playEffect and the effect is going to be SOUND_SPLAT.
| | 01:29 | Save the file and then we'll go over to
the HUD.cpp and when we miss a mole,
| | 01:35 | which we handle in missedMole, near the
top I am going to play the miss sound.
| | 01:40 | So I will paste that code that I
copied earlier to preload the Effect.
| | 01:44 | I will change it to playEffect.
| | 01:46 | Change SOUND_SPLAT to the string,
moles_miss.wav and that's it.
| | 01:52 | So now we should build the save and
run the app in the emulator and once it
| | 01:56 | launches we will hear that background
music play as we play the game, the miss
| | 02:01 | sound, when you miss a mole, and
the hit sound when you tap a mole.
| | 02:05 | So we hit the Play button
and we should hear the sound.
| | 02:07 | (music playing)
| | 02:08 | So I will close the emulator and you
could hear the background music playing as
| | 02:18 | I play the game and when I tapped a mole,
it played the splat sound, and when I
| | 02:23 | missed a mole it played the missed sound.
| | 02:25 | So you can use sound effects using
Simple Audio Engine and the simple methods
| | 02:28 | like play effect and preload effect.
| | Collapse this transcript |
| Enabling a pause feature| 00:00 | Now we'll look at how to pause the
game, stop all the animation during the
| | 00:04 | gameplay and have an option to
resume or go to the main menu.
| | 00:08 | So let's jump over to the Pause class
and we'll start in the header file to
| | 00:12 | just look at the properties and methods
that exist for this class, and then go
| | 00:17 | over to the Pause.cpp.
| | 00:19 | In the init method we will give a
value to pauseButton and we will set that
| | 00:23 | equal to CCMenuItemSprite::create and
then we need to pass in a sprite for the
| | 00:29 | default sprite and then the secondary sprite.
| | 00:33 | The default sprite is going to be a
CCSprite that we will create right
| | 00:36 | here, this is going to be
createWithSpriteFrameName and the FrameName is pause_button.png.
| | 00:45 | Second parameter for CCMenuItemSprite::
create is the selected sprite which we'll
| | 00:51 | pass in NULL, then the target which is
this, and the selector we want to run. And
| | 00:57 | remember you have to pass in a special
format for that, that's' menu_selector
| | 01:02 | and in the parentheses we pass in
the selector which is Pause::pause.
| | 01:07 | Make sure you don't run the
method here that you just reference it.
| | 01:11 | Go to the next line and we will create
a CCMenu and we will call this menu, set
| | 01:16 | it equal to CCMenu::create and we
will pass in pauseButton and then NULL,
| | 01:23 | terminate the list of objects.
| | 01:25 | Then we are going to set the position of
the menu, so menu->setPosition and here
| | 01:29 | I am not going to adjust the Anchor
point, but I am going to put the pause
| | 01:33 | button in the bottom right of the screen.
| | 01:35 | The reason I don't want to adjust the
anchor point is because we are controlling
| | 01:39 | the position of the menu and the
pause button, and they have relative
| | 01:42 | coordinates to each other.
| | 01:43 | I have had a lot of problems with
laying out menus and their individual buttons
| | 01:49 | by using anchor points, so I always
leave the default anchor points in the case
| | 01:53 | of buttons and menu items.
| | 01:54 | So we'll pass in the ccp here and
then this is going to be Utils::s().width
| | 02:01 | - pauseButton->getContentSize().width/2,
and the Y position is just going to
| | 02:10 | be half the pauseButton's height, which we
will align it with the bottom of the screen.
| | 02:14 | So pauseButton->getContentSize().height/2.
| | 02:15 | Then we are going to add it as a child
of the pause layer, so this->addChild and
| | 02:22 | then we will pass in menu and 1.
| | 02:25 | So the Z position is going to be 1 and now we
are going to give the value to the pop up object.
| | 02:31 | So popup = Popup::popupWithTitle.
| | 02:36 | We'll pass in a string for the title
which is going to be PAUSED, and on the
| | 02:41 | next line we will run addButtonWithText.
| | 02:43 | so popup->addButtonWithText(), now we
need to pass in the text for the button
| | 02:49 | which is going to be RESUME.
| | 02:51 | Target is this, selector is menu_
selector and then we pass in the method we want
| | 02:58 | to run, that's going to be Pause::resume.
| | 03:00 | Then on the next line we will do the
same thing, so I am going to copy and paste
| | 03:05 | the previous line of code and change
the text to MAIN to go the Main Menu, and
| | 03:10 | the method that I want
to run is Pause::mainMenu.
| | 03:13 | Now you may wonder why I don't just
run MainMenu, mainMenu since that already
| | 03:19 | exists to take us to the Main menu.
| | 03:21 | That's because we are
running an instance method here.
| | 03:24 | We pass in this and that grabs the
target and it runs a selector on the
| | 03:29 | target, which is mainMenu.
| | 03:30 | I will show you how I
chose to work that below here.
| | 03:33 | On the next line of code,
add the popup as a child.
| | 03:36 | So this->addChild, pass in the popup, z of 1.
| | 03:41 | Remember you can share z values, it just
puts the objects you add later in front
| | 03:47 | of the earlier added objects.
| | 03:49 | So in Pause::pause, I am going to run
this->togglePause, pass in true and then
| | 03:57 | we will just copy and paste
this into resume, pass in false.
| | 04:01 | In mainMenu we will run MainMenu::mainMenu.
| | 04:03 | Then we'll return to the MainMenu and
in togglePause we will show the popup.
| | 04:09 | It's popup->show, remember we need to
pass in whether or not to show or hide the
| | 04:15 | pop-up, so we just pass in that pause
parameter. And if we want the game to
| | 04:18 | pause, then we will show the
popup, if not we won't show it.
| | 04:22 | So the next line, Utils::gameLayer(),
then we are going to setTouchEnabled to
| | 04:29 | the opposite of paused, so !paused.
| | 04:33 | So that way if we paused the game, then
Touch is disabled in the gameLayer and
| | 04:37 | if we unpause the game
then touch is enabled again.
| | 04:40 | Go to the next line, and we are
going to hide the pause button based on
| | 04:44 | whether the game is paused.
| | 04:46 | Pause Button->setVisible
and we will pass in !paused.
| | 04:50 | So again if the game is paused, we
want to hide the pause button, and if the
| | 04:55 | game is resuming we want
to show the pause button.
| | 04:57 | So let's Save and test this out in the emulator.
| | 05:00 | Okay, I will click the Play button and
then I should be able to pause the game
| | 05:04 | when I click the Pause button.
| | 05:06 | (music playing)
| | 05:07 | So the music stops as specified in the
popup class, I can chose to resume the
| | 05:12 | game or go to the Main Menu.
| | 05:13 | (music playing)
| | 05:14 | I resume and the animation continues.
| | 05:17 | I can pause again that I can go
to the main menu and there we are.
| | 05:21 | So now if you ever want to pause your
game, make sure to setTouchEnabled to
| | 05:24 | false in the gameLayer and then you
can use this popup class or create one of
| | 05:28 | your own and use the similar method to
stop audio and to pause the scheduler
| | 05:35 | and actions.
| | Collapse this transcript |
| Displaying the game-over screen| 00:00 | Now we'll create a way to lose
the game by getting a game over.
| | 00:04 | Go over to the HUD class, into the
missedMole method, and remember that code
| | 00:08 | that we said would be the game
over code, that's if carrotsLeft <= 0.
| | 00:14 | So that's where we'll start and here
what we want to do is reference a GameOver
| | 00:18 | object, that's the GameOver layer and
we can get it to Utils::layerWithTag, and
| | 00:24 | we will pass in TAG_GAMEOVER.
| | 00:27 | Now of course we'll have to typecast this
because this is just going to return CCLayer.
| | 00:31 | So we'll typecast it to a GameOver
object and then go to the next level and
| | 00:36 | then run go->gameover.
| | 00:39 | I'll Save this file and go over to GameOver.h
just to take a look at the existing code.
| | 00:45 | So we have a Popup property and this
actually looks pretty similar to the Pause class.
| | 00:50 | So I'm going to open up Pause.cpp and
I'm just going to copy the four lines of
| | 00:56 | code where we create the popup.
| | 00:58 | I'll close that file and go back over to
GameOver.cpp, double tapping the tab to
| | 01:04 | expand the area and inside the
init method I'll paste that code.
| | 01:10 | Change the title to GAME OVER, change
the first button to REPLAY and the method
| | 01:17 | to GameOver::replay, and will leave
MAIN same for the text, and then change the
| | 01:24 | method to GameOver::mainMenu.
| | 01:27 | So in replay, we'll change the scene by using
| | 01:30 | CCDirector::sharedDirector()->
replaceScene and then we need to pass in a new
| | 01:36 | scene which we can grab from Game::scene method.
| | 01:40 | So that's just going to create a new
instance of the game and change the scene
| | 01:44 | so we can start the game over again
simply by re-creating the game scene. And
| | 01:49 | that's what we're doing here.
| | 01:50 | So the mainMenu method is just
going to be like the pause one, so just
| | 01:54 | MainMenu::mainMenu and then game over.
| | 01:58 | All we're going to do is run popup->show.
| | 02:01 | We will pass in true to show the screen,
and that's really all there is to it.
| | 02:06 | So now we should be able to save and
test the game, and when we get a game over
| | 02:10 | or after all the carrots are gone, the
popup should show up and should ask us if
| | 02:15 | we want to the play the game
again or go to the main menu.
| | 02:18 | So I'll click to play the game and
purposely get a game over to watch the screen popup.
| | 02:23 | (music playing)
| | 02:26 | And there is the Game Over screen.
| | 02:33 | Now remember that this is the emulator
and so when you see the moles animations
| | 02:38 | not finishing, that's an emulator bug.
| | 02:41 | If you test it on device
you should not see that.
| | 02:44 | So I can click Replay and I can play the
game again and I'll lose again and if I
| | 02:49 | click Main I can go to the Main menu.
| | 02:51 | (music playing)
| | 02:59 | Now I'll click Main and return
to the Main Menu and it's working.
| | 03:03 | So again, if you want to show that
popup screen, you can use the Popup class, and
| | 03:07 | you can always change the scene using
the director's replace scene method.
| | Collapse this transcript |
| Saving the player's high score| 00:00 | In your games you can save the player's
high score to increase the gameplay value.
| | 00:05 | So we'll start doing that in Constants.h by
defining a new key value called HIGH_SCORE.
| | 00:13 | The value I'll give to it
is just the string highscore.
| | 00:16 | Save this and go into HUD.
cpp into the missedMole method.
| | 00:20 | In missedMole find the area that
checks to see if carrotsLeft <= 0.
| | 00:25 | Remember, this means that there's a GameOver.
| | 00:26 | When the game is over we're going to
see if the player's score is greater than
| | 00:31 | the saved high score.
| | 00:33 | You can access saved values using CCUserDefault.
| | 00:37 | These values can be integers,
strings, Boolean etc.
| | 00:42 | You can look it up in the Cocos2d
documentation if you like to know more
| | 00:46 | information about the specifics.
| | 00:47 | So we can access it by the Singleton
CCUserDefault::sharedUserDefault().
| | 00:51 | Then we can run the method
getIntegerForKey, and the key is HIGH_SCORE.
| | 00:59 | And now if the score is greater than
the saved high score then we want to set
| | 01:03 | the saved value to the new value.
| | 01:06 | So I'll paste that inside of the if
statement and change getIntegerForKey in
| | 01:11 | this pasted code to setIntegerForKey.
| | 01:14 | After HIGH_SCORE send in the second
parameter score, so we'll save that integer
| | 01:20 | for the HIGH_SCORE key.
| | 01:21 | Now we'll scroll up and copy the code in the
init method that sets the value of scoreLabel.
| | 01:28 | Save HUD, go to the MainMenu class
and right under where we create the
| | 01:33 | background object I'm going to
paste the code I just copied.
| | 01:36 | Here we just make a few modifications
and then the high score label will show
| | 01:42 | when we play the game.
| | 01:43 | So we don't already have a variable
called score label, so I'll just need to
| | 01:47 | make sure to define this.
| | 01:48 | So right before we set the scoreLabel=CCLabelTTF,
just make sure you define that as a CCLabel.
| | 01:55 | So I have CCLabelTTF *scoreLabel and
then instead of zero for the string I
| | 02:01 | am going to change that to CCString::
createWithFormat, and I want a string that says HIGH:
| | 02:06 | and then the high score. So HIGH:
| | 02:09 | %d for digit, and then after
the string I'm going to pass in
| | 02:15 | CCUserDefault::sharedUserDefault->
getIntegerForKey and then pass in HIGH_SCORE.
| | 02:25 | And then outside of the closed
parentheses for createWithFormat, make sure
| | 02:29 | you call getCString.
| | 02:30 | Now the other values that create using
the Toonish font from that constant value
| | 02:37 | and the size, those are the still good.
| | 02:39 | So we'll just go down to the next
lines and we don't have padding defined, so
| | 02:44 | I'll just change those two
padding values to 10 each.
| | 02:48 | And then I'm going to change the Z
position instead of 1 to 10, and that's it.
| | 02:52 | I can Save and test and when I check
out this app in the emulator, you should
| | 02:57 | see that it says High:
| | 02:58 | 0 in the top left of the Main menu,
and when you play the game and lose after
| | 03:03 | you've scored a few points, when you
return to the Main menu you should see
| | 03:07 | that your new high scores reflected there
and that saves even after you exit the game.
| | 03:11 | So now if you save and test the app you
can see that there it says High:0 at the
| | 03:16 | top left and you play the game
and score a few points and lose,
| | 03:19 | (music playing)
| | 03:22 | so I will just score a point or two
and then die, and then when I lose I can
| | 03:29 | go back to the Main Menu and my high score,
which is currently 2, you'll see up there.
| | 03:35 | So if I beat that and say I get three
the next time I play it, then it should
| | 03:39 | say High of three and so on.
| | 03:41 | So remember, if you need to save any
kind of data, what you're going to use is
| | 03:46 | the CCUserDefault class.
| | 03:49 | So you can do things like set and get
integers, Boolean and strings, and again,
| | 03:55 | you can find more information about
that in the Cocos2d documentation.
| | Collapse this transcript |
|
|
5. Placing Ads in Your GamePreparing your game to support Google ads| 00:00 | Ads are an excellent and easy way to
make some revenue for your free apps.
| | 00:05 | Of course you can even put ads in a paid app.
| | 00:10 | To set up Google ads, go to
developers.google.com/mobile-ads-sdk.
| | 00:15 | Here you'll see the basic steps to
implementing Google ads in your Android game.
| | 00:21 | If you scroll down to How do I start?
| | 00:23 | You will see that you first have
to sign up as an AdMob publisher.
| | 00:27 | So you can click that link if you're
not already an AdMob publisher, sign up,
| | 00:31 | and then you'll have to create an app,
and we'll look at that in just a minute.
| | 00:36 | And the next step is to download the SDK.
| | 00:39 | So we're actually going to scroll up
and then click SDK Downloads on left side
| | 00:42 | of the page, and you'll see the
GoogleAdMobAdsSdkAndroid.zip file.
| | 00:46 | So if you download that, you are going
to find a JAR file in there, and that's
| | 00:51 | the file that you'll need
to implement the Google ads.
| | 00:54 | If you keep clicking the links here,
you'll see more information about how to
| | 00:58 | implement the ads into your apps.
| | 01:01 | If you click the AdMob link and then
Banner Ads 1, this is the type of ad
| | 01:05 | we're going to use.
| | 01:06 | And it explains how to
implement the ad in either Java or XML.
| | 01:12 | We're going to do the XML version
here, and here's some sample code that
| | 01:15 | explains how to do it.
| | 01:17 | I am going to go over to AdMob now
to show you what that looks like.
| | 01:21 | Once you've created an app in AdMob, you
can go to the app, in your Sites & Apps
| | 01:26 | section, and find your Publisher ID.
| | 01:29 | That's the number that you're going to
need in AdMob when you create your ads.
| | 01:33 | So make sure to copy
that and we'll use it later.
| | 01:37 | Now, let's go over to Eclipse.
| | 01:39 | In Eclipse, to import the GoogleAds.
jar, I change the file name, so that it
| | 01:44 | doesn't have the version on it
anymore, and I drag that onto the libs
| | 01:49 | folder, and choose Copy.
| | 01:52 | Note that if this method is giving you
any kind of trouble, you can go to your
| | 01:55 | Project>Properties>Java Build Path
and add this file as an external JAR.
| | 02:00 | I also had to use the Android API level 13.
| | 02:06 | So, to do that, I went to my apps
Properties, and under Java Build Path, I went
| | 02:12 | to Libraries and I removed the
previous Android version that I had and then I
| | 02:18 | hit Add External JARs.
| | 02:21 | And then I found the JAR file for
Android level 13 that's inside of your Android
| | 02:26 | SDKs folder in the platforms subfolder.
| | 02:30 | So remove that, and replace that with
Android API level 13 or you can always go
| | 02:35 | into your Android properties through Project>Properties
and change the API level there.
| | 02:41 | And then you'll also have to go
into all of these ant.properties,
| | 02:45 | local.properties, and project.properties
and just add this line of code at the bottom;
| | 02:50 | target=android-13 and I put
that in each of those files.
| | 02:55 | And there it is in project.properties.
| | 02:57 | So once you've set your target to be
Android 13, and you've implemented the
| | 03:02 | Android API level 13 and you've linked
the GoogleAdMobAddsSdk.jar file, you're
| | 03:09 | ready to start writing the code
to add Google ads into your apps.
| | Collapse this transcript |
| Implementing Google ads in your game| 00:00 | The code for implementing Google ads is
fairly simple, but there is a lot of it.
| | 00:05 | So I chose to have it
prewritten for this exercise.
| | 00:08 | You'll need to start by creating a file
called main.xml inside of the Resources
| | 00:13 | folder, in the Layout
subfolder. So there it is!
| | 00:16 | I'm going to expand that file
now so it fills the whole view.
| | 00:20 | Here, most of this code is
copied and pasted from Google.
| | 00:23 | If you look up their XML example,
you'll see that the code is already
| | 00:27 | written for you here.
| | 00:28 | Of course, you'll need to replace MY_AD
_UNIT_ID with your actual publisher ID
| | 00:34 | that we looked at in the last movie.
| | 00:36 | And the big difference here is that we're
wrapping our OpenGL view in a RelativeLayout.
| | 00:43 | This GL view now is going to be set
through XML as well, so we'll need to make a
| | 00:48 | change to moleit.java.
| | 00:49 | So I have it declared here, then I have my
ad view, and then I've replaced my adUnitId.
| | 00:54 | For testDevices, I just have TEST_
EMULATOR, so it should work in the Emulator,
| | 00:58 | and then I'll go to the manifest.
| | 01:01 | Now, we've changed the manifest a little bit.
| | 01:03 | One thing I've added that you could copy
and paste from Google if you don't have
| | 01:06 | access to the Exercise Files is this
activity under the main moleit activity,
| | 01:12 | that's the com.google.ads.AdActivity.
| | 01:15 | So again, if you look in the Google
tutorial, you'll see this block of code and
| | 01:19 | just paste it right in.
| | 01:21 | Also, you'll need to add some
permissions including the ACCESS_NETWORK_STATE and
| | 01:27 | that INTERNET permission.
| | 01:29 | You can do that by going to the
Permissions Tab and then hitting Add, and then
| | 01:32 | just hit Uses Permission, and
just select it in the dropdown menu.
| | 01:37 | So again, that's ACCESS_
NETWORK_STATE and INTERNET.
| | 01:41 | So just remove that permission I
just added, save the file and go back to
| | 01:45 | moleitx.java, and now
here I've declared an adView.
| | 01:48 | And of course you'll need to import
the adView class, and then I've commented
| | 01:53 | out this huge block here to change
the GL code to use the XML layout.
| | 02:00 | So, we set the ContentView to R.
layout.main, that's that main XML file.
| | 02:04 | And then I set the value of the GL
view based on the XML file, and I'm still
| | 02:10 | setting these two values here, then
I reference the adView, set it to be
| | 02:15 | Visible, and tell it to
load an ad. And that's it!
| | 02:18 | Now, when you test it in the
Emulator, here's what you should get.
| | 02:22 | Now, see how I have this ad at the
bottom, and note that I just struck the Play
| | 02:26 | button down a little bit
to accommodate the ad space.
| | 02:29 | Now, I had a problem that I spent hours looking
up, and I don't want you to do the same thing.
| | 02:35 | In my logcat, I could see that ads were
loading in, but I did not see them on the screen.
| | 02:41 | And I looked it up online and a lot of
people said it takes about two minutes
| | 02:45 | for the ads to load.
| | 02:46 | For me, it actually took about two hours.
| | 02:48 | So, if you don't see an ad on here,
try testing it on your device.
| | 02:53 | And for me, on the device it came up
right away, but in the emulator, it took
| | 02:57 | hours for an ad to appear.
| | 02:59 | So, I wouldn't count on that.
| | 03:01 | I would definitely be
testing on a device for this.
| | 03:04 | If you see this test ad, you can click it.
| | 03:06 | But remember, don't click any ads on
your device if they are real ads; that is,
| | 03:10 | ads for some kind of product or
something, not just from Google, because
| | 03:14 | Google's policies could possibly ban you
from ever using Google ads again if you
| | 03:19 | click on your own ad, so
definitely don't do that.
| | 03:22 | So just remember when you're
configuring your ad view that you'll need to
| | 03:26 | update that main XML file and add the
adView, update your manifest with the
| | 03:32 | appropriate permissions, and the ad
view and then update your main activity
| | 03:36 | file to add the adView as well.
| | Collapse this transcript |
|
|
6. Adding In-App PurchasesHandling skins in your game code| 00:00 | Now we are going to look at how to
add in-app purchases to your games.
| | 00:04 | We'll look at how to do that through both
Amazon Appstore and through Google Play.
| | 00:08 | The purchase I chose to implement
is an artwork change called the skin.
| | 00:13 | To see what that looks like, I'm
going to click SKINS at the title screen
| | 00:16 | and I'll click ALIENS.
| | 00:19 | This is going to change all of the
graphics for the game, that when I play it
| | 00:23 | I'll hear the music, see the artwork
and animations and all the menu buttons
| | 00:29 | that are associated with
that different skin graphic.
| | 00:32 | I'll go back to the Main Menu now.
| | 00:33 | Now I understand that not all of
you're going to choose to use a skin as your
| | 00:38 | in-app purchase, so I pre-wrote all of
this code and I am going to show you how
| | 00:43 | I did it in the event that you want
to implement that in your own game.
| | 00:47 | Let's look at the code I've
written and we'll start and Utils.ccp.
| | 00:50 | Here I have a static character
constant called currentSkin and I set that
| | 00:55 | equal to SKIN_MOLES.
| | 00:57 | And that's just a constant value that I
added to Constants.h. You can see that
| | 01:02 | if I open that file up in Classes.
| | 01:05 | So I have that in-app purchase code
for the Jetpack handyman skin, I have
| | 01:09 | SKIN_MOLES and SKIN_JETPACK;
| | 01:12 | I've also added TAG_SKINS to Constants.h.
So I'll go back to Utils and so we're
| | 01:19 | initializing the current skin.
| | 01:20 | At the bottom of added getters and
setters for that value, very simple and that
| | 01:25 | I created another one called getFullName.
| | 01:27 | What this does is it creates a
formatted string that puts the currentSkin in
| | 01:32 | front of the suffix that's passed in.
| | 01:35 | So we can use this for all different file types.
| | 01:37 | Let's go over to Skins.cpp.
| | 01:40 | This is a lot like the pause menu or
the game over menu, it's really simple.
| | 01:44 | I created a button that says
MOLES and a buttons that says ALIENS.
| | 01:48 | In the show method, instead of calling
popup show I just call popup->setVisible,
| | 01:53 | just because the skin screen is always
going to be run from the Main Menu so I
| | 01:57 | just need to show the popup; I don't
need to pause the schedule or anything.
| | 02:01 | And then I have set MoleSkin which sets the
skin and then mainMenu reloads the Main Menu.
| | 02:07 | Now that's significant, we'll
look at that in just a second.
| | 02:09 | setAlienSkin is the same thing, but
what I've commented out here that I will
| | 02:14 | uncomment after this movie, is I'm
checking to see if the user default is set
| | 02:20 | for that in-app purchase.
| | 02:21 | So, what I do when I buy the item after
its confirmed purchase, then I set that
| | 02:27 | bool for that in-app purchased value to true.
| | 02:30 | So that way I know that it's been
purchased and if that's not true, then I run
| | 02:34 | the code to buy the item.
| | 02:36 | Now again buyItem and everything else
related to the in-app purchase we're going
| | 02:40 | to look at in detail later on.
| | 02:42 | Let's go to MainMenu and see how
we handle changing the skin there.
| | 02:46 | I added a significant line of
code here, where I purge the
| | 02:50 | SharedSpriteFrameCache.
| | 02:53 | That means we get rid of all the sprite
frames held in the cache and then I run
| | 02:57 | sprite frames with file.
| | 02:59 | You'll notice for the sounds
that I'm preloading that I'm using
| | 03:03 | the Utils::getFullName.
| | 03:04 | So that's going to put the skin
name in front of _bg.mp3 etcetera.
| | 03:11 | So I've used that for all of my file
names that contain skin relative names.
| | 03:16 | You'll see that I've added the skin in
the scene method, so I created the skins
| | 03:20 | object and then added it as a child of
the main scene, just like what we did
| | 03:25 | with our game. And then at the bottom I
have a method that runs called showSkins,
| | 03:30 | that runs when you hit the SKINS button
from the Main Menu and it just calls the
| | 03:34 | show method of skins.
| | 03:35 | Let's go over to Game.ccp.
| | 03:37 | And here all I did differently was I
found anywhere that referenced anything
| | 03:42 | that had the word moles in it and then
I ran Utils get file name, change the
| | 03:47 | value based on the skin.
| | 03:49 | Now in case it's not obvious, you're
actually going to have to have a set of
| | 03:54 | artwork in audio files with different
names that match your skin if you're going
| | 03:58 | to use the same technique.
| | 03:59 | So if you don't have access to the
Exercise Files, you'll need to create
| | 04:03 | Jetpack_bg.mp3, etcetera.
| | 04:07 | So I created another sprite sheet with
all different sprites in there, but I
| | 04:12 | named the sprites the same so that they
would apply to both, and I just named the
| | 04:16 | file for the sprite sheets differently.
| | 04:18 | So you'll see that all across my cover
I'm running Utils::getFullName I did the
| | 04:23 | same thing in the HUD, so when I
run the miss sound I'm playing the
| | 04:27 | Utils::getFullName miss and that's about it.
| | 04:30 | So again, if you want to add a
custom skin, create some way that you can
| | 04:35 | efficiently swap out parts of a file name to
include different artwork or sound effects.
| | 04:41 | And then just make sure for the
artwork that you're purging the shared sprite
| | 04:45 | frame cash before you load the new sprites.
| | 04:48 | And then you can reload the Main Menu
scene and those new sprite frames will be
| | 04:53 | loaded in and applied.
| | Collapse this transcript |
| Setting up in-app purchases (IAP) for an Amazon Appstore app| 00:00 | To create an in-app purchase for
Amazon App Store app you'll of course first
| | 00:05 | need at Amazon App Store account.
| | 00:08 | You can get that by going
to developer.amazon.com.
| | 00:12 | Then you'll need to create an app using
that add new app button and in your app
| | 00:16 | you'll need to create an in-app
purchase to the In-App Items area.
| | 00:20 | Here you'll see I have one called
Jetpack Handyman Skin. The identifier that you
| | 00:24 | are going to be using in your code to
reference the purchase is this one here so
| | 00:29 | now is a good time to copy that and
for the type I chose Entitlement that's a
| | 00:34 | one time purchase that you unlock something.
| | 00:37 | Once you setup your in-app purchase,
you can get the SDK to the SDK link hit
| | 00:42 | Download SDK and here you'll find a
getting started with in-app purchasing
| | 00:47 | API which you should definitely look at if
you're serious about doing in-app purchases.
| | 00:51 | You can find some extra information there.
| | 00:54 | Let's go over to the desktop here.
| | 00:56 | In the SDK file that you download,
you'll see a folder called In-App-Purchasing
| | 01:00 | and folder in their called
lib and there is a jar file.
| | 01:04 | You can just drag that into your libs
folder in your Eclipse project to add
| | 01:08 | it to your project.
| | 01:09 | Remember it choose copies
so it copies in your project.
| | 01:12 | You are also going to need
some files in the tools folder.
| | 01:17 | This Jason files needs to be edited to
reflect your specific In-App Purchase.
| | 01:21 | I'll open that in a text editor.
| | 01:23 | So here is a description of how to
use it of course I'll need to uncommon
| | 01:27 | everything, and when you use this you
put a whole list of them like I have here,
| | 01:32 | make sure you use the same SKU here
and then if you have one rapid in some
| | 01:38 | curly braces like that.
| | 01:40 | And then delete everything in
the file that you don't need.
| | 01:43 | So once you've created you're
as to look something like that.
| | 01:47 | So once you've created that you're
going to need to copy that file into the SD
| | 01:52 | Card directory of your android device.
| | 01:54 | That could be in a different place
for each device the one I used was a
| | 01:58 | candle fire and that was actually in the root
directory when I plugged it into my computer.
| | 02:03 | So copy that into your SD card folder
and then you're going to need to install
| | 02:07 | the Amazon SDK tester app.
| | 02:09 | Or I did to install that is I copy the
file into my android SDK platform tools.
| | 02:17 | So we see here AmazonSDKTester.apk.
The reason I copied back in there is because
| | 02:23 | the adb is in there.
| | 02:25 | And so I opened up a command line
window, changed the directory to this platform
| | 02:29 | tools directory, and I ran adb
install AmazonSDKTester.apk.
| | 02:36 | Now once you've installed that, you
should test the app on your device just to
| | 02:40 | make sure that it works.
| | 02:42 | To test in-app purchases, you'll
need this app running; and if you've just
| | 02:47 | copied over that json file, you'll need to
unmount from your computer to save that change.
| | 02:53 | So once you've done all those steps,
you're ready to start writing the code
| | 02:56 | necessary to add Amazon In-
App Purchases to your app.
| | Collapse this transcript |
| Implementing Amazon IAP code| 00:00 | So now we'll look at the code to
implementing Amazon In-App Purchases; I'm going to
| | 00:05 | scroll down to my android manifest and
you'll see that I have some code here
| | 00:09 | starting with the receiver block.
| | 00:11 | You can copy and paste this code from
the Amazon in-app purchase SDK tutorial if
| | 00:15 | you want and that's exactly what I did here.
| | 00:18 | So we're just going to need the
receiver block and then let's go to Skins.cpp.
| | 00:23 | As I mentioned before, I just checked
to see if that user default is true.
| | 00:29 | If so, I set the skin and rerun
MainMenu, if not I run buyItem.
| | 00:35 | So to unlock the item all we need to
do is set that user default value true.
| | 00:39 | Let's look at buyItem.
| | 00:40 | I'll go over to jniIAP.cpp.
| | 00:44 | I added this file to the folder where
all of the jni files are and all it does
| | 00:50 | is it runs a static method buyItem
passing in the string to in moleitx.java.
| | 00:55 | Remember you have to past in the
fully qualified class name here, so
| | 01:00 | that's fairly simple.
| | 01:01 | Here is the header file in case you'd
like to see it, and moleitx.java let's
| | 01:06 | scroll down to buyItem.
| | 01:07 | In buyItem I used PurchasingManager.
initiatePurchaseRequests passing in the item.
| | 01:14 | PurchasingManager is an Amazon class.
| | 01:17 | So let's scroll up and see how
to handle the Amazon purchases.
| | 01:22 | I created a class called my
observer inside of my moleitx file and that
| | 01:27 | extends BasePurchasingObserver and this is like
a listener that listens for purchasing events.
| | 01:33 | So in there I have a private
moleitx called mainActivity.
| | 01:37 | In the constructor I pass in that
super and then I set mainActivity as the
| | 01:42 | activity passed into the constructor.
| | 01:44 | And if you want to you can override on
itemDataResponse; this is when you get
| | 01:48 | item data so you can display any extra
information to the user should you wish.
| | 01:54 | And then the method that is executed
when a purchase is responded to is called
| | 01:59 | onPurchaseResponse, and that gives
you the information about whether the
| | 02:03 | purchase was successful or
unsuccessful or they already have it.
| | 02:07 | So here I have a string call
response and I'm getting the string from the
| | 02:12 | purchaseResponse.getPurchaseRequestStatus
method, so that gives me the request status.
| | 02:18 | I got it as a string then I check to
see if it's successful or the person
| | 02:22 | already has this purchase.
| | 02:24 | If so I'll run mainActivity unlockSkin.
| | 02:27 | If not, I Log to see what the problem is.
| | 02:30 | So it's pretty straightforward and of
course you can find more information about
| | 02:33 | this purchase response class inside of
the documentation for the Amazon API.
| | 02:40 | So let's scroll down a little bit and
look at some other code that I added.
| | 02:44 | The unlockSkin method runs native
unlockSkin, which is a native method, which
| | 02:50 | we'll look at in just the second.
| | 02:52 | You'll notice that on start I create
the observer, passing in this and then I
| | 02:58 | tell the PurchasingManager to
register the observer and in onResume I run
| | 03:02 | PurchasingManager.initiateGetUserIdRequest.
| | 03:06 | So let's look at native unlocks
skin, that's defined in jniUnlock.cpp.
| | 03:13 | For this file there is no header file.
| | 03:15 | Here I am defining the Java_com_
toddparkins_moleitx_moleitx_nativeUnlocksSkin
| | 03:21 | with just the basic parameters.
| | 03:23 | And then I just run this CCUserDefault
method and set that value true for the
| | 03:27 | skin and that's how we unlock it.
| | 03:30 | So when you test this out on your
device, you should see that when you tap on
| | 03:34 | the aliens, a popup window should
show up, ask you to purchase the skin.
| | 03:38 | If you do and the purchase is successful,
if you hit ALIEN again, then it will
| | 03:42 | change to the Alien Skin
and that's all there is to it.
| | 03:46 | So there is kind of a lot of code to
implementing the Amazon In-App Purchases,
| | 03:51 | but as you've seen the code is fairly simple.
| | 03:54 | Once you have all this code setup,
you can test the app on your device and
| | 03:57 | confirm the In-App Purchases working by
clicking on the ALIENS button from the
| | 04:01 | skins menu and seeing that dialog popup.
| | 04:04 | And when you get a successful purchase,
you can close the dialog and hit ALIEN
| | 04:09 | again and the skin will change.
| | Collapse this transcript |
| Setting up IAP for Google Play| 00:00 | Adding In-App Purchases through
Google Play is a somewhat complex process.
| | 00:05 | The Google sample code is
thousands of lines of code for you to add a
| | 00:09 | custom implementation.
| | 00:11 | If you're looking for something as
easy as implementing an Amazon In-app
| | 00:14 | Purchase, you can use the
AndroidBillingLibrary from robotmedia.
| | 00:19 | You can find this project at GitHub.
| | 00:21 | This code simplifies Google Play In-App
Purchases to reduce them down to 20 or
| | 00:26 | 30 lines of code that you
can mostly copy and paste.
| | 00:30 | So you can download the ZIP file here,
and you can see the implementation
| | 00:34 | is fairly simple, and you're going
to need to copy and paste this code
| | 00:38 | inside of your Manifest.
| | 00:39 | So you can do that now, and
then we're going to use the
| | 00:43 | BillingController implementation.
| | 00:44 | You will also need some information
from the Android Developer Console.
| | 00:49 | From the Android Developer
Console, click Edit Profile.
| | 00:53 | From here, scroll down and copy your
Public Key as well, or you can just leave
| | 00:58 | this page open for later, and
paste it in when it's necessary.
| | 01:01 | Let's go over to Eclipse.
| | 01:03 | In Eclipse, I am going to open
up my AndroidManifest.xml file.
| | 01:07 | You'll need to add the
permission com.android.vending.BILLING.
| | 01:14 | Here's where I've pasted my
code, the robotmedia service.
| | 01:18 | And then you'll need to bring in all
the code files into your Eclipse project.
| | 01:23 | To do that, open up the robotmedia
project, and find the AndroidBillingLibrary.
| | 01:29 | In the source folder, you'll see
a com folder, and a net folder.
| | 01:32 | The com folder contains the
Android package for the vending library.
| | 01:36 | So just drag this Android
folder into your com folder.
| | 01:41 | Don't overwrite your com folder, or also
you may lose some of your existing files.
| | 01:46 | And then just drag that net folder
right into the source folder for your
| | 01:49 | project, and you can see
that I've done that here.
| | 01:51 | So inside of my source folder for my
project, I have the net folder, and then
| | 01:55 | in com, I have toddperkins and Android.
| | 01:58 | After you've done that, jump back over
to Eclipse and refresh or press F5, and
| | 02:05 | you should see all of these
classes imported in the source folder.
| | 02:09 | If you have any warnings or errors
when you do this, you can do two things;
| | 02:14 | you can try cleaning your project,
and you can go to Moleitx.java.
| | 02:18 | And if you see a line of code
that imports android.r, delete it.
| | 02:23 | Sometimes that line of code gets
inserted automatically by Eclipse.
| | 02:27 | Now, once you've imported all these
classes into Eclipse, you've updated your
| | 02:32 | Android Manifest and you're ready to
start writing the code to adding In-App
| | 02:36 | Purchases through Google Play.
| | Collapse this transcript |
| Implementing Google Play IAP code| 00:00 | Let's write the code to add Google
Play In-App Purchases to our game.
| | 00:04 | Note that most of the code we'll be
looking at I actually copied and pasted from
| | 00:09 | the Android Billing Library.
| | 00:11 | If you open up the Dungeons folder, go
into source, all the way down to all the
| | 00:16 | code, and if you open up Dungeons.java,
Application.java, that's where I got the sample code.
| | 00:23 | So any methods that I reference
here, you'll find that in there, which
| | 00:26 | should be especially helpful for those of you
who don't have access to the Exercise Files.
| | 00:30 | So let's go into Eclipse, and first I'm
going to point out that I have imported
| | 00:36 | all these robotmedia classes.
| | 00:38 | So you will need to do that, and
then scroll down, I created a property
| | 00:43 | that's an AbstractBillingObserver
called mBillingObserver, scroll down into
| | 00:48 | onCreate and I set
BillingController to debug, and then I set the
| | 00:52 | configuration for the BillingController.
| | 00:55 | And here, you can copy and paste
this ObfuscationSalt code, but this is a
| | 00:59 | special key that should be
customized in random from you.
| | 01:04 | So you can go in and edit these
numbers if you're going to publish your app.
| | 01:08 | I just copied this from the Dungeons
project, so I'm not worried about it being
| | 01:12 | unique because I'm not going to publish
the version that you're looking at right now.
| | 01:15 | Then, I have my Public Key, and this is
where you're going to need to paste in
| | 01:19 | that Public Key that you've got
from your Android developer account.
| | 01:23 | I set the mBillingObserver = new
AbstractBillingObserver, and then I am just
| | 01:30 | saying that for each of these methods,
I'm going to call onBillingChecked,
| | 01:35 | onPurchaseStateChanged,
onRequestPurchaseResponse, onSubscriptionChecked.
| | 01:36 | So you'll need to implement
those methods inside of this class.
| | 01:45 | Register the observer, check for
billing support, check for subscription
| | 01:50 | support, and then I've implemented
onDestroy, and in onDestroy, I unregister
| | 01:57 | the BillingObserver.
| | 01:59 | I'm going to scroll down, and in the
buyItem method, I run BillingController,
| | 02:03 | requestPurchase, passing in me,
that's the instance of moleitx, and then I
| | 02:09 | pass in this string.
| | 02:10 | Now, if you haven't already uploaded
your app and created In-App Purchase you
| | 02:14 | can actually still test that it
works by testing for the purchase
| | 02:18 | android.test.purchased.
| | 02:20 | Of course if you created an In-App
Purchase for your app, you want to pass
| | 02:24 | in that string here;
| | 02:26 | android.test.purchased will
also automatically return true.
| | 02:30 | So as long as that billing service
is running, then it's going to work.
| | 02:34 | And then you can see how I've
implemented most of these other delegate methods.
| | 02:38 | I just have a log that explains what
happened, I tagged it with IAP, and
| | 02:43 | onRequestPurchaseResponse, I check
to see if the response is equal to
| | 02:48 | ResponseCode.RESULT_OK.
| | 02:51 | If so, I unlock the skin.
| | 02:53 | You can also define what you do when
you check the billing, and when you check
| | 02:57 | the subscription status.
| | 02:58 | So you could see, it's not super
complicated, and if you want more detailed
| | 03:03 | code, you can look at the Dungeons
sample and see what else you can do and
| | 03:08 | what other methods you could implement to check
for your In-App Purchases and to restore them.
| | 03:13 | But once you have this code set up
and you run it on a device that has the
| | 03:18 | latest version of Google Play,
you'll be able to make In-App Purchases
| | 03:22 | through Google Play.
| | Collapse this transcript |
|
|
7. Going Forward and Getting HelpUsing the Cocos2d-x website| 00:00 | It's a good idea to follow what
happens on the Cocos2d-x website.
| | 00:04 | The site is regularly updated and
you can find information about the new
| | 00:08 | updates to Cocos2D and other utilities that
can make Cocos2D game development easier for you.
| | 00:14 | One resource that I used a lot in particular
when developing this course was the Forums.
| | 00:20 | Just like any other forum, you'll
find tons of useful information and
| | 00:24 | conversations both from the community, and
the developers and creators of Cocos2d-x.
| | 00:29 | I highly recommend looking through here
and searching here if you run into any
| | 00:33 | problems as you're developing your games.
| | 00:36 | In addition to the forums,
you'll also see the Reference page.
| | 00:40 | You can go to the Reference and hit
Cocos2d-x Online API Documentation, and you
| | 00:45 | see the documentation for all of the classes.
| | 00:48 | I'll hit Classes, and then Class Index,
and you can see the documentation for
| | 00:53 | every class in Cocos2d-x.
| | 00:55 | It's especially important to visit
this regularly because as the versions
| | 00:59 | of Cocos2D update, the use of a particular
class or the class itself might have changed.
| | 01:06 | So, throughout the Cocos2d-x website,
you have many resources that will help you
| | 01:11 | better develop your games.
| | Collapse this transcript |
| Viewing additional Android game development resources| 00:00 | After you've made the game we made in
this course, you may be interested in learning
| | 00:04 | more about game design and
creating your own commercial games.
| | 00:09 | There are some obvious
places to look, like web searches.
| | 00:13 | In developing six commercial games,
I have yet to find a problem that
| | 00:16 | somebody else didn't have.
| | 00:18 | If something doesn't work, paste your
error code into a search engine and find
| | 00:23 | out what other people have had the same problem.
| | 00:26 | If you don't see the problem for
Cocos2d-x and it's related to a class use or
| | 00:30 | something with the Cocos2d framework,
just look at regular Cocos2d-x and see if
| | 00:35 | you can translate the code into C++.
| | 00:38 | The Objective C language is not
incredibly different from C++, seeing as it's
| | 00:43 | in the same C family.
| | 00:45 | So you may be able to find
your solutions in that way.
| | 00:48 | Here's another resource that
I found particularly useful.
| | 00:51 | The website is emanueleferonato.com.
| | 00:54 | This is perhaps the best resource for
learning how to develop games that I've
| | 00:59 | found anywhere on the web.
| | 01:01 | If you look at the different articles,
you'll see that most of them are related
| | 01:05 | to Flash and ActionScript.
| | 01:06 | But there are over 500
articles related to game design.
| | 01:10 | So, if you click that link, you can find a
bunch of information about how to develop a game.
| | 01:16 | This website finds games that exist
that are popular and explains how to
| | 01:20 | build those game engines.
| | 01:22 | So through that, you can learn how to
think like a game developer and how to
| | 01:26 | plan and program different types of apps and
venture beyond what we created in this course.
| | 01:33 | So I encourage you to experiment, and
to look at other resources on the web
| | 01:37 | to find more information about game
design, and if you find any yourself, let
| | 01:42 | me know.
| | Collapse this transcript |
|
|
ConclusionGoodbye| 00:00 | That concludes this course on how to
build and monetize an Android game.
| | 00:05 | I hope you've learned a lot about how
to use a Cocoas2d-x framework to build
| | 00:10 | a game for Android.
| | 00:12 | Remember, there are many
resources out there to advance your game
| | 00:15 | development skills.
| | 00:16 | And like I said, if you find anything
interesting that you'd like to share, you
| | 00:20 | have any questions about the course,
or if you make a game using this
| | 00:24 | framework, I want to know.
| | 00:26 | You can find me on Twitter, @asktodd.
| | 00:28 | I'll see you next time!
| | Collapse this transcript |
|
|