IntroductionWelcome| 00:04 | Hi! I'm Lee Brimelow and welcome to
Building Flash Games with Starling.
| | 00:08 | In this course I'm going to show you
how to leverage the open-source Starling
| | 00:12 | framework to create games that
fully tap into the power of the GPU.
| | 00:16 | I'll cover all of the major
features of the framework including how to
| | 00:20 | incorporate different assets like
sprite sheets and sound effects.
| | 00:24 | How to create a simple game framework that
can serve as the basis for your own games.
| | 00:29 | How to add beautiful particle effects,
and also how to optimize your game, so
| | 00:33 | that they'll run great even on mobile devices.
| | 00:36 | After going through this course
you'll have all the information you need to
| | 00:39 | create your own high performance
Flash games using the Starling framework.
| | Collapse this transcript |
| Using the exercise files| 00:00 | If you are a Premium subscriber to the
lynda.com online training library or if
| | 00:05 | you are watching this course on a DVD-ROM,
then you have access to the exercise files.
| | 00:09 | And I've just gone ahead and
put them on to my Desktop here.
| | 00:13 | And you can see inside of it, it's just
a whole bunch of different assets that
| | 00:16 | we are going to be using throughout
our game, and these include things like
| | 00:20 | animation sequences, sound effects,
particle effects, and bitmap fonts.
| | 00:26 | Now if you don't have access to the
exercise files, I'll be explaining
| | 00:29 | throughout the course how you can go
ahead and create your own assets to use
| | 00:34 | inside of this game.
| | Collapse this transcript |
| What you should know| 00:00 | So before we get started working
through this course I want to make sure you
| | 00:03 | have the necessary skills in
order to get the most out of it.
| | 00:07 | So since we are going to be building
Flash games, you are obviously going to
| | 00:11 | want to have some Flash experience,
and particularly experience writing code
| | 00:15 | using ActionScript 3.0.
| | 00:17 | And this includes understanding the
Flash display list, because the Starling
| | 00:21 | framework actually bases its API on
that display list, and also object-oriented
| | 00:27 | programming techniques because we are
going to creating things like classes and
| | 00:30 | interfaces and you should have a
good idea of what those things are.
| | 00:35 | So it's not entirely necessary for
you to have game development experience
| | 00:39 | because I'm going to be showing you
how to build a game from scratch, but of
| | 00:43 | course, if you've built Flash games
before it's obviously going to help you
| | 00:46 | in this course.
| | Collapse this transcript |
|
|
1. Getting StartedChecking out the finished product| 00:00 | So before we get started I just
want to show you what we're going to be
| | 00:03 | creating in this course.
| | 00:04 | So we're going to be creating this
simple top-down shooter game called
| | 00:08 | Spacer, and you can see here that
when I come in I have this menu with this
| | 00:13 | scrolling star background.
| | 00:14 | I have my little logo here and then
I have a button that says PLAY GAME.
| | 00:18 | So when I go into the actual game you
can see we have our little hero ship with
| | 00:23 | a nice smoke trail particle effect,
and when I hold down the mouse button, I
| | 00:28 | actually fire bullets at the aliens,
and you can see when I hit them, that they
| | 00:36 | actually explode with this particle effect.
| | 00:40 | Now when my ship actually hits one of
the aliens, then the game is considered
| | 00:44 | over, we go to this Game Over screen,
and then I can click a TRY AGAIN button
| | 00:49 | to try the game again.
| | 00:55 | Now it's a very simple game play here.
| | 00:57 | I'm keeping track of a high score. It's
not the most advanced game in the world,
| | 01:01 | but it does highlight all of the major
features in the Starling framework, and
| | 01:06 | this is what we're going to
be creating in this course.
| | Collapse this transcript |
| Downloading the Starling framework| 00:00 | So before we get started actually
building things with the Starling framework,
| | 00:04 | we first need to download it.
| | 00:06 | Now Starling is an open-source framework
that you can get at gamua.com/starling.
| | 00:13 | And Gamua is the company
that's actually created Starling.
| | 00:18 | So from that page you can go ahead and
click the Download button, and you can
| | 00:22 | download a ZIP file directly from here,
or you can actually go to the repository
| | 00:27 | on GitHub, which is what we're going to
do, so I'm going to click that, and it's
| | 00:31 | going to take me to the
Starling-Framework GitHub page.
| | 00:35 | Now if you're used to using Git you can
definitely fork this or just clone it to
| | 00:40 | your computer. We're just going to go
to Downloads, and then I'm just going to
| | 00:45 | click Download as zip, and this is
going to download a ZIP file of the Starling
| | 00:50 | framework, including things like
documentation and also some samples.
| | 00:56 | So I'm going to go into my Downloads
folder here, and if we look inside of here,
| | 01:01 | have a bunch of different of things
like samples, tests, some utils, or if we go
| | 01:06 | into the starling folder, into the
source folder. These are obviously the
| | 01:11 | source code files for the Starling framework.
| | 01:14 | So I'm going to go ahead and copy
these three folders, and then go to my
| | 01:18 | Desktop, and I'm going to create a new
folder on the Desktop called code, and
| | 01:24 | this is going to hold all of the source code
that we're going to be linking to in this course.
| | 01:29 | So now I have the Starling classes in
here and I'm able to start using them.
| | 01:34 | Now there is a couple of other things
that we're going to be using as well.
| | 01:38 | So if we go back to the main Starling
page, we can go to this Help button, and
| | 01:44 | there's a bunch of really good helpful
resources about Starling, and another
| | 01:49 | thing that's really nice about Starling
is that it's extensible, and people are
| | 01:53 | already writing a lot of
extensions for Starling.
| | 01:57 | So if we go down to this Wiki entry
under extensions, we can see some of the
| | 02:02 | extensions that are currently under
development, and one of them that we're
| | 02:06 | going to be using is this
Particle System, extension.
| | 02:09 | So I'm going to go ahead and click that,
and we can see an example, and this is
| | 02:13 | an example of that particle
extension being rendered in Starling.
| | 02:18 | Now I'm going to go to the GitHub
repository for that particle system, and much
| | 02:23 | like I did before, I'm going to click
on Downloads, and then Download as zip.
| | 02:31 | And now I'm going to go back to my
Downloads folder, and inside of here if we
| | 02:38 | look under the source folder,
we have a starling directory, and an
| | 02:43 | extensions directory.
| | 02:45 | So this I'm actually going to copy
and paste into my main source folder
| | 02:50 | that's on the Desktop.
| | 02:51 | So I'm going to copy the extensions
folder, go back to the Desktop, under code >
| | 02:56 | starling, and then paste that in.
| | 02:58 | And I now have that particle
extension linked in with the rest of my
| | 03:03 | Starling source code files.
| | 03:05 | So one other thing that we're going to
using is an object pool class, and once
| | 03:11 | we start building our game, I'll
explain why it's so important to use that, but
| | 03:15 | the class we're going to be using is one
that I have actually created, and if we
| | 03:20 | go to my GitHub page, just github.com/
brimelow, and then go to the ActionScript
| | 03:27 | repository, there is only thing in
there right now and we're just simply going
| | 03:31 | to download that as well.
| | 03:32 | So I'm going to say Download as zip, and
again go to my Downloads folder, and in
| | 03:40 | that com directory, we have a
leebrimelow directory. I'm going to go ahead and
| | 03:44 | copy that, and then go to my main source
code folder on the Desktop, go into the
| | 03:50 | com directory and then paste in that folder.
| | 03:55 | So we now have that
StarlingPool class in there as well.
| | 04:00 | So those are all the major source code
libraries that we're going to going to be
| | 04:04 | using, so just again, make sure that you
incorporate all of those into a folder
| | 04:08 | somewhere on your computer so that we
can link to them from Flash Builder.
| | Collapse this transcript |
| Installing Flash Builder| 00:00 | So as we go through this course
building our game, we are going to be doing
| | 00:04 | it using Flash Builder 4.6, which
is the latest version of Adobe's
| | 00:08 | ActionScript 3 Editor.
| | 00:09 | Now you can use other editors, for
instance, you could do this in Flash
| | 00:13 | Professional, but I don't recommend it
as building a game is something where you
| | 00:18 | are going to be doing a lot of
intensive coding and you need a full featured
| | 00:22 | editor like Flash Builder.
| | 00:24 | So from the adobe.com homepage you can
go to Downloads, and then from this page
| | 00:29 | if we go to All product trials here,
we can actually scroll down to Flash
| | 00:35 | Builder 4.6 and click Go.
| | 00:38 | And from this page you can download a full
featured trial version of Flash Builder 4.6.
| | 00:44 | So again make sure the correct version
for your operating system and language is
| | 00:49 | selected and go ahead and
download that and install it.
| | 00:53 | Now another thing you are going to
want to make sure you have is the latest
| | 00:57 | version of the Flash Player, and in
particular the debug version of the player.
| | 01:02 | So if we go to adobe.com/support/
flashplayer/downloads.html, you are going to be
| | 01:12 | able to download the latest
version of the Flash Player.
| | 01:15 | And if we scroll down, at the time I'm
recording this, that's 11.2. So again
| | 01:20 | depending on which operating system
you are using, you want to download the
| | 01:25 | plug-in the content debugger
version of that plug-in and install it.
| | 01:31 | So in this course, I'm going to be
using Safari, but again depending on which
| | 01:35 | operating system, which Browser you are
using, just make sure you download the
| | 01:39 | appropriate debugger plug-
in and have it installed.
| | Collapse this transcript |
| Installing additional tools| 00:00 | So in addition to Flash Builder, I'm
going to be showing you how to use a few
| | 00:04 | different tools throughout this
course, but only one of them is actually
| | 00:07 | required for you to get, and
that's a tool called TexturePacker.
| | 00:11 | If you go to codeandweb.com/texturepacker,
you can download this tool, which
| | 00:17 | essentially allows you to create
sprite sheets, and sprite sheets are something we
| | 00:22 | are going to be using
quite a bit during this course.
| | 00:24 | And this is a tool that has a free
version available, and then if you like it,
| | 00:29 | you can pay a small amount to
essentially unlock some additional features.
| | 00:33 | But you are going to want to
download this tool and it's available on all
| | 00:37 | major operating systems, so
obviously download and install the one that's
| | 00:41 | appropriate for your system.
| | 00:43 | Now another tool that I'm going to be
showing is a tool called Glyph Designer,
| | 00:47 | and here is the URL for it right here
and this is a tool that is only available
| | 00:52 | on Mac, but once we get to this section
of the course, I'll explain some other
| | 00:57 | options that are available
for other operating systems.
| | 00:59 | Now it's not required that you get this
tool because I've actually provided the
| | 01:04 | assets for you that came out of this
tool, but if you are on Mac you can go
| | 01:08 | ahead and download this and
follow along when I get to that part.
| | 01:11 | Now another tool made by the same
company is a tool called Particle Designer,
| | 01:15 | and this is a visual tool
for creating particle effects.
| | 01:20 | Again, it's not required that you have
this tool during the course, but if you
| | 01:24 | want to download it and follow along
with me, you can definitely do that if
| | 01:28 | you are using a Mac.
| | Collapse this transcript |
| Overview of the Starling framework| 00:00 | So before we get started I just
wanted to give you an overview of what the
| | 00:04 | Starling framework actually is.
| | 00:06 | So Starling is a pure ActionScript 3
library that mimics the conventional Flash
| | 00:10 | display list architecture.
| | 00:12 | In contrast to conventional display
objects however all content in Starling is
| | 00:17 | oriented directly by the GPU, and
this is made possible by the Stage 3D
| | 00:22 | rendering engine that was
introduced in Flash Player 11.
| | 00:26 | Now a couple of things to highlight is,
again this framework is free and open
| | 00:30 | source, and it's actually open-sourced
under a simplified BSD license, which
| | 00:35 | means you can download it, tweak it,
do whatever you want with the framework.
| | 00:39 | Now in addition to building games that
run in Flash in the browser, we can also
| | 00:44 | use it to build mobile
games for iOS and Android.
| | 00:50 | And lastly I wanted to highlight that
while Starling is actually developed
| | 00:54 | outside of Adobe by Gamua, this is a project
that Adobe is actively funding and backing.
| | 01:00 | So now let's look at an actual Starling
game that's out there on the web right
| | 01:05 | now, and definitely the biggest
one is Angry Birds on Facebook.
| | 01:09 | So obviously everybody knows Angry
Birds first introduced as a mobile game, was
| | 01:14 | hugely successful, and when Rovio
decided they wanted to bring that game to
| | 01:19 | Facebook, they chose Flash
and the Starling framework.
| | 01:23 | And here it is running in Facebook,
it's the traditional Angry Birds that you
| | 01:27 | are used to playing on your mobile
devices, but now embedded in Facebook.
| | 01:31 | And Rovio was able to use lots of
particle effects and other kind of visual
| | 01:36 | eye candy things because all of the
content is running under GPU when you are
| | 01:42 | using Starling.
| | Collapse this transcript |
|
|
2. Project SetupCreating the Flash Builder project| 00:00 | So in this movie we are going to
create the Flash Builder project that we are
| | 00:04 | going to be using throughout this course.
| | 00:06 | So open up Flash Builder 4.6, and I'm
just going to right-click in the Package
| | 00:11 | Explorer and choose New > ActionScript Project.
| | 00:14 | Now we are going to be calling this
project Spacer and you can just save the
| | 00:21 | project to the default location.
| | 00:23 | For Application type, we are going to
want to create something that runs on the
| | 00:28 | web inside a Flash Player, and we are
going to use the default Flex 4.6 SDK.
| | 00:34 | So essentially you can leave everything else
here at their default values and click Next.
| | 00:39 | Now the next thing we need to do is to
link up the actual source files where the
| | 00:45 | Starling framework is located.
| | 00:46 | So we are going to click on the Source
path tab and click Add Folder, and then
| | 00:52 | I'm going to browse and navigate to
that code folder that we created and click
| | 00:58 | Open, and then click OK, and then Finish.
| | 01:03 | So now we have our default
class created called Spacer.
| | 01:08 | Now one of the things that you need
to be aware of when you are using the
| | 01:12 | Starling framework and Stage 3D is
that when you embed it using HTML into the
| | 01:18 | browser, you need to set
the W mode value to direct.
| | 01:24 | So what we can do is to change the HTML
template in our project, so I'm going to
| | 01:28 | go into the HTML template folder, right
-click on the indextemplate.html, and
| | 01:34 | then choose Open With > Text Editor.
| | 01:37 | This will allow me to edit that HTML
file and all I'm going to do is to come
| | 01:42 | into the swfobject code here
and put in a new parameter.
| | 01:47 | So I'm going to put params.wmode and
then in quotes put direct, like that.
| | 01:57 | And then I'm going to save this
file and now I can close the template.
| | 02:01 | So now each time the HTML template is
actually created, it's going to set that W
| | 02:07 | mode value to direct.
| | 02:10 | And again, I can now debug this project
and it should open in the browser and if
| | 02:15 | we right-click, you should Flash Player 11.2;
| | 02:19 | again, make sure you have the latest
version of the Flash Player debugger
| | 02:24 | installed on your system.
| | 02:26 | And you should also, in the top of your
project here, see that code folder linked
| | 02:31 | to with those Starling class files.
| | 02:34 | So that's our basic project setup
that we are going to be using throughout
| | 02:39 | this course.
| | Collapse this transcript |
| Setting up your Starling scene| 00:00 | So in the last movie we created our
basic Flash Builder ActionScript 3 project
| | 00:06 | which is going to serve
as the basis for our game.
| | 00:09 | Now we want to modify this main Spacer
class that is essentially our default
| | 00:15 | class that gets launched when we run the game.
| | 00:18 | The first thing I am going to want to do
is to put in some SWF metadata up here, and this
| | 00:24 | is going to allow me to control the
width, height, background color and frame
| | 00:27 | rate of our actual game.
| | 00:29 | So I am going to start putting that in
and first thing I am going put in is the
| | 00:34 | width and our game is going to be
800x800, put in a height of 800.
| | 00:38 | We are going to set the frame rate
of our movie to 60 frames per second.
| | 00:44 | Now if you are used to
regular Flash, you might think, wow!
| | 00:46 | That's a really fast frame rate, and
you can now reliably use 60 frames per
| | 00:52 | second, again, because since Starling
is running on the GPU we can get that
| | 00:55 | really fast performance.
| | 00:56 | And I am going to set the
backgroundColor of my movie to black like that.
| | 01:04 | So now we have our SWF metadata set up.
| | 01:07 | Now you'll notice that this class
extends flash.display.Sprite, which is the
| | 01:12 | main display object container
that you are used to working.
| | 01:16 | But when you are working with Starling,
you are not using the regular display
| | 01:20 | list, because Starling has its own
version of the Sprite class, its own version
| | 01:24 | of the movie clip class.
| | 01:26 | So this main class that you come into
essentially all that it does is to launch
| | 01:32 | your Starling instance, which
will be handled in a different class.
| | 01:36 | And once you are in that class,
you are no longer using the regular
| | 01:40 | Flash display list.
| | 01:41 | So in the constructor here, what we
first we need to do is to create an instance
| | 01:45 | of the Starling class.
| | 01:46 | You can call it whatever you want, but
I usually call it star, so I am going to
| | 01:51 | say var star and this is going to be
of type Starling equals new Starling.
| | 01:57 | And to this we can pass in a
host of different properties.
| | 02:01 | The first is that main class, the
ActionScript class, which is going to be our
| | 02:06 | root Starling instance.
| | 02:08 | We haven't created that class yet,
but we are going to call it Game.
| | 02:12 | Now the next is which stage object do we
actually want to render our Starling instance?
| | 02:19 | Well we want to render it in
our main stage for this class.
| | 02:23 | So we can simply pass in
the stage object like that.
| | 02:27 | Now those are the only two parameters
that we are actually going to be sending
| | 02:31 | into the constructor.
| | 02:32 | Again, first is the main class, which is
going to be our Starling root, and then
| | 02:36 | the main stage in which we are going
to be rendering our Starling instance.
| | 02:41 | But just to look at some of the other
parameters, we can actually provide a
| | 02:45 | viewPort Rectangle if we wanted to render
Starling into a certain rectangle of that stage.
| | 02:52 | Some other more advanced properties
are a Stage 3D instance, so if you are
| | 02:56 | working with low level Stage 3D objects,
you can actually give it a custom Stage
| | 03:01 | 3D object to use for Starling.
| | 03:04 | But in typical cases, you are not going
to need to use this parameter at all.
| | 03:08 | Now the last parameter is called
render mode and this is an interesting one
| | 03:12 | because Stage 3D can actually run
either using the GPU or it can actually
| | 03:18 | render in software mode.
| | 03:20 | So if somebody goes to your game and
they don't have a supported graphics
| | 03:23 | driver, they are actually going to
be viewing your game in software mode.
| | 03:29 | So if you wanted to force software
mode so that you could test out how it
| | 03:34 | performed, you could actually
send in software for that string.
| | 03:38 | But again, we are not going to need to
do that, so we are only going to send in
| | 03:40 | these two arguments.
| | 03:42 | Now another nice feature of Starling
is that it has a build in stats class.
| | 03:47 | So often, as you are building your Game,
you are going to want to see things like
| | 03:51 | what is the current frame rate, or how
much memory is my game currently taking.
| | 03:55 | And while you are debugging
that can be really helpful.
| | 03:58 | So to show that we are going
to say star.showStats = true;
| | 04:04 | and obviously when you go out and
publish your final game, you are going to want
| | 04:08 | to remove that, because typically you
are not going to want to show those stats.
| | 04:12 | Now this Starling instance can be
started and stopped and this is useful, let's
| | 04:17 | say, if the user navigates away from
your game, you can actually stop the
| | 04:21 | Starling instance, which will stop
everything about it and then you can restart
| | 04:25 | it when the user returns to your Flash movie.
| | 04:28 | So we are going to go ahead and start
that Starling instance and what this is
| | 04:32 | going to do is essentially going to
now call this Game class and that will be
| | 04:38 | now our root Starling class.
| | 04:41 | Now just to show you some of the
other properties that are available on the
| | 04:44 | Starling instance, we have things like
being able to set a custom antialiasing
| | 04:48 | amount. We can actually scale content up.
| | 04:52 | This is useful on mobile, like if
you are dealing with, let's say, a second
| | 04:56 | generation iPad and the new iPad with
the retina display, you can actually use
| | 05:01 | that scale factor to scale
up your content appropriately.
| | 05:05 | You can enable error checking; this
is particularly for Stage 3D methods.
| | 05:10 | You don't want to do that unless you
need to, because it can have a negative
| | 05:13 | performance impact.
| | 05:15 | If you need to get to or have a
nativeOverlay, if you want to add traditional
| | 05:20 | regular Flash display list content
over your Starling instance, you can use
| | 05:24 | this nativeOverlay.
| | 05:26 | We can get access to the nativeStage object,
which we will be doing later on in the course.
| | 05:31 | Another interesting feature is
the ability to simulateMultitouch.
| | 05:36 | So Starling was built with mobile in mind.
| | 05:38 | So it has Multitouch classes available
and if we simulateMultitouch to true,
| | 05:44 | we can actually, by holding down the
Ctrl key, enable multiple touch points and
| | 05:48 | see how they interact.
| | 05:50 | So definitely look through all of
the properties in the documentation.
| | 05:54 | In our case here, all we are going to do
is simply turn the stats on and then we
| | 06:00 | are going to start off our Starling instance.
| | 06:02 | And in the next movie we are going to
go ahead and create our main Game class.
| | Collapse this transcript |
| Creating the main game class| 00:00 | So now that we have our main entry to
our game created in the Spacer class,
| | 00:06 | we now need to create our Game class, which
is going to be our root Starling instance.
| | 00:11 | So what I'm going to do is go into the
default package here, right-click, and
| | 00:17 | say New > ActionScript Class.
| | 00:19 | Now we're actually going to be
organizing the classes in our games into
| | 00:23 | different packages, and we're going to
hold this Game class in a package called
| | 00:27 | core, which is going to contain
our core files for our project.
| | 00:32 | And for Name we're going
to give this a name of Game.
| | 00:36 | For the Superclass, this is going to
need to sub-class sprite, but again, we're
| | 00:42 | not going to be using flash.display.
Sprite, we're using starling.display.Sprite,
| | 00:47 | so that's a very important distinction.
| | 00:49 | It can be a little difficult at
first when you first begin with Starling,
| | 00:53 | because again, the class names are
often times exactly the same as the
| | 00:56 | traditional display list, so you need to
make sure you are using the correct one.
| | 01:00 | I'm going to click Finish now.
| | 01:03 | And now we have our core package
with that Game class inside of it.
| | 01:07 | Now you'll notice the Spacer class
still has an error and that's because the
| | 01:11 | Game class is not in the same package.
| | 01:15 | So what we're going to do is to move
that Spacer class into the core package,
| | 01:19 | we're just going to drag it like that,
and then we can click OK, and it's going
| | 01:23 | to tell you that there is errors but
don't worry about it, just click Continue,
| | 01:27 | because the error will be corrected as
soon as it gets into the core package.
| | 01:32 | So now both our Spacer class and our
Game class are in that core package.
| | 01:37 | So the first thing I am going to do in
the constructor, and we don't have to
| | 01:41 | call this super constructor here, is
we need to listen for the ADDED_TO_STAGE
| | 01:45 | event, because we don't want to do
anything with our main Starling instance
| | 01:48 | here, until we know it's
been added to the stage.
| | 01:51 | So we're going to say addEventListener.
| | 01:54 | Now here again, we're going to be using
the ADDED_TO_STAGE event, but this is the
| | 01:58 | one that's actually in Starling, so
when you import it, you want to import the
| | 02:02 | starling.events.Eventclass.
| | 02:05 | And you'll notice it has a lot of very
similar methods or events rather than the
| | 02:09 | traditional event class. Now there is
also some other ones in here that are
| | 02:13 | specific to Starling.
| | 02:14 | But we're going to use the ADDED_TO_
STAGE event, and we're going to have it call
| | 02:18 | a function called init.
| | 02:19 | So let's go ahead and create that function.
| | 02:22 | So private function init, the event
object again is going to be of type starling
| | 02:29 | events.Event. We're not going
to be returning anything here.
| | 02:32 | So now inside of this main class, we're
going to have an enter frame loop, and
| | 02:39 | this is going to serve as our main game loop.
| | 02:41 | In the init event, register and
listen for the ENTER_FRAME event. So again,
| | 02:47 | addEventListener, this is going to be
event.ENTER_FRAME, and we're going to have
| | 02:54 | it call a method called update.
| | 02:56 | Quick tip in Flash Builder, if you hit
Command+1 or Ctrl+1, it will give you
| | 03:01 | this quick fix menu, it will give you the
option to create that method called update.
| | 03:07 | And all we have to do is to
add in the event object to that.
| | 03:10 | So I'm going to say event, and
again this is going to be of type Event.
| | 03:14 | And that's our basic Game class created.
| | 03:17 | Again, the main thing to understand
is that once we're in our main Starling
| | 03:21 | instance here, we're now going to be
working with the Starling version of the
| | 03:27 | display objects, so you're not going
to using regular movie clips and sprites;
| | 03:31 | we're now essentially in Starling world.
| | 03:34 | Here is the main entrance to our game,
which is our Spacer class, this is what
| | 03:39 | extends flash.display.Sprite.
| | 03:42 | But again, once we're in our Starling
instance, we have now switched to using the
| | 03:47 | Starling versions of all of those classes.
| | 03:50 | Now it is possible to mix regular Flash
display list with Starling, but it's not recommended.
| | 03:56 | If you're building a game, you should
try to do everything inside of Starling,
| | 04:02 | even things like menus and high
scores and things like that, and we'll get
| | 04:06 | into how you can accomplish that
later in the course, but this is the main
| | 04:09 | structure for our Game class.
| | Collapse this transcript |
|
|
3. The Game State MachineCreating the IState interface| 00:00 | So we are going to be separating our
game into different states and more
| | 00:04 | specifically our game is going
to have three distinct states.
| | 00:07 | First, it's going to have a Menu state,
and this is when you first come into
| | 00:11 | the game it's going to display the logo and a
button in which you can start playing the game.
| | 00:16 | Then there's going to be a Play state and
this is when you are actually playing the game.
| | 00:20 | And then finally a Game Over state,
which will display a message saying, game
| | 00:24 | over and do you want to try and play again.
| | 00:26 | Now a larger scale game of course,
you're going to have lots and lots of
| | 00:30 | different possible states.
| | 00:31 | So to create these state classes what
we are first going to do is to create an
| | 00:35 | interface, and an interface is
essentially going to require that any state
| | 00:40 | implement a certain set of methods.
| | 00:42 | So I'm going to go to the source folder,
right-click and say New > ActionScript
| | 00:47 | Interface, and we are actually
going to put this into a package called
| | 00:51 | interfaces. This is the only one we are
going to be creating for this game, but
| | 00:56 | still again, it's nice to separate
things and organize it into packages.
| | 01:01 | So using the best practices naming
conventions, we're going to call it IState,
| | 01:07 | so it's essentially called IState.
| | 01:09 | I'm going to click Finish.
| | 01:12 | And for our state classes we are
going to require that they implement two
| | 01:16 | methods, one is called
update and one is called destroy.
| | 01:20 | The update method is going to be
called on every frame and that's essentially
| | 01:24 | where we are going to able to update
its visuals and do things, different logic
| | 01:29 | operations depending on what state we are in.
| | 01:32 | And then the destroy method is going
to handle actually cleaning up after
| | 01:35 | itself, getting rid of the state from
memory, so that we don't have memory leaks.
| | 01:40 | So I'm going to define two functions in
here, the first one is called update and
| | 01:45 | the return type of both of these
functions is just going to be void, since we
| | 01:49 | are not going to be returning
anything from either function. So function
| | 01:55 | destroy(), and again this is going to
be of type void for the return type.
| | 02:02 | So that's all we are going to be
creating for our interface but now when we
| | 02:05 | create those state classes, when we
implement this interface, we'll be sure that
| | 02:10 | each of those states
implements the required methods.
| | Collapse this transcript |
| Creating the three game states| 00:00 | So now that we have our IState
interface created, we can go ahead and create
| | 00:04 | those three Game states: the Menu state,
the Play state and the Game Over state.
| | 00:09 | So I'm going to right-click on our
source folder and choose New > ActionScript
| | 00:14 | Class, and for a Package we are
going to store these state classes in a
| | 00:19 | package called states.
| | 00:20 | And the first one I'm going
to create is the Menu state.
| | 00:24 | Now for a superclass this is going to
subclass starling.display.Sprite, because
| | 00:30 | it's going to contain the actual
visual representation for the state.
| | 00:34 | And for interfaces we are going to
Add that IState interface, so if we
| | 00:39 | actually just search for it here we
can see the IState interface, click OK,
| | 00:45 | and now we can click Finish.
| | 00:47 | And you could see automatically by
implementing that interface it's now created
| | 00:51 | the update and destroy methods for us.
| | 00:55 | So we are going to make a couple of
changes to this. The first thing we are
| | 00:59 | going to do is when we create one of
these states from our Game class, we are
| | 01:03 | actually going to send in a reference
to our main Game class so that we can
| | 01:08 | communicate back to it.
| | 01:09 | So in the constructor here, I'm going to
put an argument called game, and this is
| | 01:14 | going to be of type Game.
| | 01:16 | And now inside of our constructor we
are going to create an instance property
| | 01:21 | called game, so I'm going
to say this.game = game;
| | 01:26 | and now I can hit Command+1 or Ctrl+1
to get a quick fix to create that as an
| | 01:31 | instance variable at the top.
| | 01:34 | So now anywhere inside of this state I can
actually call back to our main Game class.
| | 01:39 | Now the next thing I'm going to do is
to add an event listener for the added to
| | 01:44 | stage event, again because we don't
want to do anything here until we know it's
| | 01:48 | been added to the stage.
| | 01:49 | So I'm going say addEventListener and
again be sure when you are importing event
| | 01:54 | that you are importing starling.events.Event.
| | 01:57 | We are going to listen for ADDED_TO_
STAGE and we are going to have it call a
| | 02:02 | function called init.
| | 02:03 | And let's go ahead and define that function now.
| | 02:06 | So private function init, we are
going to have our event object be of type
| | 02:12 | starling.events.Event.
| | 02:14 | I'm not going to return
anything and now we have that set up.
| | 02:17 | So this is going to be main template that
each of our states is going to implement.
| | 02:22 | So what I'm going to do is copy this
entire class to the clipboard, and now
| | 02:27 | I'm going to right-click in the states package
and we are going to create the other two states.
| | 02:32 | So New > ActionScript Class, and this
one is going to be called Play, and again,
| | 02:37 | the Superclass is going to
be starling.display.Sprite.
| | 02:41 | For interfaces we are going to implement
that IState interface and click Finish.
| | 02:47 | Now I'm just simply going to select all
of text in here and paste in that Menu
| | 02:52 | state, because now all we need to do is
to simply change Menu to Play here and
| | 03:00 | there, and now we have our Play state created.
| | 03:03 | So now we are going to do the
same thing for the Game Over state.
| | 03:07 | So New > ActionScript Class, this one
is called GameOver, Superclass is going
| | 03:13 | to be Sprite.
| | 03:15 | We are going to implement the
IState interface, click Finish, and again,
| | 03:21 | replace the text with the text
that's on the clipboard, change this to
| | 03:26 | GameOver and GameOver like that.
| | 03:32 | So now you can see we have our states
package and we have our three states created.
| | 03:39 | So now in the next movie we are going
to look at implementing a state machine
| | 03:44 | which is going to control the
switching of the various states of our game.
| | Collapse this transcript |
| Building the state machine| 00:00 | Okay, so now we have our
three main game states created.
| | 00:04 | Now our main Game class is going to
actually incorporate a state machine and its
| | 00:10 | whole purpose is going to be to switch
between the various states of our game.
| | 00:15 | So with the top of Game class, I am
going to define three constants which are
| | 00:20 | actually going to represent each
of the states in the state machine.
| | 00:24 | So I am going to say public, and these
are going to be static so that we can
| | 00:29 | reference them anywhere and they are
going to be directly attached to our class,
| | 00:34 | and we are going to say const for
constant, and the first one is going to be
| | 00:38 | MENU_STATE and these are going to be
simple integer values, and they just have to
| | 00:45 | contain unique integer values.
| | 00:47 | I am going to set this one equal to zero.
| | 00:49 | I am going to duplicate that twice
and now we are going to change this to
| | 00:54 | PLAY_STATE and I am going to make this
one a value of 1. We'll make this one a
| | 01:02 | value of 2 and change it to
GAME_OVER_STATE, like that.
| | 01:10 | So again, just these three constants and
this is going to enable us to reference
| | 01:15 | these states via a nice constant
value instead of having to use the actual
| | 01:19 | integer values themselves.
| | 01:21 | Now another property we are going to
create up here is going to be variable
| | 01:25 | which is going to hold what is the current
state which is actually visible in our game.
| | 01:30 | So we are going to create
this an instance variable.
| | 01:33 | So private var current_state and now
this going to be of type IState, which
| | 01:42 | is our interface.
| | 01:44 | So it's nice that we can do this,
because again, we don't have to reference them
| | 01:50 | as their individual types, like GameOver,
Menu or Play, since they all implement
| | 01:55 | that IState interface, we can nicely
type this to IState and it will essentially
| | 02:01 | include all three of those.
| | 02:02 | Okay, so now we have that created,
now what we need to do is to create a
| | 02:07 | function, and this is going to be
public function which is going to allow us to
| | 02:11 | change the state of our game
from any of the individual states.
| | 02:16 | So let's say I'm currently in the Play
state of my game and I die, and then I
| | 02:21 | need to change the state
of the game to GameOver.
| | 02:24 | Well I am actually going to call this function.
| | 02:28 | So we are going to create a public
function and it's going to be called
| | 02:34 | changeState, and to this function we
are going to send in an integer value
| | 02:39 | which represents which state we want
to change to and it could be any one of
| | 02:42 | these three constants.
| | 02:44 | So this is going to be of type int and we
are not going to be returning anything here.
| | 02:49 | So now inside of this changeState we
are going to essentially use a switch
| | 02:54 | statement to find out which state is
actually passed in and then we are going
| | 02:59 | use that value to change the state of our game.
| | 03:02 | But what we first want to do is to
come in because when we first come to our
| | 03:06 | game, remember there is no current state.
| | 03:09 | So this current_state
variable will actually be null.
| | 03:12 | So we are going to test for
that at the very beginning of our
| | 03:15 | changeState function.
| | 03:16 | So we are going to say if current_state
not equal to null, that means we already
| | 03:24 | have a state which is visible, and what
we are going to do then is we are going
| | 03:30 | to call the destroy method on the current_state.
| | 03:32 | Let's say we are in the Menu state
currently and we want to switch to the Play state.
| | 03:36 | Well before we switch to the Play state
we first want to destroy the Menu state
| | 03:42 | and we do that by saying current_state.destroy.
| | 03:46 | And here again, why it's important
that all of the states all have that
| | 03:50 | destroy method implemented.
| | 03:52 | And just to make sure that the garbage
collector does its thing, we are going to
| | 03:58 | set current_state here equal to null.
| | 04:01 | So once it's destroyed, we are going
to set it to null and then now at this
| | 04:05 | point we can actually go ahead and reset it
to the new state that we want to switch to.
| | 04:11 | Okay, so with that if statement completed,
now we can create our switch statement.
| | 04:16 | So switch, and we are going to be
switching over that state argument which was
| | 04:21 | sent in, and now we are going to put in
a case statement for each of the three
| | 04:26 | possible states that we can switch to.
| | 04:28 | So we'll say case and the first one is
going to be MENU_STATE, so we say it like
| | 04:34 | that, case MENU_STATE, and if that is
the state that we want to switch to we are
| | 04:40 | going to set current_state equal to a
new instance of the Menu state class.
| | 04:48 | And remember when we created all of our
state classes it's expecting us to send
| | 04:53 | in a reference to this game class.
| | 04:55 | We can do that just by saying this.
| | 04:57 | So if that was the case, we are going to
set that current_state property and then
| | 05:01 | we are simply going to break.
| | 05:05 | Okay, so I am going to copy this code,
this is going to be very similar for the
| | 05:09 | other two cases, and this is one is
going to be the PLAY_STATE and obviously
| | 05:16 | here I am not creating a new instance of menu,
I am creating a new instance of the Play state.
| | 05:22 | I am going to need to make sure that we
actually import that, because again they
| | 05:26 | are in a different package.
| | 05:28 | And lastly, there is going to be the
GAME_OVER_STATE and for this we are going
| | 05:34 | to create a new instance of
the GameOver Class, like that.
| | 05:43 | So now once we go through that
switch statement we'll now have set that
| | 05:46 | current_state property equal to the
correct state class, but what we need to do
| | 05:51 | next is to actually add that
state class to our display list here.
| | 05:55 | So I am going to come underneath the
switch statement and I am going to say
| | 06:00 | addChild(current_state).
| | 06:04 | Now we can't just keep it like this,
because this is of type IState right now,
| | 06:08 | so we need to make sure we cast this to
a Sprite and we are just going to wrap
| | 06:13 | it in a cast statement like this, so
the display list knows that this is
| | 06:18 | actually a valid Sprite class.
| | 06:20 | Okay, so now we have our changeState
function implemented, what we need to do
| | 06:25 | next is when we first come into our movie,
in this init Event Handler here, right
| | 06:32 | before we set the ENTER_FRAME event, we
are going to want to change the initial
| | 06:36 | state to be the Menu state.
| | 06:37 | So we are going to call that
ChangeState method and we are going to pass in
| | 06:43 | MENU_STATE, because remember when we
first launch our game we want to initially
| | 06:47 | go to that MENU_STATE.
| | 06:49 | So now I mentioned when we created
this game class that we have our main Game
| | 06:53 | loop which is this update function,
this is being called on every frame.
| | 06:58 | So all we are going to do in this
update method is to call the update method of
| | 07:03 | our current state, because again,
depending on what state we are in, we are going
| | 07:08 | to be doing different things on every frame.
| | 07:10 | So we are simply going to pass this call
down to whatever state is currently active.
| | 07:14 | So all we have to say here
is current_state.update().
| | 07:22 | Okay, so just to recap again, we've
created our three constants for the three
| | 07:26 | different states and we've created our
changeState method which looks at the
| | 07:32 | integer which is passed in and chooses
the correct state, creates a new instance
| | 07:38 | of it and adds it to the display list.
| | 07:40 | And again, in our main game loop, we
are simply calling the update method of
| | 07:45 | whatever state is currently active.
| | Collapse this transcript |
|
|
4. Preparing and Importing AssetsCreating a static assets class| 00:00 | So now that we have our basic game
structure created, we need to turn our
| | 00:04 | attention to the assets in which
we are going to use in this game.
| | 00:08 | Now if you have access to the exercise
files, if you look in that folder, you
| | 00:11 | will see there's a whole bunch of
different types of assets ranging from
| | 00:15 | animation sequences, like here, we have
this alien animation sequence, we have
| | 00:20 | sound effects, particles, fonts, and
we need a way in which to manage those
| | 00:26 | inside of our game project.
| | 00:28 | So what I'm going to do is inside the
exercise files, I'm going to copy all
| | 00:33 | of those assets to the clipboard and
then go back to my Flash Builder project
| | 00:37 | and I'm going to create a new folder at
the root of my project. So I'm going to
| | 00:42 | right-click, create a New > Folder,
and I'm going to call this folder assets,
| | 00:46 | and then I'm simply going to paste those
assets into that folder so that we have
| | 00:51 | them inside of this assets folder.
| | 00:54 | Now in our project we are going to
create a class that's specific job is to
| | 00:59 | manage our assets for us.
| | 01:01 | So I'm going to go into the core
package and create a New > ActionScript Class
| | 01:06 | and I'm going to call it Assets.
| | 01:07 | And this will be used to embed and
manage the various assets that we are going
| | 01:14 | to have in our game.
| | 01:15 | Now all of those are going to be
static assets, because again, we don't want to
| | 01:19 | instantiate this class and have
different versions of all of these assets.
| | 01:23 | So I'm going to modify the constructor
where I'm actually going to replace it
| | 01:27 | with a public static function called
init and this is going to have a return
| | 01:32 | type of void. We are not
going to be returning anything.
| | 01:36 | Now we are actually going to call this
function in our Game class constructor,
| | 01:40 | because again, the first thing that we
want to do when our Game class is created
| | 01:44 | is to initialize our assets,
so I'm going to say Assets.init.
| | 01:50 | So again, all of our assets are going
to be managed from this Assets class and
| | 01:54 | in the next sequence of movies in
this chapter, I'll show you how you can
| | 01:58 | incorporate different types of assets
and make them available for your game.
| | Collapse this transcript |
| Adding images and creating textures| 00:00 | So the first type of asset that I'm
going to show you how to include is a
| | 00:04 | simple image asset.
| | 00:05 | So in our game we have a background
which consists of some stars, and that's
| | 00:10 | just a simple PNG file. If we look in
our assets folder, it's called sky.png and
| | 00:17 | that's what it looks like.
| | 00:18 | So we're going to want to embed
this so that we can use it in our game.
| | 00:23 | So the way we embed a PNG or any other
type of image asset, and you're used to
| | 00:28 | this if you've been doing Flash for
a while, is to use the Embed Metadata.
| | 00:32 | So we can say Embed and then give a
source property and give it the path to the
| | 00:39 | PNG file that we want to include.
| | 00:41 | Well that's in the assets
folder, and it's called sky.png.
| | 00:46 | And then next we need to give a
class which is going to be used to
| | 00:51 | instantiate that image.
| | 00:53 | So again, we're doing everything as static, but
this is going to be a private static var
| | 01:00 | sky and this is going to be of type Class.
| | 01:04 | Now when we're dealing with images,
we're actually going to be creating textures
| | 01:09 | out of these images, because remember,
when you're running on the GPU using Stage
| | 01:13 | 3D, everything is essentially triangles
and the way in which you display things
| | 01:18 | is to actually put a
texture onto those triangles.
| | 01:23 | Now it's important that we
don't repetitively create textures.
| | 01:27 | So for instance, this sky image we're
going to create a single static texture
| | 01:33 | here in the Assets class and any time we
want to use that, anywhere in our game,
| | 01:37 | we're going to use that single texture
object, because remember everytime you
| | 01:41 | create a texture, it has to upload it
to the GPU and it's also increasing the
| | 01:45 | memory that your game uses.
| | 01:48 | So you want to create the very least
amount of texture as possible and make
| | 01:52 | sure you reuse them.
| | 01:53 | So we're going to create a texture out
of this and this is going to be a public
| | 01:57 | static texture, so that we can
reference it from outside of this class.
| | 02:01 | So we're going to say public static
var and I'm going to call this skyTexture,
| | 02:08 | and this is going to be of
type texture, and the package is
| | 02:13 | starling.textures.Texture.
| | 02:16 | Okay, so now with that created inside
of our init function, we're going to
| | 02:20 | instantiate that texture or create that texture.
| | 02:24 | So I'm going to say skyTexture =, now I
could say new texture here, but there is
| | 02:31 | some helpful static factory methods
on the texture class that we can use.
| | 02:36 | So I'm going to say texture, and
there is a fromBitmap static function
| | 02:41 | available, in this we pass in a bitmap
instance which is going to be used to
| | 02:46 | create the texture, and for that we pass in
a new instance of that sky embedded bitmap.
| | 02:54 | So now after this initialization
function is called from our game, main game
| | 02:58 | constructor function, anytime we need
to display that sky image, we're going to
| | 03:02 | reference this skyTexture.
| | 03:04 | So again, it's only going to be in
memory one time uploaded to the GPU, and
| | 03:09 | anytime we need to use it we're
going to reference that single texture.
| | 03:13 | So again, that's the basics of
incorporating an image file such as a PNG and a
| | 03:18 | JPEG and creating it
into a texture for Starling.
| | Collapse this transcript |
| Creating sprite sheets with TexturePacker| 00:00 | So in the last movie I showed how you
can incorporate images into your game
| | 00:05 | using that Assets class and
embedding the images there.
| | 00:09 | But typically in a game you are going to
have lots of different image files, and
| | 00:14 | the problem with that, if you keep them
all separated, is that everytime your game
| | 00:19 | loads it's going to have to
make multiple network requests.
| | 00:23 | So if this game is embedded on the web,
you don't want every single little image
| | 00:27 | file to have to create a new
network operation to get it.
| | 00:31 | What's better is to pack all of the
graphics in your game into either a single
| | 00:36 | image or sometimes you have too many
and you have to go into, let's say, a second
| | 00:41 | or a third, but packing them all
together into a single image and this gives
| | 00:45 | you numerous benefits.
| | 00:46 | First of all again, you only have to
make one network operation to get the
| | 00:50 | image, and then the other is that
you are not having to upload multiple
| | 00:54 | textures on to the GPU, you essentially
upload, in our case, it's going to be a
| | 01:00 | single image on to the GPU as a
texture and then we can pull the individual
| | 01:05 | pieces of that texture out.
| | 01:07 | Now for the sky image that we did in
the last movie, since it's such a large
| | 01:12 | image we are not going to include
that into a sprite sheet, but all of the
| | 01:17 | other images that we are going to deal with
can be packed together into a single image.
| | 01:21 | So we are going to be using
TexturePacker for this, so go ahead and launch it up.
| | 01:25 | Now when you first see it, it will give
you a message saying you are currently
| | 01:29 | using the free version.
| | 01:30 | I definitely recommend if you are
doing a lot of this type of work to upgrade
| | 01:34 | and buy the license, it's not very expensive.
| | 01:36 | But for our case we are just going
to use the essential version here.
| | 01:40 | And what we need to do first is to
import all of those images that we want to
| | 01:45 | add on to our sprite sheet.
| | 01:47 | So I am going to click this Add
Sprites button here at the top.
| | 01:51 | And what I am going to do is to
navigate to where my Spacer project is, so mine
| | 01:58 | is in Documents > Flash Builder 4.6 >
Spacer and then to that assets folder.
| | 02:04 | And now I need to choose which assets do I
want to actually include on my sprite sheet.
| | 02:10 | So here I have this image sequence of
this alien, this little animated sequence,
| | 02:16 | so I want to include those.
| | 02:17 | I want to include this bullet.png,
which is the bullet that we are going fire
| | 02:22 | out of the ship, this explosion particle,
the hero.png which is our main ship.
| | 02:27 | I am not going to include this font PNG
because we'll get to that later in this chapter.
| | 02:33 | I am going to include the logo, the
playButton, the smoke particle PNG and
| | 02:39 | the tryAgainButton.png.
| | 02:41 | Again, we are not going to include the
sky because that's such a big image, it's
| | 02:45 | just better for us to embed that directly.
| | 02:47 | Now I am going to click Open, and
now you will see all of those various
| | 02:52 | images laid out here.
| | 02:54 | Now we need to do some tweaks to
this so we get the format that we want.
| | 02:59 | The first thing we want to do is to
come down and we want to check off Allow
| | 03:04 | free sizes. That will essentially
create the smallest possible sprite sheet
| | 03:09 | based on the images that we have in it.
| | 03:12 | Now under Layout we want to change the
Layout to Basic and the MaxRect is a more
| | 03:19 | advanced algorithm which actually is
only available if you buy the license.
| | 03:23 | If you use that it will actually tint
one of your frames red, so you can't
| | 03:28 | really use it in a real game.
| | 03:31 | So we are going leave everything down
here at the default, except we are going
| | 03:34 | to uncheck Allow rotation
and we are uncheck Trim.
| | 03:38 | Okay, so we are going to leave
that at its very basics here.
| | 03:42 | But we can see all of the individual
images that are being packed into the
| | 03:46 | sprite sheet, so we have out little
animation sequence, we have our explosion
| | 03:50 | particle, our hero ship, logo,
buttons; all packed together in this nice
| | 03:55 | little sprite sheet.
| | 03:57 | So when we export this or publish it,
it's going to save two things, first it's
| | 04:02 | going to save a PNG, which is going to
be the actual sprite sheet image itself,
| | 04:07 | but then also it's going to export a data file.
| | 04:10 | And this data file is required
because when we tell Starling to, let's say,
| | 04:16 | give me this hero texture, Starling
needs to know the X and the Y and the
| | 04:22 | width and the height of where in this
big sprite sheet that lives, and that's
| | 04:26 | what the data file does.
| | 04:28 | Now if we come under Output here, we
can see there is a lot of different data
| | 04:32 | formats that are supported.
| | 04:34 | The one we are going to use is
a data format called Sparrow.
| | 04:38 | The creator of Starling, Gamua,
actually created an iOS game framework called
| | 04:43 | Sparrow and Starling is
actually based on Sparrow.
| | 04:47 | So it uses the same data format.
| | 04:50 | Now for Data File I am going to click
this, because we want to save that data
| | 04:55 | file into our assets folder.
| | 04:57 | So again, make sure that
you are in the right folder.
| | 05:01 | So I am going to go to Documents > Flash
Builder 4.6 > Spacer > assets, and I am
| | 05:07 | going to call this atlas.
| | 05:10 | And the reason is when we get into
Starling, we are going to be creating what's
| | 05:14 | called a texture atlas.
| | 05:16 | So we are going to call it
atlas here and click Save.
| | 05:19 | And you can see by default
TexturePacker is also going to save that atlas.png
| | 05:25 | file in the same directory,
which is what we want.
| | 05:28 | So now all I am going to do is click
Publish, and now if we go back to Flash
| | 05:32 | Builder, you should see if we
refresh the project here that we have our
| | 05:38 | atlas.png and our atlas.xml.
| | 05:41 | So if I load that up here we can see
our sprite sheet that was exported, and if
| | 05:46 | I look in the XML, let's say I just
open this with the XML Editor here, we can
| | 05:53 | see what has happened here is
this created a texture atlas for us.
| | 05:57 | And essentially when we want to
request a certain texture out of the sprite
| | 06:03 | sheet, this is the name
that we are going to give.
| | 06:05 | So if I want, let's say, the bullet texture,
I am going to be able to reference it
| | 06:10 | using a string of bullet, but you can
see what the structure of it, it's saying
| | 06:14 | the x, the y, the width and the height
of the various positions of the sprites.
| | 06:20 | So with that atlas created, in the
next movie I am going to show you how to
| | 06:24 | create that texture atlas here in Starling.
| | Collapse this transcript |
| Creating the main texture atlas| 00:00 | So now that we've created our main
sprite sheet in TexturePacker, we need to use
| | 00:04 | both the PNG and the XML file to
create a texture atlas, so that we can
| | 00:10 | reference those assets in Starling.
| | 00:11 | So I'm going to come into my asset class
right under where I created or embedded
| | 00:16 | the sky.png and we need to embed both
that atlas.png and also the atlas.xml.
| | 00:24 | So I'm going to start with the PNG. So
Embed source and that is assets/atlas.png
| | 00:34 | and I'm going to create a private static
variable which is going to hold a class
| | 00:39 | variable so we can instantiate that.
| | 00:42 | So it's going to be private static
var and I'm just going to call it atlas.
| | 00:50 | Now when we create our texture atlas,
I want to create that as a public
| | 00:53 | static variable, so that we can actually
reference it from anywhere we want in our game.
| | 00:58 | So I'm going to create another variable
here public static var, and I'm going to
| | 01:04 | call it ta for TextureAtlas, and this
is going to be of type TextureAtlas.
| | 01:10 | So now I need to embed that XML file.
So it's going to be a similar thing, I'm
| | 01:14 | going to say Embed (source="assets/atlas.xml",
but the difference is when we are
| | 01:25 | dealing XML files is we also have to
set the mime type to application octet
| | 01:31 | stream, so let me do that now.
| | 01:34 | mimeType="application/octet-stream")
and now we're going to create a private
| | 01:47 | static variable called atlasXML.
| | 01:54 | So now I have both the PNG and the
XML embedded and I also have that public
| | 01:59 | static variable, which is
going to hold my TextureAtlas.
| | 02:03 | Now I'm going to come down into the
init function and instantiate that. So I'm
| | 02:07 | going to instantiate the ta variable,
is equal new TextureAtlas, and to this
| | 02:14 | we need to pass in the texture that we're going
to create from that PNG, and also the XML file.
| | 02:22 | So we're going to use the Texture.fromBitmap
factory method and we're going pass
| | 02:29 | in a new instance of atlas, because
remember that's the embedded PNG file.
| | 02:34 | Now the next thing we need to pass in
is the XML file. When we instantiate
| | 02:39 | atlasXML we are going to need to cast
it to an XML object, so we are going to
| | 02:44 | cast it like that and pass in a new atlasXML.
| | 02:50 | So let me close that, close that, and close that.
| | 02:54 | So I've now instantiated my TextureAtlas,
and you'll see as we go through the course,
| | 02:59 | I'm going to easily be able to use this
ta variable, and say ta.gettexture and
| | 03:06 | give it a string name for the texture
that I want to retrieve, but again, the
| | 03:10 | main benefit of this is I'm not having
to embed all of these different images
| | 03:15 | separately causing different
network requests, and so on, and so forth.
| | 03:19 | So putting them together into a
TextureAtlas, not only makes it a lot easier
| | 03:23 | as you are building your game, but
also greatly improves the performance of
| | 03:28 | your game.
| | Collapse this transcript |
| Creating and importing bitmap fonts| 00:00 | So when it comes to rendering text in
Starling, you have a couple of different options.
| | 00:05 | First, you can just use regular system
fonts that every user has on their system
| | 00:10 | and this could be Arial or
any of those common fonts.
| | 00:13 | And Starling will actually render that
into a texture and put it on the GPU for you.
| | 00:20 | So this is good if you have text that
isn't going to be changing very often.
| | 00:24 | But in most cases what you are going
to want to do is to create a bitmap font,
| | 00:29 | and this is essentially identical to
the idea of a sprite sheet where you have
| | 00:34 | all of the glyphs for the characters
that you are going to want to use, packed
| | 00:38 | into a single image and then there is
going to be this data file that says for
| | 00:43 | instance, if I want the letter D, it's
going to go to this X and Y in the sprite
| | 00:48 | sheet and pull out the correct area.
| | 00:50 | So when it comes to creating bitmap
fonts, I am going to be showing you how to
| | 00:55 | use a tool called GlyphDesigner,
but that is a Mac only tool.
| | 00:58 | If you are on Windows, there is a tool
called Bitmap Font Generator, which you
| | 01:02 | can get on angelcode.com.
| | 01:04 | This essentially allows you
to do the same type of thing.
| | 01:08 | Now I am only going to be showing you
these tools. I have already gone ahead and
| | 01:13 | created a bitmap font for you which is
in the exercise files, but if you don't
| | 01:17 | have those, you are going to
need to get your own bitmap font.
| | 01:20 | So if we look in GlyphDesigner, you can
see when I first launch it up here it's
| | 01:24 | giving me a default font and here is
essentially the sprite sheet that is
| | 01:28 | going to be created.
| | 01:30 | So I can go through and change it to
whatever font I wanted to create a bitmap
| | 01:36 | font out of. Let me just go to,
let's say, this font right here.
| | 01:41 | Now what I can do is to choose which
characters I need to embed or I want to
| | 01:46 | embed, because again, I don't want to
include a bunch of characters that I am
| | 01:50 | not going to use, because this is going to
make the resulting sprite sheet that much bigger.
| | 01:55 | So I can come down here and under the
Included Glyphs, I can just include the ones I want.
| | 02:00 | So let's say I only want to
include uppercase letters and numbers.
| | 02:05 | So I can get rid of the lowercase, I
can get rid of all the symbols and then
| | 02:09 | click Update and now my sprite sheet
has been updated to just include the
| | 02:14 | characters that I want.
| | 02:16 | Now we can also apply different
Fills to it here, so obviously I can do a
| | 02:20 | Gradient Fill like this. I can change
it to a Solid Fill, I can add an Outline.
| | 02:26 | Now when we are in Starling, you are
going to have the option of using the
| | 02:30 | individual glyph exactly how it looks
which is going to include the Color and
| | 02:34 | the Stroke, or you have the option to
actually color over it with your own color
| | 02:39 | and that's what we are going to be doing.
| | 02:41 | So the actual visual
representation is not that important.
| | 02:44 | Now if we go up to the top here you can
see we have our Texture Atlas and then
| | 02:49 | we also have a Glyph Info panel which
tells us the various IDs and positions of
| | 02:56 | the actual characters that
are going to be embedded.
| | 02:59 | So now, let's say, we are ready to
export this, what we can do is to click the
| | 03:04 | Export button, and you'll notice that
by default this tool will only export a
| | 03:09 | font if you have the registered version.
| | 03:11 | And again, GlyphDesigner is not a
free tool, you can download it, you can
| | 03:16 | experiment with it, but you are not actually
going to be able to export your bitmap fonts.
| | 03:21 | So that's essentially how that tool works.
| | 03:24 | Now like I mentioned, I have included
a bitmap font that we are going to be
| | 03:28 | using in the exercise files, and if you
go into your assets folder, you'll see
| | 03:32 | this komika.png and komika.fnt.
| | 03:37 | So if we look at the png, here is the
font sprite sheet that I exported from
| | 03:42 | GlyphDesigner and I have only included
the uppercase letters, the numbers and a
| | 03:47 | few different symbols that we might want to use.
| | 03:50 | So very similar to the sprite
sheet that we created in TexturePacker.
| | 03:53 | There is also an XML file and
this has an extension of fnt.
| | 03:57 | You can see it's a similar type of thing
where we have an XML file which tells us
| | 04:03 | the position of each of the
characters in the sprite sheet.
| | 04:08 | And when we want to reference this font
from within Starling, we are going to be
| | 04:12 | referencing it within this face name.
| | 04:15 | So I am going to copy that string
to the clipboard, so we have it.
| | 04:19 | Now I need to set that font up in my
assets class, so that we are able to use it
| | 04:24 | throughout our project.
| | 04:25 | So very similar to what we did for the
TextureAtlas, I am going to need to embed
| | 04:30 | both the PNG and the XML file.
| | 04:34 | So I am going to copy this one here
from the TextureAtlas and paste it, and
| | 04:39 | this one is going to be komika.png and
for the Class name we are actually going
| | 04:46 | to call it komika.
| | 04:49 | And the next thing I need to do is to
embed the XML file, so we'll also copy that
| | 04:54 | embed statement from our TextureAtlas
and remember this is not called .xml, this
| | 05:01 | is called komika.fnt.
| | 05:03 | And again, we need the application
octet-stream mimeType and we are going to
| | 05:10 | name this Class komikaXML.
| | 05:14 | Okay, so now we have embedded both
the PNG and the XML, now we need to
| | 05:19 | actually register this bitmap font
with Starling so that we can use it
| | 05:24 | anywhere in our game.
| | 05:26 | So I am going to come under here
where we created our TextureAtlas. Now to
| | 05:29 | register this font, we are actually going to
use a static method of the TextField Class.
| | 05:36 | So I am going to say TextField and when
we import this, again, remember to use
| | 05:41 | starling.text.TextField.
| | 05:44 | And there is a static method on
there called registerBitmapFont.
| | 05:49 | And to this, we first need to pass in an
instance of the BitmapFont class, so we
| | 05:55 | are just going to do it right in line here,
I going to say new BitmapFont and to the
| | 06:02 | constructor of the BitmapFont, very
similar to the TextureAtlas, we need to pass
| | 06:05 | in a texture object in our XML.
| | 06:09 | So I am going to create a texture using
texture.fromBitmap method and pass in a
| | 06:16 | new komika like that.
| | 06:18 | Because again, that's our embedded image.
| | 06:21 | And next I need to pass in that XML file,
again, I am going to need to cast it
| | 06:27 | to XML and then pass in a
new komika XML instance.
| | 06:33 | And that's all it takes to
register a bitmap font with the system.
| | 06:37 | So again, now that we've done that,
anywhere in our movie where we create a
| | 06:41 | TextField we can say use the
komika access font that was embedded.
| | 06:47 | So that's the general workflow of
including bitmap fonts into Starling.
| | Collapse this transcript |
|
|
5. The Menu StateCreating the Background class| 00:00 | So in this chapter we're going
to be building our Menu state.
| | 00:04 | Again, this is the first state that actually
you get into when you first launch the game.
| | 00:08 | It's a menu that has the star background,
and it has the logo and the Play button.
| | 00:13 | What we first need to do is to create
a class called Background, and this is
| | 00:18 | going to hold that stars image and it's
actually going to scroll it, so we have
| | 00:23 | an animated star background.
| | 00:25 | So I'm going to go to my main
source folder, right-click, create a
| | 00:29 | new ActionScript Class.
| | 00:31 | And for the different objects of
our game, we're going to put it in a
| | 00:35 | Package called objects.
| | 00:36 | And the name of this Class is going to
be Background and the Superclass is going
| | 00:42 | to be starling.display.Sprite.
| | 00:45 | So now in order to achieve the
scrolling effect, we're going to need two copies
| | 00:51 | of that sky texture that we're
going to be scrolling and moving.
| | 00:55 | So in the constructor here I'm going to
create a couple of instance properties,
| | 01:00 | and I'm going to call it sky1 and that's
going to be equal to a new image object
| | 01:07 | and this is starling.display.image.
| | 01:10 | And this is the display object
that allows you to map a texture onto,
| | 01:15 | essentially, two triangles, so
we have a very light weight image.
| | 01:21 | Now to the constructor of the image
object we need to pass in what texture do
| | 01:26 | we want to use for this image, but we
already created that texture in our assets class.
| | 01:33 | So I'm going to say Assets.skyTexture,
and now I'm going to do a quick fix to
| | 01:39 | create that as an instance variable at the top.
| | 01:43 | And as soon as I create it, I'm
essentially going to add that to the display list.
| | 01:48 | So I'm going to say addChild(sky1).
| | 01:52 | So I'm going to copy those two lines,
come down, paste in another one,
| | 01:57 | because we're going to create another image, and
let's also create that as an instance variable.
| | 02:04 | And I want to add sky2 to the
display list, and now I'm going to want to
| | 02:10 | position this one off the screen to the top,
so that it is lined up right behind sky1.
| | 02:15 | So to do that, I'm going to
say sky2.y is equal to -800.
| | 02:23 | So it's going to position it above sky1.
| | 02:26 | Okay, so now what we need is a method which is
going to update the position of these images.
| | 02:33 | And we're going to call this
function from our Menu state.
| | 02:38 | So we're going to create a public
function, we're going to call it update,
| | 02:43 | I'm not going to be returning anything, and
this is going to handle moving that background.
| | 02:49 | So what we're going to do is for each
of the images, we're going to increment
| | 02:53 | its y position by 4 pixels, so
I'm going to say sky1.y += 4.
| | 03:01 | Now what I need to do is to test
whether this image is actually off of the
| | 03:05 | screen, like down below the screen, and
if it is, I need to move it back to the
| | 03:09 | top into position to animate again.
| | 03:12 | So I'm going to do an if statement, if(
sky1.y = 800), then I'm going to set its
| | 03:21 | y position sky1.y = to -800 and that
way it's ready to start animating again.
| | 03:31 | And now we're also going to increment the
sky2.y position by the same amount, so += 4;
| | 03:39 | and now we need to do that same check
to see if its actually off the screen.
| | 03:44 | So we're going to say if(sky2.y == 800);
| | 03:50 | if this is not a perfectly divisible
number you could actually do, if(sky2.y > 800);
| | 03:56 | but for our cases we can just check for
whether it's equal to 800 and if it is,
| | 04:02 | again, we're going to say sky2.y = -800.
| | 04:08 | So again, if we call this update
method repetitively, it's essentially now
| | 04:12 | going to animate our sky.
| | 04:15 | So let's go back to our Menu state
and what I'm going to do is in the
| | 04:20 | init function of our Menu state,
I'm going to create a new instance of
| | 04:23 | that Background class.
| | 04:24 | And I'm going to call it
background = new Background();
| | 04:30 | and again I want to create this as an
instance variable at the top, and we want
| | 04:34 | to add that background to
the display list of our menu.
| | 04:39 | So addChild(background);
| | 04:42 | Now remember our update function for
our menu is going to be called on every
| | 04:48 | frame, because that's being
funneled down from our main Game class.
| | 04:52 | So what I want to do in this update method is
to call the update method of our background.
| | 04:57 | So we're going to say background.update();
| | 05:01 | Okay, so now we're going to run
our project for the first time.
| | 05:05 | Now if you get an error when you first
try to run your project, just go ahead
| | 05:08 | and open up that Spacer file, because
remember we changed the package that it
| | 05:13 | was in, so just go ahead now and
debug your project and you can see when it
| | 05:17 | launches, we have our nice
scrolling background here.
| | 05:21 | Now one of the things I wanted to point
out when you're using Starling is when
| | 05:25 | you test your movie, or your game and debug
it, the performance can often be pretty
| | 05:30 | poor compared to what it's going to
be when you export a release build.
| | 05:35 | So if you're seeing stuttering
here, this is a debug version.
| | 05:39 | If you want to see the real performance
of your game, you are going to want to
| | 05:43 | actually export a release build of it and
we'll do that towards the end of this course.
| | 05:48 | But now you should see you Menu
state up and we have that nice seamless
| | 05:52 | scrolling stars background.
| | Collapse this transcript |
| Adding the logo| 00:00 | So now that we have our animated
background in our menu state, the next thing
| | 00:04 | we're going to add is the logo for our game.
| | 00:08 | And if you look in the assets folder,
remember that's in our Texture Atlas that
| | 00:12 | we created, it is this logo right here.
| | 00:14 | So now we're going to look at how
you can extract this specific texture
| | 00:18 | from that Texture Atlas.
| | 00:20 | Okay, so I'm going to come under where
we created our background, and I'm going
| | 00:23 | to create a variable, I'm going to call it
logo, and that's going to be equal to new Image.
| | 00:31 | And remember that when we want to
extract a certain texture from the Texture
| | 00:36 | Atlas, we're going to use that
Texture Atlas that we created in our assets
| | 00:39 | class, so I'm going to say Assets.ta,
which is our Texture Atlas.
| | 00:45 | Now there's two different methods that
we can use, first is get texture, that's
| | 00:49 | going to return a single texture.
| | 00:51 | If we have an animation which is a
series of frames, we would use getTextures
| | 00:55 | and we will look at that later in the course.
| | 00:58 | But for our purposes right now we're
going to use the getTexture method and pass
| | 01:03 | in the texture name which we
want to get and it's called logo.
| | 01:06 | And if you don't remember what
these names are, you can look in the
| | 01:10 | atlas.xml file to see.
| | 01:11 | So I'm going to create that as an
instance variable, and what I'm going to do is
| | 01:17 | to set its pivotX point.
| | 01:20 | So much like in Flash where we can
create a movie, we can give it a registration
| | 01:24 | point and that's where
the zero zero position is.
| | 01:27 | And by default in Starling, it's going to be
the upper left-hand corner just like Flash.
| | 01:32 | If we wanted to put what is essentially
the registration or the pivot point in
| | 01:37 | the center, we can set its
pivotX or pivotY properties.
| | 01:41 | I'm going to say logo.pivotX, and I'm
going to set that = logo.width * 0.5;
| | 01:54 | that's essentially going to put the pivotX
point directly in the center of our logo.
| | 01:59 | And this way, it's easy for me to
position it in the center of our Menu state.
| | 02:04 | So now to position the X position,
I'm going to say logo.X = 400;
| | 02:11 | because remember our game is 800 pixels wide.
| | 02:14 | For the Y position, and this is
something you just have to do through trial and
| | 02:19 | error is setting it at 250.
| | 02:22 | And then lastly, I'm going to add that
logo to our display list for our menu.
| | 02:30 | So I'm going to test that, see what
it looks like, and you can see now when
| | 02:34 | we come in to our movie, we have
our logo which is placed on top of our
| | 02:39 | scrolling sky background.
| | 02:41 | So that's basically how easy it is
once you've created your Texture Atlas to
| | 02:46 | get a specific texture.
| | 02:47 | It's just to simply give it its
string name, it will retrieve that
| | 02:51 | specific piece of our texture so
that you can use it to display inside of
| | 02:56 | an image object.
| | Collapse this transcript |
| Adding the play button| 00:00 | So the next thing we need to add to
our menu state is our Play button, and
| | 00:04 | this is obviously what you're going
to click on when you want to actually
| | 00:07 | start playing the game.
| | 00:09 | So Starling actually has a class
called Button which makes it very easy
| | 00:13 | obviously to create buttons.
| | 00:14 | So I'm going to come under our logo here,
create a new variable called play, I'm
| | 00:19 | going to set that equal to a new
instance of the Starling.display.button class.
| | 00:26 | Into this you can pass in different
textures for the up and the down states,
| | 00:31 | we're not going to deal with that, we're
just going to do an up state to keep it simple.
| | 00:36 | And for the texture, again, we're going to
use a texture which is in that texture atlas.
| | 00:41 | So Assets.ta.getTexture and the
texture is called "playButton", and let's go
| | 00:50 | ahead and create that
playButton as an instance variable.
| | 00:55 | Now when we're dealing with buttons
there is a special event in Starling called
| | 01:00 | a triggered event and that's essentially going
to be fired whenever you click on the button.
| | 01:04 | So let's listen for that now, so play.
addEventListener (Event, and again make
| | 01:10 | sure you're using Starling.events and
it's Event.TRIGGERED, and we'll have it
| | 01:17 | call a method called onPlay.
| | 01:19 | So go ahead and create that method now,
and the only thing you have to do is to
| | 01:25 | come in and put in that event object.
| | 01:28 | Now we need to position the play
button, so it's in the right location.
| | 01:32 | And much like I did before for the
logo we're going to first set its pivot
| | 01:36 | point, so we are going to say
play.pivotX = play.width * 0.5;
| | 01:46 | and we'll position it on the X axis in
the center of our game, so play.X = 400,
| | 01:54 | play.y is going to be equal to 450.
| | 01:59 | And lastly let's add that
Play button to the display list.
| | 02:04 | So now when the button is clicked on,
this is where we're going to actually
| | 02:08 | change the state of our game.
| | 02:09 | So we're going to call back out to our
main Game class, called the changeState
| | 02:14 | method and change the state to the play state.
| | 02:18 | So in our onPlay method here, we're
going to say game, then we're going to
| | 02:22 | call the changeState method, and we're
going to use that constant of the game
| | 02:27 | class called PLAY_STATE. Let's save it.
| | 02:30 | And let's go ahead and test it now.
| | 02:33 | So we have it launched and we can see we
have our image and we have our Play button.
| | 02:39 | So again, now when we press this PLAY
GAME button it's essentially going to go
| | 02:44 | out and change the state, but we
haven't put any visuals yet on the Play State
| | 02:50 | so when I click it, you can see we
don't see anything that's because first of
| | 02:54 | all we haven't destroyed the menu state.
| | 02:56 | And then we also don't have any visuals
yet in the actual play state, and that's
| | 03:01 | what we're going to do in the next movie.
| | Collapse this transcript |
| Implementing the destroy method| 00:00 | So now we have our menu
state essentially completed.
| | 00:03 | The last thing we have to do is
remember that for each state when we change the
| | 00:08 | state it's first going to call this
destroy method, so that our state can
| | 00:12 | actually clean up itself, because again,
we want to remove all of the things from
| | 00:17 | the display list, because we don't want
to be taking up memory while a different
| | 00:21 | state is happening. So let's
fill in this destroy method now.
| | 00:25 | So there's some nice helpful methods
that are in Starling that are not in the
| | 00:29 | traditional Flash display list API.
| | 00:32 | And one of them is a
method called removeFromParent.
| | 00:35 | So the first thing I'm going to do is
to remove the background, so I can say
| | 00:40 | background, and then call the
removeFromParent method, and I can pass in true if
| | 00:46 | I want it to also be disposed, and that
will do things like unregister any event
| | 00:52 | listeners that have been registered,
so we're going to pass in true there.
| | 00:57 | And now to make sure we totally clean up,
I'm also now going to set background = null.
| | 01:04 | So we're going to do the same thing for
the logo, so logo.removeFromParent, put
| | 01:10 | in true, because we want to
dispose it, and let's set logo = null.
| | 01:15 | And lastly let's do the play button,
so we'll do play.removeFromParent(true);
| | 01:24 | and we'll also set it to null.
| | 01:27 | When we change the state to the play
state, the first thing that's going to
| | 01:32 | happen is this destroy method will be called
and we can actually dispose of it properly.
| | 01:37 | Now the last thing we need to do is to
get rid of the menu state itself, remove
| | 01:41 | itself from the game's display list,
and here we can use the removeFromParent
| | 01:46 | method and pass in true.
| | 01:49 | So this is a really handy method to be
able to have in order to help you easily
| | 01:53 | manipulate the display list.
| | 01:56 | Let's go ahead and test it now. We can
see it's launched up, and when I click
| | 02:01 | PLAY GAME, everything has
disappeared, because again the menu state has
| | 02:06 | removed itself, but remember now the play
state doesn't have any visuals on it whatsoever.
| | 02:12 | So in the next chapter we're going to
be building out that play state, which is
| | 02:16 | going to contain all of our actual game play.
| | Collapse this transcript |
|
|
6. The Play StateAdding the background| 00:00 | So the first thing we're going to do in
our play state, very similar to what we
| | 00:03 | did in the menu state, is to add
that scrolling background to it.
| | 00:08 | So the same way I did in the menu state,
I'm going to come into the init event
| | 00:12 | handler and I'm going to create a
variable called background, that's going to be
| | 00:16 | equal new Background;
| | 00:19 | and we're going to want to create that
as an instance variable, and we want to
| | 00:24 | add that background to our display list.
| | 00:29 | And again, in the update method for our
play state which will be called on every
| | 00:34 | frame, we're going to go
ahead and update that background.
| | 00:38 | So background.update, and we can save
that and let's go ahead and test it.
| | 00:45 | So again when we first come into the game,
we're in our menu state and then when
| | 00:50 | I click PLAY GAME we're now essentially
in the play state for our game, but it
| | 00:55 | has that similar scrolling
background associated with it.
| | 00:59 | So again, that's the
first part of our play state.
| | Collapse this transcript |
| Creating the Hero class| 00:00 | So now that we have our scrolling
background in our play state, the next thing
| | 00:04 | we're going to create is our actual
hero, and this is the fighter that's
| | 00:09 | actually going to be firing
bullets at all of the aliens.
| | 00:13 | So what we're going to do is in our
objects package, we're going to create a new
| | 00:17 | ActionScript Class, and we're going to
call it Hero, and this for a Superclass
| | 00:22 | is going to be starling.display.Sprite.
| | 00:28 | And what we're going to need to do is
when we create this hero, we're going to
| | 00:33 | pass in a reference to our play state here,
so that we can actually call back to it.
| | 00:39 | So I'm going to put in a argument here
called play, and this is going to be of
| | 00:44 | type Play, so it's in from our states.
| | 00:49 | And now I'm going to create an instance
variable to hold that, so I'm going to
| | 00:53 | say this.play = play;
| | 00:58 | and we'll create that as an instance variable.
| | 01:01 | Okay, so now for the visual
representation of our hero, we're going to be using
| | 01:06 | a texture which is
actually in our texture atlas.
| | 01:10 | So I'm going to come down here, I'm
going to create a new variable. I'm just
| | 01:14 | going to call it img for image,
and it's going to be of type
| | 01:17 | starling.display.image = new Image,
and now we're going to grab a texture
| | 01:23 | from our texture atlas, so it's
going to be Assets.ta.getTexture, and the
| | 01:32 | texture name is hero.
| | 01:36 | Now we're going to set
the pivotX and the pivotY.
| | 01:39 | For all of the objects that are in our
game, we're going to set its pivot point
| | 01:43 | directly in the center of the visual
representation, and that's going to make it
| | 01:48 | a lot easier for us as we're
doing this like collision detection.
| | 01:51 | So I'm going to say img.pivotX = img.width *
0.5, and now we'll do the same
| | 02:02 | thing for the pivotY = img.height * 0.5.
| | 02:10 | And lastly let's go ahead and
add that to the display list here.
| | 02:15 | So now when we're actually moving our
hero around, we're going to be doing it
| | 02:20 | with the mouse, based on the mouse position.
| | 02:24 | Now the Starling framework does not
have mouse events built in, it was actually
| | 02:29 | first designed with mobile in mind,
so it actually uses touch events.
| | 02:35 | Now that's good if your game or your
application is taking advantage of things
| | 02:39 | like multitouch, but if you're not
taking advantage of multitouch, it's better
| | 02:44 | to reach out to your main Flash stage
and get the mouse position that way.
| | 02:50 | So I prefer to use mouse events, unless
I have to use the touch events which are
| | 02:55 | in Starling, because there is
more overhead associated with those.
| | 02:59 | So for updating my hero's position, I'm
going to create a public function called
| | 03:05 | update, and you'll notice the theme
here that all of the game objects are going
| | 03:09 | to have an update function with which
can be called to obviously update its
| | 03:14 | position or any other
characteristics of the object.
| | 03:18 | So inside of this update method, what
I'm going to do is I'm going to ease the
| | 03:22 | position of my hero to the current
mouse position, and I'm going to do it using
| | 03:28 | typical Flash easing code.
| | 03:30 | So I'm going to increment a certain
amount to the X position of my hero, and
| | 03:36 | what I need to do is to
first get the mouse position.
| | 03:39 | So here's where I'm going to need to
reach out to the native Flash stage, and
| | 03:44 | to do that I'm going to go the
Starling method, you'll need to import that,
| | 03:48 | it's in starling.core.
| | 03:50 | Then you want to go to current.nativeStage,
and now that gives you a reference
| | 03:56 | to the native Flash stage, so you've now
reached out back into the regular Flash
| | 04:01 | display list world, and from there,
I can retrieve the mouseX property.
| | 04:08 | In order to ease to that, I'm going
to subtract the current X position from
| | 04:12 | that, and that's going to give me the
distance that needs to be traveled towards
| | 04:17 | the target, but I'm going to multiply
that by 0.3, so then it's essentially
| | 04:23 | going to ease to that position.
| | 04:24 | Now I'm going to duplicate that line,
because this is going to be same thing
| | 04:29 | for the Y position.
| | 04:30 | I'm obviously going to be using the mouseY
property, and I want to ease to the Y property there.
| | 04:37 | So this is the update function again,
and we're going to be calling that on
| | 04:42 | every frame from the play state.
| | 04:44 | So let's go back to our play state,
and let's create our hero now.
| | 04:48 | So I'm going to come under here under
the background, create a new variable
| | 04:52 | called hero, and I'm going to
instantiate a new hero object.
| | 04:57 | And remember, we're passing in a
reference to this play state, so I'm going to
| | 05:02 | pass in this, create this as an
instance variable, and now we want to add that
| | 05:07 | hero to our display list.
| | 05:10 | And now lastly in the update method of
our play state, after we call an update
| | 05:15 | on the background, let's call an
update on our hero, because again we created
| | 05:21 | that public update method.
| | 05:22 | Let me save that now and
let's go ahead and test it.
| | 05:25 | So we have our main menu state, I'm
going to click on the PLAY GAME button. We
| | 05:30 | now have our ship, and it's
easing towards the mouse position.
| | 05:34 | So you can see if I move my mouse
really quickly it's not just sticking to the
| | 05:39 | mouse cursor, it actually has a nice
subtle easing effect, which just makes
| | 05:43 | everything feel a little bit smoother.
| | 05:45 | When we get later on in this course,
we're actually going to add a smoke
| | 05:49 | particle effect so it looks like there
is exhaust coming out of this plane, but
| | 05:53 | we're going to do that later on.
| | 05:55 | So that's all it took to create our hero.
| | 05:58 | Again, the main theme is that for any
game objects we're going to have a public
| | 06:02 | update function that you're going to be
able to call from your state to update
| | 06:07 | its position, to check for collisions,
and different types of things that
| | 06:11 | happened in our game.
| | Collapse this transcript |
| Creating the Bullet class| 00:00 | So now that we have our hero created,
the next thing we are going to want to do
| | 00:05 | with it is to be able to fire bullets.
| | 00:07 | So the first thing we have to do is to
create a Bullet class, and again, we are
| | 00:10 | going to do it in our objects package,
so I'm going to create a new ActionScript
| | 00:13 | Class. It's going to be called Bullet.
| | 00:17 | And again, the Superclass is
going to be starling.display.Sprite.
| | 00:21 | So this one is going to be pretty
simple, all we need to do is to get that
| | 00:25 | texture out of our Texture Atlas
and feed it to an image object.
| | 00:28 | So we are going to say var img, it's
going to be of type image, it's equal to
| | 00:34 | new Image, and let's reach out and grab
that texture so it's in the Assets class
| | 00:40 | to our ta, which is our Texture Atlas,
call the getTexture method and pass in
| | 00:46 | the string name for the texture which is bullet.
| | 00:50 | And let's set its pivotX and pivotY properties.
| | 00:53 | So we want to do pivotX = img.width * 0.5,
and set pivotY = img.height * 0.5,
| | 01:15 | and then lastly we will add
this image to this play list.
| | 01:21 | So now the Bullet class itself is not
going to have an update method, and the
| | 01:25 | reason is, we are going to create a
bullet manager class, and this bullet
| | 01:29 | manager is going to handle and keep
track of all of our bullets, and it's going
| | 01:33 | to handle animating the bullets,
destroying the bullets and things like that.
| | 01:37 | So for the actual Bullet class
itself, it's simply just a visual
| | 01:41 | representation of the bullet.
| | Collapse this transcript |
| Creating the BulletManager class| 00:00 | So we now have a bullet game object.
| | 00:03 | But there's going to be a lot of
bullets that are going to be flying around, so
| | 00:07 | in order to keep track of them and to
handle the updating and destroying we're
| | 00:11 | going to create a BulletManager class,
and this is the first of a series of
| | 00:15 | manager classes that we're going to be
creating to manage different objects.
| | 00:19 | So I'm going to right-click on my
main source folder and create a new
| | 00:23 | ActionScript Class, and I'm going
to create a package for these manager
| | 00:27 | classes and I'm going to call it
managers, and then I'm going to create a new
| | 00:32 | BulletManager class, and this doesn't
have any Superclass or interfaces involved.
| | 00:38 | So I'll click Finish, and now I'm
going to stub out this manager class.
| | 00:42 | So the first thing I'm going to do when
I create a BulletManager is to send in a
| | 00:46 | reference to our main play state, so I
need an argument here to catch it. I'm
| | 00:51 | going to call it play, and
this is going to be of type Play.
| | 00:55 | So let's create an instance variable
to store that, so this.play = play;
| | 01:01 | and create it as an
instance variable at the top.
| | 01:05 | What I'm going to need to create is
an array, and this array is essentially
| | 01:10 | going to keep track of all of the
active bullets that are currently in my game.
| | 01:15 | And what I'm going to do is to be able
to loop through that array and update all
| | 01:19 | of the positions of the active bullets.
| | 01:21 | So I'm going to come onto here and
create a new variable called bullets, and
| | 01:26 | that's going to be equal to a new Array.
| | 01:30 | Now ActionScript 3 does have a vector
class, which is essentially a typed array,
| | 01:37 | but the thing is, currently at least
in the current public Flash player, it's
| | 01:41 | actually faster sometimes to use
arrays, particularly when you're going to
| | 01:45 | mobile, so for our case right here
we're just going to use a regular array.
| | 01:49 | Now I'm going to create that bullets
array as an instance variable at the top.
| | 01:55 | So now I'm going to need to create a series
of methods that I'm going to want to call.
| | 02:00 | So the first thing I'm going to want
is a public function called update, and
| | 02:05 | this is going to be called from our play state.
| | 02:07 | So on every frame we're going to
call this bulletmanager.update.
| | 02:11 | So let's say public function update,
and again this is going to do things like
| | 02:18 | updating the position of all of our
bullets, determining when we need to fire a
| | 02:23 | bullet and also when we
need to destroy a bullet.
| | 02:26 | So with that update method created, the
next thing I'm going to do is to create
| | 02:31 | a function called fire, and this is a
function that's going to be called from
| | 02:35 | our update method which is essentially
going to fire a new bullet. So this can
| | 02:39 | be private, so private function fire,
it's not going to return anything.
| | 02:45 | Now the next thing we're going to want
to create is a method which allows us
| | 02:50 | to destroy a bullet.
| | 02:52 | So let's say in our collision detection
which we'll get to later, it turns out
| | 02:56 | that a bullet has hit an alien.
| | 02:58 | Well in that case we want to destroy
the bullet, we want to remove it from the
| | 03:02 | screen, we want to remove it from our
bullets:Array and when we actually get to
| | 03:07 | looking at object pools, we are going to
want to return that to the object pool,
| | 03:11 | so it's available for the next time.
| | 03:13 | So we're going to create this as a
public function destroyBullet, and to this
| | 03:20 | we're actually going to be passing in a
bullet object which we want to destroy.
| | 03:24 | So I'm going to catch it with an
argument called b, and this is going to be of
| | 03:29 | type Bullet, we're going to
fill in these methods later.
| | 03:34 | And the last function I'm going to want
to create is a destroy function, which
| | 03:39 | we're going to be able to call from
our play state, so when it comes time to
| | 03:43 | switch to the game over state, we're
going to be able to call this destroy
| | 03:47 | method and make sure we clean up
after ourselves and remove all of these
| | 03:51 | things from memory.
| | 03:52 | So we're going to create a public
function called destroy, and we're going to be
| | 03:59 | creating other managers, so for
instance, we're going to be creating an Alien
| | 04:02 | Manager we're also going to be
creating a CollisionManager, and they are all
| | 04:06 | going to take this same basic approach,
and that they're all going to have an
| | 04:09 | update method which we can
call from our play state.
| | 04:13 | We're going to be able to also clean up
and destroy the manager and all of its
| | 04:18 | accompanying objects when we want
to change to the game over state.
| | Collapse this transcript |
| Using the StarlingPool class| 00:00 | So now in our BulletManager class we
need to actually handle the creation and
| | 00:05 | destruction of bullets and this is a
time to talk about a very important concept
| | 00:10 | for games and that's object pooling.
| | 00:12 | So one of the things that's most
expensive performance-wise in games or
| | 00:16 | any application is when you instantiate a
new object, because there is a lot of overhead.
| | 00:22 | So let's say in a game where I am
constantly firing bullets like this one, every
| | 00:26 | time I fire a bullet I don't want to
create a new bullet using the new keyword
| | 00:30 | and then when it's off the screen I destroy it.
| | 00:33 | That repetitive process causes a lot of
stuttering in your game and it's just a bad practice.
| | 00:40 | So this is where you want to use an
object pool where at the beginning of
| | 00:44 | your game you create a pool of, in our
case, we are going to create 100 bullets
| | 00:48 | in memory right at the beginning of our
game and then we are just going to use
| | 00:53 | those bullets that are already in
memory and just reuse them and that's
| | 00:57 | definitely the approach to take.
| | 00:59 | So back earlier in the course we
actually linked to a class that I created
| | 01:04 | called StarlingPool and let's
look at that really quickly.
| | 01:07 | This is a simple class that essentially
allows you to, when you instantiate it,
| | 01:12 | send in a type and this is a class of
what type of object you want to create for
| | 01:17 | the pool and then a length of how many
objects you want to create for the pool.
| | 01:23 | It has three public methods available.
| | 01:26 | First is something called getSprite and
this when you want a new object from the pool.
| | 01:32 | So let's say when it comes time to fire
a bullet I am going to call getSprite.
| | 01:37 | Now if you go beyond, let's say, if I
create 100 bullets and there is more than
| | 01:42 | 100 bullets being requested it's
going to throw an error, so that's where you
| | 01:45 | need to make sure that you are
instantiating enough bullets for your game.
| | 01:51 | Now when you are done with the bullet,
let's say, when it goes off the top of the
| | 01:55 | screen, I return it to the pool
using this returnSprite method.
| | 02:00 | And lastly, we can also destroy all of
the items by calling the destroy method.
| | 02:06 | So that's what we are going
to use in our BulletManager.
| | 02:10 | So what I am going to do is under
where we create a new array, we are actually
| | 02:15 | going to instantiate a new variable.
| | 02:18 | I am going to call it pool and that's
going to be equal to new StarlingPool.
| | 02:26 | Now the constructor for the class type,
we want to send in bullet, because
| | 02:31 | remember we want to actually create a pool of
bullet objects and I am going to pass in 100.
| | 02:37 | So we want to instantiate 100 bullet
objects for us to use, because the ship
| | 02:42 | is going to be firing pretty rapidly.
| | 02:44 | You aren't going to want to
trial and error with those numbers.
| | 02:47 | Obviously, you want to use the least
amount as you can, because it's going to
| | 02:51 | take up less memory.
| | 02:52 | So I am going to create that pool
variable as an instance variable at the top
| | 02:56 | and now what I am going to do is
go in and fill in this fire method.
| | 03:01 | Again, this is going to be called
when we want to fire a new bullet.
| | 03:04 | But in our game we actually have
guns on either side, on either wing.
| | 03:10 | So whenever we fire, we are
actually going to be firing two bullets.
| | 03:14 | So let's go ahead and implement this method now.
| | 03:16 | So I am going to create a new reference here.
| | 03:18 | I am going to call it b, and
this is going to be of type Bullet.
| | 03:23 | Now if I wasn't using an object pool
this is where I would say new bullet, but
| | 03:28 | this is again is what you want to do.
| | 03:30 | What we want to do is to pull one
of those bullets out of the pool.
| | 03:34 | So I am going to say pool.getSprite.
| | 03:38 | Now the type for inside of the
StarlingPool class is actually DisplayObject.
| | 03:43 | So I am just going to cast it to a bullet.
| | 03:46 | So I am going to say as Bullet.
| | 03:48 | What we want to do now is to add this
bullet to the display list of our play
| | 03:52 | state and that's why we got a
reference to our play state here.
| | 03:56 | So I am going to say play.addChild(b).
| | 04:02 | Now we want to position the
bullet in the right location.
| | 04:05 | So we are going to say b.x = play.hero.
| | 04:13 | Now you'll notice by default when we
created it, it created hero as a private property.
| | 04:19 | So what we are going to do is to go
back to our play state and make sure that
| | 04:24 | that hero property is actually set to
public so we can see it from our BulletManager.
| | 04:29 | And now we can say play.hero.x. But we
want to move it a little bit, because
| | 04:36 | again, we don't want to do it in the
center of the ship for this one, we want to
| | 04:40 | do it on to the left of the wing.
| | 04:41 | So we'll actually say -10 here.
| | 04:44 | And now we'll set the Y position of the bullet.
| | 04:47 | So b.y = play.hero.y and we actually
want to push it back a little bit on the Y axis.
| | 04:57 | So we are going to say -15 just so
it's positioned where it should be.
| | 05:03 | So now let's go ahead and copy this
block, because again, we are going to be
| | 05:07 | creating two bullets every time we fire.
| | 05:09 | So I'll paste this in and I am just
going to reuse this b reference here.
| | 05:13 | So we are going to get
another bullet from the pool.
| | 05:16 | We are going to add it to the display
list of our play state and we are going to
| | 05:21 | set it X and Y. Now for this one
obviously we are going to want to put the X
| | 05:23 | position at +10, so it's on the other wing.
| | 05:28 | Now the one last thing that we need to
do is we need to add these bullets into
| | 05:32 | our bullets array, because again, as
soon as we fire, these things are active
| | 05:37 | bullets in our game.
| | 05:39 | So I am going to come under each of
these and push it into that bullets array.
| | 05:44 | So I am going to say bullets.push(b)
and then we'll do the same thing down
| | 05:50 | below bullets.push(b).
| | 05:57 | So now when our fire method is called,
again we are going to be creating two
| | 06:01 | individual bullets, adding them to
the display list of our play state,
| | 06:05 | positioning them, and also adding them
into our bullets array so that we can
| | 06:10 | update them on every frame.
| | 06:12 | So now we want to turn our
attention to our update method.
| | 06:15 | Again, we are going to be calling
this BulletManager update method on every
| | 06:19 | frame from our play state.
| | 06:22 | So what we are going to want to do is
to loop through our bullets array and
| | 06:26 | update all the positions of the active bullets.
| | 06:28 | So I am first going to come in here
and I am just going to create a local
| | 06:33 | reference variable and I am going to call
it b and it's going to be of type bullet.
| | 06:38 | Now we want to loop through that bullets array.
| | 06:40 | So we are going to use the for loop.
| | 06:42 | Now an important thing when you are
creating a for loop and looping through
| | 06:46 | an array that you might splice something
out of, is you want to go from the top down.
| | 06:51 | You don't want to start at zero and
increment up through all the items.
| | 06:55 | You want to go backwards through the array.
| | 06:57 | So we are going to create an integer
counter here and we are going to set it
| | 07:01 | equal to bullets.length -1 and then
we are going to test for if i > =0 then
| | 07:12 | go ahead and continue and then we are going
to subtract from i everytime we go through.
| | 07:18 | So what we are first going to do in
here is to get a reference so we are going
| | 07:22 | to use that b variable and we are going
to say bullets i, so that way we have a nice
| | 07:27 | reference variable to work with.
| | 07:29 | Now on every frame we are going to
increment the Y position of the bullet, we
| | 07:34 | are actually going to decrement
it by 25 so it moves up the screen.
| | 07:38 | So we are going to say b.y - = 25.
| | 07:45 | Now if the bullet is off the top of
the screen then let's go ahead and
| | 07:48 | destroy that bullet.
| | 07:49 | So we are going to say if b.y < 0,
call the destroyBullet method and pass
| | 08:00 | in this bullet.
| | 08:03 | And we'll go ahead and set up
the destroyBullet in a minute.
| | 08:07 | So again that's what we are
going to do in our for loop.
| | 08:10 | Now another thing we need to do is we
are not going to call the fire function on
| | 08:15 | every frame, because remember this
is running at 60 frames per second.
| | 08:18 | So it's going to be firing way too many bullets.
| | 08:21 | So what we are going to do is we are
going to only do it on every sixth frame.
| | 08:27 | So if I actually come--I am going to
create a property at the top here, private
| | 08:33 | var count, and this is going to be an
integer and it's simply going to count the
| | 08:38 | number of times that the
update function has been called.
| | 08:41 | So we are going to come down to the
bottom of our update function and increment
| | 08:47 | that count variable.
| | 08:49 | So now we are going to use the Modules
operator to test whether we should fire or not.
| | 08:53 | So we are going to say if count%10 =
0 then we are going to call the fire
| | 09:02 | method and that's just a way for us to
slow down the amount of times that it's
| | 09:06 | actually firing, because doing it 60
frames per second is just going to fire
| | 09:11 | way too many bullets.
| | 09:12 | So that's the basic setup
for our update function.
| | 09:14 | Now in the next movie I am going to
show you how to implement the actual fire
| | 09:18 | behavior in our play state and get
the bullets firing the way they should.
| | Collapse this transcript |
| Firing bullets with the mouse| 00:00 | So in the last movie we started to fill
out our BulletManager functions here for
| | 00:04 | updating and for firing, but we only
want to fire bullets when the user has
| | 00:09 | their mouse down, so when they
actually have the mouse button down.
| | 00:13 | So let's set that up in the play state.
| | 00:16 | So the first thing I'm going to
want to create is a new instance of the
| | 00:20 | BulletManager class.
| | 00:21 | I'm going to come under where we
created our hero and I'm going to create a
| | 00:25 | variable called BulletManager.
| | 00:28 | It's going to be of type new BulletManager.
| | 00:30 | Now remember to that we need to pass
in a reference to our play state here.
| | 00:35 | So I'm just going to pass in this.
| | 00:38 | Again, let's create
bulletManager as an instance variable.
| | 00:42 | So now what we want to do
is to create a Boolean value.
| | 00:45 | We're going to create a public
Boolean property here, public var, and we're
| | 00:51 | going to call it fire.
| | 00:53 | This is going to be able to tell the
BulletManager whether it should fire a bullet or not.
| | 00:57 | Now we're going to set it at the default
to false up here, because when we first
| | 01:02 | come into the movie the user is
not going to have their mouse down.
| | 01:05 | So we're going to keep it at false.
| | 01:07 | Now what we need to do is to listen for
the mouse down and mouse up events, and
| | 01:12 | I told you before how Starling doesn't
have mouse events, but we can actually
| | 01:16 | reach out to the nativeStage and
listen for the mouse events there.
| | 01:21 | So I'm going to come to the top of my
init function here and I'm going create a
| | 01:26 | property called ns, which is short for
native stage and I'm going to set that
| | 01:31 | equal to Starling and again
you might have to import that
| | 01:34 | Starling.core.current.nativeStage.
| | 01:40 | That way we just have a nice short
reference to our nativeStage and now I'm
| | 01:45 | going to listen for the mouse down
and mouse up events on the nativeStage.
| | 01:49 | So ns.addEventListener and these
are going to be MouseEvent.MOUSE_DOWN.
| | 01:56 | We'll have that function called
onDown, and then I'm going to copy this,
| | 02:01 | we're going to create also one
called onUp, and that we're going to be
| | 02:06 | listening for the MOUSE_UP event.
| | 02:08 | So let's go ahead and create those.
| | 02:10 | Private function onDown.
| | 02:14 | Remember, the event object is going to
be MouseEvent and we can copy this and
| | 02:22 | duplicate it for the onUp event.
| | 02:26 | So all we're going to doing in the
onDown is we're going to be setting that fire
| | 02:31 | Boolean property to true, and again, the
BulletManager is going to be reading that
| | 02:37 | Boolean value determining
whether to fire bullets or not.
| | 02:41 | Then in the onUp what I want to do
is to set that fire Boolean to false.
| | 02:48 | Now another thing we're going to do here is to
reset the count property on our BulletManager.
| | 02:54 | So let's go ahead and change that to
public and we're going to reset the count = 0;
| | 03:03 | and this is actually bulletManager.count.
| | 03:06 | So again these methods are very simple.
| | 03:10 | Now the last thing we need to do is we need
to call the update method of our BulletManager.
| | 03:15 | So bulletManager.update.
| | 03:19 | So now let's go back to the BulletManager.
In our update method remember we came
| | 03:23 | down here and we say if count is
evenly divisible ten, so on every ten frames
| | 03:29 | it's going to fire a bullet.
| | 03:30 | But what we want to add is a condition,
because we want to say if(play.fire
| | 03:38 | && count%10.
| | 03:43 | So that will mean it will check
essentially if the mouse is down.
| | 03:47 | If so, then it's going to actually fire bullets.
| | 03:50 | So I'm going to save that now and if we
look we have our fire method and now we
| | 03:55 | need to fill in the destroyBullet method.
| | 03:58 | So let's go ahead and do that.
| | 04:00 | Because remember up here in the update
method if the bullet is off the screen
| | 04:04 | we need to destroy it.
| | 04:05 | So what I'm going to do is
to copy this for loop here.
| | 04:08 | We are going to use something
similar up in the destroyBullet method.
| | 04:15 | One of the things that we should
do, best practices, is if you're
| | 04:18 | looping through an array, you
actually don't want to be continuously
| | 04:22 | checking the length.
| | 04:24 | So what we're going to do is
to save that as a variable.
| | 04:27 | So I am going to come up to the top here.
| | 04:30 | I'm going to create a
variable called len for length.
| | 04:33 | It's going to be an integer
and it's equal to bullets.length.
| | 04:37 | So we can use that instead of
constantly hitting that bullets.length property.
| | 04:45 | For consistency let's also go up to our
update method and we'll do the same thing there.
| | 04:55 | So in our destroyBullet method,
in this case we don't have to go
| | 04:59 | backwards through it.
| | 05:00 | So we can actually set i to
0 and we can say if i<len;
| | 05:06 | i++, and here we're going to loop
through the array and check if the current
| | 05:13 | array variable is equal to the
bullet that we sent into the method.
| | 05:17 | So we're going to do that and we're
going to say if (bullets i is equal to b), because
| | 05:27 | remember that's the bullet we're
sending into this method, then we're going
| | 05:30 | to remove it.
| | 05:32 | So first let's splice it from the bullets array.
| | 05:34 | We are going to say bullets.splice and
we're going to start at the i position
| | 05:41 | and remove one element.
| | 05:43 | Let's remove the bullet from the display list.
| | 05:47 | So we're going to say b.removeFromParent.
| | 05:52 | We'll pass in true there and now we
want to return that bullet to our pool so
| | 05:57 | that it's available for the
next time we want to use it.
| | 06:00 | To do that we call the returnSprite
method of our pool and we pass in b.
| | 06:11 | So let's go ahead and test it and
see where we're at now, and I click in
| | 06:14 | here and now when I hold the mouse
button down you can see we're firing
| | 06:19 | bullets continuously.
| | 06:21 | If I lift the mouse button up, we stop.
| | 06:24 | Again, hold it down and we fire.
| | 06:26 | Now if you want to see what it looks
like to fire on every frame, you can
| | 06:29 | actually remove this,
which is a little excessive.
| | 06:35 | It's almost kind of like a laser.
| | 06:37 | It's not even individual bullets,
but you could do something like this.
| | 06:40 | See the frame rate at the top is not dipping.
| | 06:43 | When you're dealing with Starling and
Stage 3D you can use like thousands of
| | 06:47 | things on the screen at the same time,
but my personal preference again is to do
| | 06:51 | a little slower. Something like this
could be an upgrade, like you have a little
| | 06:55 | thing that comes down that when you get
it allows you to rapid fire and do all
| | 06:59 | kinds of upgrades and things like that.
| | 07:01 | But we now have our BulletManager class
and we're able to fire bullets and again
| | 07:05 | this concept of having of a manager is
something that you should use often in
| | 07:09 | your games, because again, you don't
want your main play state class to be
| | 07:14 | littered with all of this code.
| | 07:15 | It would just become too big.
| | 07:17 | So it's better to offload certain
things like that to some manager classes like
| | 07:22 | the one we just created.
| | Collapse this transcript |
| Creating the Alien movie clip| 00:00 | So in the last two movies we created our
Bullet class and our BulletManager class
| | 00:04 | which helps to keep track of all those bullets.
| | 00:06 | Well we are going to do a
very similar thing for our alien.
| | 00:10 | We are first going to create an Alien
class and then an AlienManager class.
| | 00:13 | So I'm going to go to my Objects
package, right-click, and say New >
| | 00:17 | ActionScript Class and
I'm going to call it Alien.
| | 00:21 | Now for a Superclass, we don't want
Sprite, we want MovieClip now, because again
| | 00:25 | this actually contains an animation
within itself and make sure you choose
| | 00:29 | Starling.display.MovieClip.
| | 00:33 | Now you'll see that it expects
two arguments to the constructor.
| | 00:36 | First is a Vector of Texture objects,
which we are going to get out of our
| | 00:41 | Texture Atlas, and then a frames
per second so this can actually have an
| | 00:45 | independent frame rate different
from the frame rate of our main game.
| | 00:48 | So I'm going to remove these arguments
from the constructor and we are going to
| | 00:53 | send them into the super constructor.
| | 00:55 | So first we need to get those
textures out of our Texture Atlas.
| | 00:58 | So I'm going to say Assets, and make sure
we import that, .ta.getTextures.
| | 01:04 | We've been using getTexture
when you need to get a single one.
| | 01:08 | If you need to get multiple, you use
getTextures and then we pass in our root
| | 01:12 | name which is alien, and if you forgot
what that name is, you can always look at
| | 01:17 | the Texture Atlas XML file.
| | 01:19 | Then we are going to pass
in 12 for the frame rate.
| | 01:22 | Now much like our other objects, we
want to set the pivot point of this movie
| | 01:26 | clip directly in the center.
| | 01:28 | So I'm going to set pivotX = width * 0.5
and then we are going to do the same
| | 01:37 | thing for pivotY and this
will be height * 0.5 like that.
| | 01:44 | So that's all we need to do for the alien.
| | 01:46 | Again, similar to the bullet.
| | 01:47 | The difference is that it's not just a
static sprite that we are creating here,
| | 01:52 | this is an animated object and that's
why we use MovieClip instead of Sprite.
| | Collapse this transcript |
| Creating the AlienManager class| 00:00 | So now that we've created our
Alien class we're going to create our
| | 00:04 | AlienManager class.
| | 00:05 | So I'm going to go to my manager's
package, right-click, create a new
| | 00:08 | ActionScript class and call it
AlienManager and I'm going to start with the code
| | 00:16 | from the BulletManager class, because
there's going to be a lot of similarities.
| | 00:20 | So I'm just going to copy all of that
class to the clipboard and just overwrite
| | 00:24 | the AlienManager class here.
| | 00:25 | Now obviously I need to go through and
change the class name to AlienManager.
| | 00:36 | We're going to change our
Array here from bullets to aliens.
| | 00:40 | So I'm just going to refactor and rename that.
| | 00:47 | And we're going to change our pool,
because obviously we don't want to create
| | 00:51 | bullets for our pool, we want to
create alien objects. So we're going to make
| | 00:57 | sure we import that Alien class and
we're not going to need a hundred of them.
| | 01:01 | At most we're going to need 20 aliens
in any one time, and again, that's a number
| | 01:05 | you can arrive at just by trial and error.
| | 01:08 | So we have our AlienManager.
| | 01:09 | I'm going to remove the contents here of
this for loop and remove this code right here.
| | 01:17 | We're going to change this local
variable from b to a, and then this is
| | 01:22 | obviously going to be type Alien.
| | 01:25 | We're going to change our fire
method to spawn, because we're going to be
| | 01:28 | spawning new aliens here, and I'll
just remove the contents of that function.
| | 01:35 | Our destroyedBullet class is actually
going to be called destroyAlien and this
| | 01:40 | is obviously going to be a, and
the class name is going to be Alien.
| | 01:46 | Well, that's already aliens, and we can
remove the contents of that for loop.
| | 01:52 | So now we can start adding in our code here.
| | 01:55 | Now I'm going to start with the spawn
method and that's going to be called
| | 01:58 | anytime we want a new alien to be spawned.
| | 02:02 | What I'm going to first do is
to get an alien out of our pool.
| | 02:06 | So I'm going to create a local
reference variable here called a, it's going to
| | 02:09 | be of type Alien is equal to pool.getSprite()
and we'll cast it as Alien.
| | 02:18 | Now the difference between a Sprite and
a MovieClip is this movie clip needs to
| | 02:21 | be animated on every frame and the way
in which we do that in Starling is to add
| | 02:25 | it to an object called the juggler and
the juggler makes sure that all of the
| | 02:29 | objects it contains are updated.
| | 02:32 | We get to the main juggler instance,
because it's a static property on
| | 02:37 | the Starling class.
| | 02:38 | So if we say Starling, and again make
sure that that is imported, .juggler.add.
| | 02:45 | Then we're going to add in that (a)
| | 02:49 | alien here, and that's going to
make sure that it's actually animated,
| | 02:52 | because if we don't do that, it's just
going to be stuck on the first frame.
| | 02:56 | The next thing I want to do is to
push that into the aliens array.
| | 03:00 | So I'm going to aliens.push(a);
| | 03:05 | and now I need to set its X and Y position.
| | 03:08 | First set its Y position.
| | 03:10 | So we want it to be off the screen at the top.
| | 03:13 | So I'm going to set it to negative 50.
| | 03:15 | Now I'm going to set its X position
and here we want a random X position,
| | 03:19 | because obviously we don't want
them all falling in the same spot.
| | 03:22 | So I'm going to say Math.random() * 700 + 50;
| | 03:29 | and that will give us a nice
distribution across the X axis.
| | 03:34 | Now lastly I need to add this to
the display list of our play state.
| | 03:38 | So we are going to say play.addChild(a).
| | 03:42 | So again this function will be called
anytime we want to spawn a new alien.
| | 03:47 | So then that brings up the question
when do we want to spawn new aliens?
| | 03:51 | Well, we want to do it kind of randomly.
| | 03:54 | So in our update method up here I'm
going to create an if statement and I'm
| | 03:58 | going to create a random number.
| | 04:00 | So I'm going to say Math.random().
| | 04:04 | If(Math.random() is less than 0.2,
then we're going to call the spawn method.
| | 04:13 | So now remember Math.random
returns a random number between 0 and 1.
| | 04:18 | So by adjusting this number here, we
can make it more or less likely that a new
| | 04:23 | alien is going to be spawned.
| | 04:25 | Again, you can just use trial and
error and then also this value can change
| | 04:29 | throughout your game to
make the game more difficult.
| | 04:32 | So now what I want to do is to go
through and update all of the aliens that are
| | 04:37 | currently in the game.
| | 04:38 | So I'm going to use that local
variable here and I'm going to get the item
| | 04:43 | out of the aliens array, and I'm
going to increment its Y position by 8
| | 04:49 | pixels on every frame.
| | 04:51 | Again, you can adjust that number to
adjust the speed in which the aliens travel.
| | 04:57 | Now I'm going to test if the
alien is actually off of the screen.
| | 05:02 | So I am going to say if(a.y > 800),
then I need to actually destroy this alien.
| | 05:11 | So I'm going to say
destroyAlien and pass in (a);
| | 05:18 | and now we can actually look how to
destroyAlien method, and again, this can be
| | 05:22 | called from within this function, but
also outside of this function when we get
| | 05:26 | to collision detection.
| | 05:27 | The first thing we're going to do is to loop
through and make sure we have the correct alien.
| | 05:32 | So we're going to say if(a is equal
to aliens i) then we are going to dispose
| | 05:39 | of this and we're going to do that first by
splicing it out of the array, aliens.splice.
| | 05:49 | I'm going to start with i and go to 1.
| | 05:53 | Now we need to remove it from the juggler.
| | 05:55 | So starling.juggler.remove(a);
| | 06:01 | because again, we don't want this thing
to be constantly updated if it's not even
| | 06:05 | in the game anymore.
| | 06:08 | Then we want to remove it from the display list.
| | 06:10 | So we're going to a.removeFromParent
and we're going to dispose it and then
| | 06:15 | lastly we want to return this to our
pools so that it can be re-used later.
| | 06:21 | So pool.returnSprite(a);
| | 06:24 | and we're going to get to the destroy method
for our Manager classes later in this chapter.
| | 06:29 | So I'm going to save this now, and
I'm going to go back to my play state,
| | 06:34 | because now I need to create an
instance of this AlienManager.
| | 06:37 | So I'll do it right under my BulletManager.
| | 06:39 | I'm going to call it alienManager is
equal to new AlienManager and remember we
| | 06:46 | have to pass in (this) to it.
| | 06:49 | I'll create that as an instance variable.
| | 06:52 | And now I need to go to my update
method and here I need to update the
| | 06:57 | alienManager on every frame.
| | 06:59 | So alienManager.update();
| | 07:04 | So I'm going to go ahead and run this.
| | 07:08 | So here is our menu. I'm
going to click Play Game.
| | 07:11 | And now you can see, we have
actually exhausted the pool.
| | 07:15 | So if I click on here, you'll see that
custom error has been thrown and then
| | 07:20 | this is where we need to adjust that
value; the value which determines how often
| | 07:26 | something is spawned.
| | 07:28 | So we need to make it a lot less than this.
| | 07:30 | So let's say if it's less than
0.05 and now we can try this.
| | 07:35 | This number is of course going to be
trial and error, because there are way too
| | 07:39 | many aliens being spawned there.
| | 07:41 | So that's a decent number right there,
but again, this can be adjustable.
| | 07:46 | This could be a value that's
actually changed over time once the game
| | 07:50 | becomes more difficult.
| | 07:51 | So definitely play around with those
values to create different effects.
| | 07:56 | So that's the basics of our AlienManager class.
| | 07:58 | Now again, we're going to filling in the
destroy methods for the AlienManager and
| | 08:02 | the BullentManager later on.
| | 08:04 | But in the next movie we're going to
look at collision detection, because
| | 08:07 | obviously it's no good firing bullets
if it doesn't actually kill anything.
| | Collapse this transcript |
| Overview of collision-detection options| 00:00 | So before we go and actually
implement collision detection into our game,
| | 00:04 | I wanted to go over a couple of the
options which you have for collision detection.
| | 00:09 | So the simplest is called bounding box
collision detection and you can see in
| | 00:13 | this example here, I have my alien and
I have my hero ship, and essentially,
| | 00:18 | there are rectangles around
them that denote the bounds.
| | 00:22 | So anytime I overlap the two,
we can see they turn red here.
| | 00:27 | This is the simplest form of collision
detection that's actually useful for a
| | 00:32 | lot of things, because remember in our
game, the aliens are moving downwards.
| | 00:36 | So if we want to test between the
aliens and the ship, this is actually pretty
| | 00:42 | good, and for the most case since
things are moving so fast, this would
| | 00:45 | actually work fairly well.
| | 00:48 | Now obviously, if you had a big
graphic that had all kinds of intricate
| | 00:51 | shapes, and you wanted to really test in a
more accurate way, then things would break down.
| | 00:57 | But this is the simplest and the
fastest way to do collision detection and you
| | 01:01 | can see the code at the bottom,
essentially every display object in Starling has
| | 01:06 | a Bounds property which contains this
rectangle, and you can use the intersects
| | 01:12 | method of the rectangle class to check
if it's overlapping the bounds of another
| | 01:17 | Starling display object.
| | 01:19 | So again, this is the
simplest form of collision detection.
| | 01:22 | The next one is distance-based
collision detection.
| | 01:26 | So in distance or sphere-based collision
detection, you can think of there being
| | 01:31 | a circle around all of your objects,
and essentially, you are testing the
| | 01:36 | difference between the center of both circles.
| | 01:39 | So if the distance between the center
of both of these circles is within a
| | 01:43 | certain amount, then it will
determine that a collision has happened.
| | 01:48 | This is a more accurate way to do
things, and all of this is adjustable.
| | 01:53 | You can adjust the numbers to
create any type of effects that you want.
| | 01:57 | This is usually considered the best
approach and it actually works for the vast
| | 02:02 | majority of cases in which you need
collision detection, and this is the method
| | 02:06 | that we're going to be using in our game.
| | 02:08 | But you can see at the bottom,
essentially you find out the distance between
| | 02:12 | the center of both of these circles and
if it's less than the two radiuses added
| | 02:18 | together, then a collision has occurred.
| | 02:20 | And again, you can
manipulate those numbers if you want.
| | 02:23 | Now this brings up a point about pixel
perfect collision detection and that's
| | 02:28 | something you want to avoid at all cost,
particularly when you are running games on the GPU.
| | 02:33 | Pixel perfect collision detection
first of all is not needed in 99% of cases,
| | 02:40 | and if it is needed, then you might
want to consider not running a game on the
| | 02:45 | GPU because it's such a CPU intensive process.
| | 02:48 | Once your textures are uploaded to the
GPU, you don't have any way to read the
| | 02:53 | pixel data in order to do
good collision detection.
| | 02:57 | All of that has to happen on the CPU.
| | 02:59 | So definitely, avoid pixel perfect
collision detection, particularly when you
| | 03:04 | are running games in Starling, and this
distance-based approach will work in the
| | 03:08 | vast majority of cases.
| | Collapse this transcript |
| Creating the CollisionManager class| 00:00 | So like I showed you in the last movie
we are going to be using distance-based
| | 00:04 | collision detection for our game.
| | 00:06 | Now I could do that collision
detection directly in the Play state, but
| | 00:09 | again, it's nice if we create a
CollisionManager class which is going to
| | 00:13 | handle that for us.
| | 00:15 | So I am going to right-click on my
managers package, New > ActionScript Class
| | 00:19 | and this one is going to be called
CollisionManager, and to the constructor we
| | 00:25 | are going to send in our Play state.
| | 00:27 | So I am going to create an argument
called play, it's going to be of type Play,
| | 00:32 | and we'll create that as an
instance variable, so this.play = play.
| | 00:41 | And we are going to create a public
update function which we are going to call
| | 00:45 | from our play state.
| | 00:46 | So public function update, and we
are not going to return anything here.
| | 00:52 | And in this update method we are going
to call two different functions and they
| | 00:56 | are going to check collisions between
the bullets and the aliens, and then also
| | 01:00 | we are going to check collisions
between our hero ship and the aliens, because
| | 01:04 | essentially in our game it's pretty
simple; the game is going to be over if an
| | 01:08 | alien crashes into you essentially.
| | 01:11 | So we are going to first call the
bulletsAndAliens function, so we'll just
| | 01:18 | define that here and we can do a quick
fix to actually create that function.
| | 01:23 | Then we are going to be doing the
heroAndAliens check and I'll create that method.
| | 01:29 | So we are going to start with
the bulletsAndAliens function.
| | 01:34 | So now what we need to do is to get a
reference to the bullets array and the
| | 01:40 | aliens array which are in those manager classes.
| | 01:43 | But remember, by default, we create all
of our class properties as private so we
| | 01:48 | need to now expose those as public.
| | 01:50 | So I am going to go into my
BulletManager class and this bullets:Array, we are
| | 01:55 | going to change its access modifier to
public, and then also in our Play method
| | 02:02 | we need to make sure that our
bulletManager and our alienManager class is also
| | 02:08 | exposed as public, so that we can
access it from our CollisionManager.
| | 02:14 | And then I also need to go into the
AlienManager and make sure that aliens:Array
| | 02:19 | is also set to public.
| | 02:24 | Okay, so I am going to get references
to both of those, so I am going to create
| | 02:29 | a local variable called ba for bullets
array and this is going to be of type
| | 02:34 | Array, is equal to play.bulletManager.bullets.
| | 02:40 | And we are going to do the same
thing for the aliens:Array, so var aa =
| | 02:45 | play.alienManager.aliens.
| | 02:50 | Now we are going to create two local
variables as we loop through to store the
| | 02:55 | references to the bullet and to the
alien, so var b is going to be of type
| | 02:59 | Bullet and var a is going to be of type Alien.
| | 03:05 | So what we need to do is to
create two nested for loops.
| | 03:09 | So we are going to loop through all of
the bullets and for each bullet we are
| | 03:13 | then going to test whether it's
touching or close enough to any other aliens
| | 03:18 | that are currently in play.
| | 03:20 | So I'm going to create a for loop, var i:int,
and remember that we are going to
| | 03:26 | want to loop backwards through these,
so is equal ba.length-1; i>=0; i--).
| | 03:40 | Now I am going to copy this line right
here because we are going to create an
| | 03:44 | inner for loop, and I am going to
change the variable to j, and then this is
| | 03:50 | going to be aa.length-1; j>=0; j--).
| | 04:00 | What I want to do inside of this
first for loop is get a reference to the
| | 04:04 | current bullet, so I am going use that
b variable and I am going to go into ba
| | 04:10 | and go to the ith element
of that array like that.
| | 04:15 | And now inside of the second for
loop, I am going to set that alien
| | 04:19 | local variable, to aaj.
| | 04:22 | So now we need to test the distance
between the alien and the bullet, and to do
| | 04:27 | that we are going to use the point class.
| | 04:29 | So we are essentially going to create
two point objects that contain the X and Y
| | 04:34 | of both the bullet and the alien.
| | 04:36 | Now we could create those in here but
it's a lot better performance if we create
| | 04:40 | those at the top as class properties.
| | 04:44 | So we are going to say private var p1,
is of type Point, and we are going to
| | 04:49 | instantiate it right here, new Point,
and we are going to do the same thing
| | 04:55 | for the second point.
| | 04:57 | p2, type Point = new Point.
| | 05:03 | And then all we are going to do inside
of this loop is just adjust the X and
| | 05:07 | the Y position of that point, that way we were
not instantiating a new point on every frame.
| | 05:12 | So let's first get the position of our
bullet and we are going to use that p1 point.
| | 05:17 | So we are going to set p1.x = b.x,
p1.y = b.y and now we'll set the second
| | 05:28 | point, the x property to the aliens x
and we'll set the y property to the alien y.
| | 05:34 | Well now we can use a static function
on the Point class called Distance, which
| | 05:40 | will give us the distance
between these two objects.
| | 05:43 | So we are going to test if the
difference is small enough and then we are going
| | 05:48 | to determine that a collision has occurred.
| | 05:49 | So we are going to use an if statement.
| | 05:52 | We are going to say if Point.distance,
and here we pass in those two point
| | 05:56 | objects, p1 and p2, if it's less
than the radius of both the alien and the bullet.
| | 06:05 | So if it's less than a, and we are
going to use the pivotY of it, because
| | 06:10 | remember these things are actually
coming down vertically up and down so we need
| | 06:15 | to get the center
vertically of each of these objects.
| | 06:18 | If it's less than a.pivotY + b.pivotY,
then we are going to go ahead and
| | 06:28 | determine that a collision has occurred,
and in that case, we want to destroy both
| | 06:32 | the bullet and the alien.
| | 06:34 | So we are going to say play.
alienManager.destroyAlien(a);
| | 06:41 | and then play.bulletManager.destroyBullet(b).
| | 06:48 | And if you want to make sure you have
these set correctly, if we go into our
| | 06:52 | Alien class and our Bullet class, here
we are setting the pivotX and pivotY to
| | 06:56 | make sure it's in the center of our alien.
| | 06:59 | If we go to the Bullet class this
actually should not be image, so let's
| | 07:03 | go ahead and remove that to make
sure it's in the center of our actual
| | 07:07 | bullet sprite itself.
| | 07:09 | So now we are going to determine
that a collision has occurred here.
| | 07:14 | So now if we actually go and create our
CollisionManager now in our Play class,
| | 07:18 | let's just create it right under
our alienManager and we'll call it
| | 07:23 | collisionManager = new CollisionManager,
and we are going to pass in this, and
| | 07:31 | create that as an instance variable.
| | 07:34 | And much like before, we are going to
come to our update method and call the
| | 07:38 | update method of the collisionManager.
| | 07:42 | So now let's go ahead and
test it and see what happens.
| | 07:46 | So if I click, now you can see when I
am shooting I am actually now killing
| | 07:51 | aliens and both the bullets and
the aliens are actually going away.
| | 07:55 | Now we haven't got to adding particle
effects or anything like that, but we can
| | 07:59 | see the collision is now working.
| | 08:01 | Now let's say we wanted to make it so
the bullet had to be even closer to the
| | 08:04 | alien, but we could come to the
CollisionManager and actually update this.
| | 08:09 | So we can make it a little less than
this if we wanted to, but this is actually
| | 08:12 | fine for what we are doing now.
| | 08:15 | Now lastly, we need to do the
heroAndAliens because that's how we actually are
| | 08:19 | going to die and the game is going to be over.
| | 08:21 | So we are going to loop through the
aliens, so I am going to copy this line from
| | 08:26 | bulletsAndAliens, and then again, I
want to get a local alien variable.
| | 08:29 | So I'll just copy this, and I am
going to go ahead and copy this for loop,
| | 08:34 | because we are going to do a very
similar thing here, and we are going to be
| | 08:39 | looping through aa here.
| | 08:42 | And again, let's get
that local reference to aai.
| | 08:48 | And now essentially we are going to do the same
thing, where we are setting this point object.
| | 08:53 | So let's go ahead and copy that, and
this point can say the same, but in this
| | 08:58 | one we are actually going to be getting
the x and y of our hero, so play, and we
| | 09:04 | need to make sure the hero is actually
public in our Play state, which it is.
| | 09:10 | So here, if we say play.hero.x, play.hero.y.
And again, we are going to do this
| | 09:22 | if statement and we are going to check
the distance between these two points. If
| | 09:29 | it's less than a.pivotY and
then we want play.hero.pivotY.
| | 09:38 | Then we are not going to worry about any
of this because we are going to make it
| | 09:40 | so that the game is actually over.
| | 09:43 | So for that, we are going to say play,
and we need to make sure that our game in
| | 09:47 | our Play state is also public.
| | 09:49 | So let's go ahead and modify that to public.
| | 09:52 | So we'll do play.game.changeState and
then we'll go into that Game class and get
| | 10:00 | the GAME_OVER constant.
| | 10:01 | Okay, so now we have added it.
| | 10:04 | If we actually test this now, we can
see that as I shoot, I am actually killing
| | 10:11 | the aliens, but I'll let myself hit
one of the aliens and we can see that
| | 10:15 | everything is paused.
| | 10:16 | Now again, we haven't created the
destroy method for our Play state yet and we
| | 10:21 | don't have any visuals
yet on the GameOver state.
| | 10:23 | But you can see that our collision
detection is actually working and you can see
| | 10:27 | here where it actually stopped,
that's where that collision has occurred.
| | 10:31 | And you can see with that distance-based
collision detection that's about
| | 10:35 | the right location.
| | 10:36 | So we can, again, adjust that, expand the
numbers dependent on our case, but the
| | 10:41 | collision detection is now working.
| | 10:43 | In the next movie we are going to do
all of our clean up and handle destroying
| | 10:47 | of the Play state before we
move to the GameOver state.
| | Collapse this transcript |
| Implementing the destroy method| 00:00 | So now we have our basic game play
completed. So we have our collisions
| | 00:04 | happening and we determined when
we're going to go to the GameOver state.
| | 00:08 | But now we need to clean up
after ourselves in the play state.
| | 00:12 | So we need to implement the destroy methods.
| | 00:14 | So first, let's go to our BulletManager.
| | 00:17 | So in our Manager classes, we need to do
a couple of things in the destroy method.
| | 00:22 | First, we're going to destroy the pool.
| | 00:24 | So to do that, we're going to
call the destroy method of the pool.
| | 00:28 | Then we're going to set pool = null and
we're also going to set our array to null.
| | 00:35 | So our array here is called bullets,
and we'll set it equal to null.
| | 00:40 | When it comes to cleaning up after
yourself and garbage collection in Flash,
| | 00:45 | it's better to do too much than not enough.
| | 00:47 | So it's somewhat of a mystery
sometimes about how to force things to be
| | 00:52 | reclaimed in memory, so it's better
just to go overboard and just be sure that
| | 00:57 | you're cleaning up after yourself.
| | 00:59 | So we're going to copy this because
we're going to do a similar thing in
| | 01:03 | the AlienManager class.
| | 01:04 | I am going to come down to the destroy
method, paste that in, and obviously our
| | 01:09 | array here is called aliens.
| | 01:12 | Now we want to go to our play method,
and implement the destroy method here.
| | 01:18 | Now what I'm going to first do is to
copy these two event handlers where we
| | 01:22 | listen for the mouse up and mouse down,
and let's go ahead and make sure that
| | 01:26 | those are actually unregistered.
| | 01:28 | So we'll do that first.
| | 01:29 | We'll change that to removeEventListener.
| | 01:36 | Now we're going to call those destroy methods
on the BulletManager and the AlienManager.
| | 01:41 | So bulletManager.destroy();
| | 01:47 | and then alienManager.destroy(), and
then lastly let's remove this play state
| | 01:56 | from the display list of our game.
| | 01:59 | So we're going to say removeFromParent and
we're going to pass in (true) to dispose it.
| | 02:05 | Now let's go ahead and test
it, so I'm going to debug.
| | 02:09 | We'll go to our actual game.
| | 02:11 | So everything is working and now when I
die, we actually remove the play state
| | 02:17 | and now here is the GameOver state.
| | 02:19 | Obviously, we haven't done anything
yet in the GameOver state, but we'll be
| | 02:22 | doing that in the next chapter.
| | Collapse this transcript |
|
|
7. The GameOver StateAdding the background| 00:00 | So in this chapter, we're going
to focus on the GameOver state.
| | 00:03 | Now this is going to be
similar to the menu state.
| | 00:05 | We're going to have that same animated
background, we're going to have a game
| | 00:09 | over text field, and then we're
simply going to have a button that says
| | 00:13 | essentially Try Again, so you can
actually try to play the game again.
| | 00:17 | So we're going to do the background first.
| | 00:19 | So I'm going to come into my init
method and I'm going to create a new
| | 00:23 | property, call it background = new
Background, and let's go ahead and create
| | 00:30 | that as an instance variable.
| | 00:31 | Now I need to add this to the display list;
| | 00:35 | so addChild(background).
| | 00:39 | And much like before, in our update
method, we're going to call the update
| | 00:43 | method of our background.
| | 00:45 | So background.update();
| | 00:48 | and that's all we need to do for the
background, but let's go ahead and make
| | 00:52 | sure that it's working.
| | 00:53 | So we'll test it, go to Play Game,
we'll make sure the game is over there, and
| | 00:57 | we can see we're now in our GameOver
state with our scrolling background.
| | 01:02 | So in the next movie, we're actually
going to focus on creating a text field
| | 01:06 | using that bitmap font that says Game Over.
| | Collapse this transcript |
| Creating the "Game Over" text| 00:00 | Now that we have our background, we are
going to focus on creating the game over
| | 00:05 | text, and we are going to use a
Starling text field to display that.
| | 00:09 | So I'm going to come under where I
created my background in my init method.
| | 00:13 | I'm going to create a variable here,
and I'm going to call it overText, and I'm
| | 00:18 | going to set that equal to a new text field.
| | 00:21 | And again, be sure you are
using starling.text.TextField.
| | 00:25 | And to that, we are going to
pass in a few different things;
| | 00:29 | first, the width and the height.
| | 00:30 | I'm going to put the width at 800, so
it's the whole width of my game and we are
| | 00:35 | going to set its align to Center, so
that way, it's centered in the middle.
| | 00:39 | And I'm going to set the height here
to 200, pass in what actual texturing we
| | 00:44 | want to display, and we can set all of
these also outside of the constructor,
| | 00:48 | but I'm just doing it here.
| | 00:50 | We are going to say GAME OVER.
| | 00:52 | Now we need to use uppercase, because
remember, when I created that bitmap font,
| | 00:55 | when we did the assets chapter, I only
included the glyphs for the uppercase
| | 00:59 | characters because that's
all the font actually contains.
| | 01:03 | Now next is the font name.
| | 01:04 | So remember, in our assets
class, we have this Komika font.
| | 01:10 | So if I open that with the Text Editor
here, remember this is the name that I
| | 01:15 | need to give when I want to use that font.
| | 01:18 | So I'm going to give it a
string of KomikaAxis like that.
| | 01:23 | Now next is the size of the font.
| | 01:25 | I'm going to do 72 and then the
color, and I'm going to do white.
| | 01:31 | I'm going to create that
as an instance variable.
| | 01:35 | Now I want to set up a couple of things with it.
| | 01:36 | First, I want to set its align property.
| | 01:40 | So I'm going to set overText and we want
to set the hAlign property, and we just
| | 01:46 | set it to a string of center, and now
I'm going to set the y position of that.
| | 01:51 | So overText.y, because remember, it will
automatically be centered on the x axis.
| | 01:57 | I'm going to set it to 200, and then lastly,
we want to add this text to the display list.
| | 02:03 | So addChild(overText); like that.
| | 02:07 | Let's see what that looks like.
| | 02:08 | So we will launch our game,
and we'll die on purpose.
| | 02:13 | And there we have our text nicely
centered and we are using that bitmap font.
| | 02:18 | So again, this is a nice way to be
able to render text, and we don't have to
| | 02:24 | include a PNG file that says game over.
| | 02:27 | If we are using a lot of text in our
game, we can just reference those bitmap
| | 02:31 | fonts, and use the text field
class that is included with Starling.
| | 02:36 | So the next step is to add our Try
Again button which the user can click on to
| | 02:41 | try again at playing the game.
| | Collapse this transcript |
| Adding the Try Again button| 00:00 | So now, we have our animating
background in our game over text.
| | 00:03 | Last thing we need to do in the GameOver
state is to create our Try Again button.
| | 00:08 | So I am going to create a
property here called tryAgain.
| | 00:12 | I'm going to set that equal to a new
Starling button instance, and now we need
| | 00:17 | to get that texture from our texture atlas.
| | 00:20 | So I am going to say Assets, make sure
we import that class .ta.getTexture and
| | 00:29 | the texture name is tryAgainButton.
| | 00:34 | Now let's go ahead, and create
that as an instance variable.
| | 00:39 | Now we want to set the
pivot X property of the button.
| | 00:43 | That way we can easily
position it in the center of our movie.
| | 00:45 | So we are going to say tryAgain.pivotX =
tryAgain.width * 0.5.
| | 00:57 | Let's position this now.
| | 00:58 | So we are going to say tryAgain.x.
You can put it right in the center at
| | 01:06 | 400, tryAgain.y = 450.
| | 01:10 | Again, that's just a trial and
error thing to position it correctly.
| | 01:14 | Now let's add it to the display list;
| | 01:16 | so addChild (tryAgain).
| | 01:19 | Now much like we did in the menu state,
we need to listen for the triggered
| | 01:22 | event on this button so that we know when
to actually let the user play the game again.
| | 01:27 | So I am going to come right
under where we created it and say,
| | 01:31 | tryAgain.addEventListener. We want Event.
| | 01:35 | Again, make sure you get starling.
events.Event, and now we want the TRIGGERED
| | 01:40 | event, and we'll just call
the event handler onAgain.
| | 01:45 | So let me create that method, and make
sure we have our event object being caught here.
| | 01:53 | And in this onAgain event, what we are
going to do is to change the game state to play.
| | 01:59 | So again, we're going to say game.changeState,
and then we are going to get that
| | 02:05 | static state property of PLAY_STATE.
| | 02:09 | So now let's go ahead and
test it, and make sure it works.
| | 02:12 | So we'll debug here, click Play
Game, and I'll let myself die.
| | 02:17 | We are in the GameOver state, and
we can see our button being displayed,
| | 02:22 | and when I click it, we
actually go back to the Play state.
| | 02:25 | Okay, so now we just need to implement
the destroy method here, and to do that,
| | 02:30 | we are essentially just
going to removeFromParent(true).
| | 02:36 | So we are going to make sure we dispose that.
| | 02:38 | Now one of the things that's good
practice to do is since we are listening for
| | 02:43 | this event here, let's go ahead
and unregister for that event here.
| | 02:49 | We'll say tryAgain.removeEventListener.
| | 02:53 | So again, my philosophy on cleaning up
after yourself, it's better to do more.
| | 02:58 | Even if some things aren't entirely
necessary, it's just good practice to get into.
| | 03:02 | So now let's go ahead and test it.
| | 03:04 | Again, we come in, we have our
game, we die, GameOver state;
| | 03:10 | TRY AGAIN brings us back to the play
state so we continue playing our game.
| | 03:15 | And again, I just wanted to highlight
to you that the performance that you are
| | 03:19 | seeing here is not necessarily
accurate of the real performance of the game.
| | 03:22 | For numerous reasons, this is a debug
build, and I mentioned before how with
| | 03:27 | Starling in particular, you really
need to do a release build of your game in
| | 03:31 | order to get an idea of the real
performance, because you can see even though
| | 03:36 | the frame rate here is 60 frames
per second, it still looks a little
| | 03:40 | stuttery, and that's because we are
looking at this using a debug build and
| | 03:44 | also in the debug player.
| | 03:46 | But that's the GameOver state, and in
the next chapter, we are actually going
| | 03:51 | to focus on creating some more visual effects.
| | 03:55 | We are going to create particles so that
when you actually shoot a bullet and it
| | 03:59 | hits an alien, we are going to see an
explosion particle so we'll add a little
| | 04:03 | more eye candy to our game in the next chapter.
| | Collapse this transcript |
|
|
8. Adding Particle EffectsExploring particle-creation tools| 00:00 | So we now have our major gameplay and
our game created, but you'll notice that
| | 00:04 | obviously when we shoot a bullet and it
hits an alien, well nothing happens, they
| | 00:08 | both just disappear.
| | 00:09 | It's not exactly the most
thrilling gameplay ever.
| | 00:11 | So now, we want to include particle
effects, like I mentioned when we downloaded
| | 00:16 | the Starling framework, the
particle features actually an extension.
| | 00:20 | We've already incorporated
that into our source code.
| | 00:23 | But now the question is how do
we create these particle effects?
| | 00:26 | Well I am going to show you a
tool that's Mac only that's called
| | 00:30 | ParticleDesigner and we downloaded
that when we were setting up our system.
| | 00:35 | And this is not a free tool, so you
can see I am using just the trial version
| | 00:40 | here, so it says unregistered.
| | 00:41 | But this allows you to
visually create particle effects.
| | 00:44 | So this tool is geared for iOS development.
| | 00:47 | That's why you're seeing
things displayed here in an iPhone.
| | 00:51 | But with this particle thing, I can drag it
around to see the effects of these particles.
| | 00:56 | But most importantly, there is a
huge library of user-submitted particles
| | 01:02 | that I can check out.
| | 01:03 | So I can just click on one of these
to see how these particle effects look.
| | 01:08 | Now one thing to note is when you use
these in Starling, they may look slightly
| | 01:12 | different, and that's because of the way
in which Starling is doing things. It's
| | 01:17 | not an exact duplicate, but you
can get pretty close by doing this.
| | 01:22 | So you can use your own images for
particles, like here is one of these like
| | 01:26 | falling rocks. Let me just go to a couple
of more of these. So here is a lava flow;
| | 01:32 | really, really cool stuff.
| | 01:33 | Now the real thing is
that you can then edit these.
| | 01:37 | So let's say I use this particle here.
| | 01:39 | I can go to Emitter Config, and then
this allows me to adjust all of these
| | 01:45 | properties to change how the
particle effect is actually going to look.
| | 01:49 | So let's say I wanted to change the gravity.
| | 01:51 | I could come down to Gravity y and
change it, so it's a different gravity.
| | 01:56 | Now all of these, or most of these
properties, can be adjusted in Starling at run
| | 02:00 | time, so say you wanted to have an
effect where the particle effect was actually
| | 02:05 | changing over time, you can absolutely do that.
| | 02:08 | And here you can see the texture
that's being used on this particular effect.
| | 02:12 | But again, being able to have one of
these existing particles as kind of a
| | 02:17 | starting point for you is a really cool thing.
| | 02:19 | Now when you want to save these, first
of all in the unregistered version, it's
| | 02:24 | not going to let you.
| | 02:25 | But if we look at the particles that
I've included in the assets, we can see
| | 02:30 | we have this explosion.pex file, and that's
the file that you export from ParticleDesigner.
| | 02:35 | But then you also export a PNG which
is the actual particle, and this is what
| | 02:42 | the particle looks like.
| | 02:43 | And remember, this is actually
a part of our texture atlas now.
| | 02:47 | But if I look at this file, I am going
to look at it just in the Text Editor,
| | 02:52 | we can see that it's just an XML file.
| | 02:54 | So you can actually come in here and
adjust these things in the XML or you can
| | 02:58 | actually do it at run time in Starling.
| | 03:00 | Now I did want to show you one
other tool which is really nice.
| | 03:04 | This is actually a web-based
tool created by One by One Design.
| | 03:09 | So if you go to onebyonedesign.com/flash/
particleeditor, this is a similar type
| | 03:15 | of editor, but this is actually
now displaying this in Starling.
| | 03:19 | So this is actually
built in Starling right here.
| | 03:22 | So you are going to get an exact
representation of how things look.
| | 03:27 | Now another thing is that you can
actually load in particles that you built
| | 03:31 | in ParticleDesigner.
| | 03:33 | You can change the
texture of the background here.
| | 03:35 | So I can adjust these values.
| | 03:37 | So let's say I wanted to reduce the
number of particles that I am using, and
| | 03:41 | that's an important thing.
| | 03:42 | And when it comes to performance, you
want to make sure you are not using way
| | 03:46 | more particles than you need.
| | 03:48 | Often times, you can get away with
lot smaller number of particles, and
| | 03:52 | achieve the same effect.
| | 03:53 | So here I can change,
let's say, the gravity of this.
| | 03:57 | We can see that as I adjust these, things change.
I can change the blending, the color values.
| | 04:03 | So let's say I wanted to adjust the
color of this, well that changes the alpha.
| | 04:08 | So maybe I want to make these blue, a more
purple effect, you can see things are changing.
| | 04:12 | Another thing to be aware of with
ParticleDesigner is that it uses a
| | 04:17 | different coordinate system.
| | 04:19 | So let's take this example.
| | 04:21 | This would actually be flipped in Starling.
| | 04:24 | So the Y is actually
flipped when we are in Starling.
| | 04:27 | So if you are going to be designing
particle effects in ParticleDesigner, make
| | 04:31 | sure that you are aware of that,
and you actually reverse things in
| | 04:34 | ParticleDesigner so that they work.
| | 04:36 | So in conjunction with these two tools,
you can create just an incredible array
| | 04:41 | of really nice particle
effects that perform really well.
| | 04:45 | So in the next movie, I am going to
show you how to incorporate the particle
| | 04:49 | effects that I've
provided for you into our game.
| | Collapse this transcript |
| Adding the smoke texture| 00:00 | So now that I've showed you how you
can go ahead and create particle effects,
| | 00:04 | let's incorporate the first
particle effect into our actual game.
| | 00:08 | So I've included two
particle effects in the assets;
| | 00:11 | the first is this smoke particle effect and
this is going to be the exhaust for our hero ship.
| | 00:18 | So I'm in our assets class.
| | 00:19 | Now remember that our particle PNG file
is actually in our texture atlas, so we
| | 00:25 | don't need to actually go
ahead, and embed that here.
| | 00:28 | All we need to embed is the PEX file.
| | 00:31 | So I'm going to say Embed(source="
assets/smoke.pex" which again is that XML
| | 00:42 | file, and I'm just going to copy this,
because again, since it's an XML file, we
| | 00:47 | need to set its MIME type.
| | 00:49 | And now I'm going to create this as a
public static variable because we are
| | 00:54 | going to reference this
directly from our Hero class.
| | 00:58 | Public static var and I'm just going to call
it smokeXML, it's going to be of Type class.
| | 01:05 | Okay, so now let's go to our Hero
class, and what I want to do is to set up
| | 01:11 | this particle system.
| | 01:12 | So I'm going to come under
where we import our image.
| | 01:15 | I'm going to create a new property
called smoke, I'm going to set it equal to
| | 01:20 | new, and then the class is PDParticleSystem.
| | 01:25 | That's the class which
actually handles our particle system.
| | 01:28 | So to the constructor, you can see it's
expecting that particle XML file which
| | 01:34 | is our PEX file, and then our texture
that we are using for the particle effect.
| | 01:39 | So I'm going to first have to cast
that to an XML file and then create a new
| | 01:44 | instance of Assets.smokeXML.
| | 01:51 | Now for the texture, remember, that's
in our texture atlas, so I'm going to say
| | 01:55 | Assets.ta.getTexture and it's called smoke.
| | 02:03 | Now we need to actually create that as
an instance variable, and this has now
| | 02:10 | instantiated our new particle system.
| | 02:12 | So now we need to set up its properties.
| | 02:16 | So much like a movie clip where the
movie clip needs to animate itself, we need
| | 02:20 | to add it to the juggler object.
| | 02:23 | We need to also do that
for our particle effects.
| | 02:26 | So we need to stay Starling and
make sure we import that class,
| | 02:30 | .juggler.add(smoke).
| | 02:36 | Now we need to add it to
the display list of our game.
| | 02:40 | Now the reason we are adding it to
the display list of our game, or our play
| | 02:44 | state, is we are going to be moving
these things kind of independently of each
| | 02:49 | other, because again, if we just move
this hero object, the particle system
| | 02:54 | inside of it, if we add it to the
display list here, is not going to be moving.
| | 02:58 | So we are not going to get nice trails
that go back and forth as we move our ship.
| | 03:02 | So that's why we are going to add the particle
effect to the display list of the play state.
| | 03:07 | So we are going to say play.addChild(smoke);
| | 03:13 | and that's a very important part.
| | 03:16 | Now what we need to do is to
actually start the particle system.
| | 03:21 | So we are going to say smoke and we
are going to call the start method.
| | 03:25 | Now if we want this to only last a
certain amount of time, we want to pass in a
| | 03:29 | duration here, and we will be
doing this for the explosion particles.
| | 03:33 | But for this, we want it to be constant,
because the ship is always going, so
| | 03:37 | we want the smoke particle to always be
running, and in that case, we can just
| | 03:41 | leave out the duration, and it
will automatically loop this thing.
| | 03:45 | Okay, so now in our update method, we
need to update the position of our smoke
| | 03:49 | so that it sticks with the position of our ship.
| | 03:53 | But the important thing to note is
we are going to be changing the smoke.x
| | 03:58 | because that's just essentially
changing the coordinate system.
| | 04:02 | What we need to change is the emitterX.
| | 04:07 | So it has an emitterX and emitterY property.
| | 04:10 | Those are the values we want to
change if we want to get nice side-to-side
| | 04:14 | movement of our particle effect.
| | 04:15 | So we are going to change that to
the x position of the hero, and then
| | 04:21 | smoke.emitterY, we are going to set
that equal to the y position of our ship.
| | 04:27 | But we are going to add 20 on it, so
that it looks like it's coming out of
| | 04:32 | the back of the ship.
| | 04:33 | Okay, let's save that, and let's check it out.
| | 04:36 | Now you can see we have our nice
particle effect that moves side to side.
| | 04:43 | It looks really nice.
| | 04:44 | I mean, one of the reasons I love
Starling is that it's so easy to do
| | 04:48 | these kinds of really rich particle effects
that look really nice and really realistic.
| | 04:54 | So that's our smoke particle effect.
| | 04:56 | Now we are going to focus on the
explosions which happen when a bullet actually
| | 05:00 | hits one of these aliens.
| | Collapse this transcript |
| Creating the Explosion class| 00:00 | So in the last movie we created our smoke
particle effect, which is attached to our hero ship.
| | 00:06 | Now we are going to create the explosion
effect which happens when a bullet hits an alien.
| | 00:12 | Now this one is going to be little
different because we are going to need to
| | 00:16 | create a lot of these potentially.
| | 00:17 | So we are going to need to
make sure that we manage them.
| | 00:20 | So we are first going to create an
Explosion class which is going to subclass
| | 00:24 | the PDParticleSystem, and then we are
going to create an ExplosionManager which
| | 00:29 | is going to help us track these in our game.
| | 00:32 | So I'm going to go to our objects
class and create a new ActionScript Class,
| | 00:37 | and I'm going to call it Explosion and
this is going to have a Superclass of
| | 00:42 | PDParticleSystem and click Finish.
| | 00:47 | So now in the constructor here it's
expecting us to send in the config and the
| | 00:52 | texture, so now we need to
embed that into our assets class.
| | 00:57 | So I'm going to copy the one that we
have for our smoke particle effect and
| | 01:02 | paste it, and this one is going to
be explosion.pex and we are going to
| | 01:10 | call this explosionXML.
| | 01:14 | Okay, so what I'm going to do now is
go back to my Explosion class and I'm
| | 01:18 | going to remove these from the
constructor because we are going to send them
| | 01:22 | into the super constructor.
| | 01:24 | And for the config, again, I'm
going to need to cast it to XML (new
| | 01:30 | Assets.explosionXML) and then we are
going to get our explosion texture out
| | 01:38 | of our texture atlas.
| | 01:41 | So we are going to say Assets.
ta.getTexture("explosion").
| | 01:50 | So now essentially we have a new
PDParticleSystem that's using the explosionXML
| | 01:56 | and the explosion texture.
| | 01:58 | Now we are actually going to be
managing these using an ExplosionManager class,
| | 02:03 | which we are going to create in the next movie.
| | Collapse this transcript |
| Creating the ExplosionManager class| 00:00 | So now that we've created our
explosion particle class here, we're going to
| | 00:04 | create an ExplosionManager to
help track these in our game.
| | 00:07 | So I'm going to right-click on the
managers package, New > ActionScript Class, and
| | 00:12 | this is going to be
ExplosionManager, and click Finish.
| | 00:18 | Now much like the other managers,
we're going to send in our play state to
| | 00:24 | the constructor, and I'm going to set
that as an instance variable, this.play = play.
| | 00:35 | Okay, so much like the AlienManager
and the BulletManager, we're going to use
| | 00:39 | an object pool here to
hold our particle effects.
| | 00:42 | These are the things that you don't want to be
instantiating in the middle of your gameplay.
| | 00:47 | So I'm going to create a variable
called pool, and that's going to be equal
| | 00:52 | to new StarlingPool.
| | 00:54 | and for the type it's going to be a type
of Explosion, make sure we import that.
| | 01:00 | And we're going to create 15 of them,
and again that's a number that you're
| | 01:05 | going to have to trial and error
depending on your game for the least number
| | 01:09 | that you can get away with.
| | 01:10 | And what we're going to do is to create
a public function called Spawn, which is
| | 01:15 | going to spawn a new explosion.
| | 01:18 | So public function spawn, and we're
going to pass in an X and a Y value for
| | 01:25 | where in the game we want it to spawn,
and this is something we're going to be
| | 01:28 | calling from the CollisionManager class.
| | 01:30 | So I'm going to say our X property of
type int, Y property of type int, we're
| | 01:37 | not going to be returning anything, and
now let's get a new explosion from the
| | 01:41 | pool, so I'll create a local reference
variable, I'll just call it ex, and we'll
| | 01:47 | say pool.getSprite() as Explosion.
| | 01:51 | And now we want to set the emitterX and
the emitterY property of our explosion,
| | 01:58 | and we're going to set it to that X
property that was sent in to this function.
| | 02:05 | We'll set emitterY = y, and now we want
to start our particle effect, so we're
| | 02:12 | going to call that start method.
| | 02:14 | But for this we do want to pass in a
duration, because we don't want this to be
| | 02:18 | like a sparkler that just keeps going.
| | 02:20 | So we're going to put 0.1 seconds in here
for the duration of the particle effect.
| | 02:26 | Now we want to add this particle effect
to our play state, so we're going to say
| | 02:31 | play.addChild(ex), and much like we did
for the smoke particle, we need to add
| | 02:40 | it to the juggler, so Starling.juggler.
add(ex), and what we need now is to know
| | 02:50 | when this particle effect is finished,
essentially it's going to blow up and
| | 02:55 | it's going to make all these stars come out.
| | 02:56 | We want to know when it's actually
finished, so that we can clean up after
| | 03:00 | ourselves and return it to the pool.
| | 03:02 | Well there is a complete event on
the PD particle designer class, so
| | 03:07 | we'll listen for that.
| | 03:08 | So ex.addEventListener and we want
Starling.events and we want the COMPLETE event.
| | 03:19 | And we'll just have it call a
function called onComplete, and go ahead and
| | 03:24 | create that method, and make sure we
are catching our event object as well.
| | 03:30 | Okay, so in the onComplete we
essentially want to clean up that particle effect
| | 03:36 | and return it to the pool.
| | 03:38 | So first I'm going to get a local
reference to it and so var ex of type
| | 03:43 | Explosion = event.currentTarget as
Explosion, and that gives us a reference to
| | 03:56 | the particle effect that is finished here.
| | 03:58 | And what we want to do most importantly
is to remove this from the juggler, so
| | 04:03 | Starling.juggler.remove(ex).
| | 04:09 | And now we want to return it to the pool,
and just to be on the safe side here,
| | 04:16 | we're going to do a check to make sure
if pool is not equal to null then we're
| | 04:23 | going to say pool.returnSprite(ex).
| | 04:28 | And the reason is once we get down to
our destroy method for this, it's possible
| | 04:32 | that this might actually fire after
we've killed the pool, so just to be safe
| | 04:37 | we're going to put that line in there.
| | 04:39 | So now we need a public function
which is going to be our destroy method.
| | 04:44 | So we're going to say public function destroy.
| | 04:51 | Now these particle effects are one of
the more trickier things to remove from
| | 04:56 | memory, so I'm going to show you how
we're going to go about doing that.
| | 05:00 | We're going to go do a for loop, so we
can loop through all the items in our pool.
| | 05:05 | So we're going to say for(var i:int=0;
| | 05:11 | i<pool.items, which is the items array in
our actual Starling Pool class, .length; i++).
| | 05:24 | And let's get a reference to that
item, so let's say var ex:Explosion =
| | 05:33 | pool.items i, and we're going to say ex.dispose().
| | 05:41 | So that's an important thing that we
need to do is to call the dispose method of
| | 05:45 | that particle, and then
we're going to set ex = null.
| | 05:51 | So after we do that, then we're going to
actually destroy the pool, so pool.destroy();
| | 05:58 | and then we'll set pool also equal to null.
| | 06:02 | And that will successfully remove
our particle effects from memory.
| | 06:08 | So now we have our ExplosionManager,
now we actually need to create that
| | 06:13 | ExplosionManager in our play state,
where we created the other ones.
| | 06:19 | So I'm going to come under CollisionManager
and create it here is equal to new ExplosionManager.
| | 06:29 | Now we could create this in the
CollisionManager class, but I prefer to create
| | 06:34 | it here in our play state, create that
as an instance variable, and we're going
| | 06:38 | to need to create this public, because
we're going to need to reference it from
| | 06:42 | our CollisionManager.
| | 06:43 | So now what I want to do is to go into
my CollisionManager class and I want to
| | 06:49 | make one of these explosions happen.
| | 06:52 | So here while we're testing between
bullets and aliens, if we determine that a
| | 06:57 | collision has happened, what we want to
do is to go play.ExplosionManager.spawn
| | 07:05 | and give it the position where we want
this to spawn, while we want to actually
| | 07:09 | do it from a.x and a.y.
| | 07:14 | And actually, let's move this before
we actually call those destroy methods, like that.
| | 07:22 | Okay let's go ahead and test it now.
| | 07:24 | We'll run, and now you can see we have
those cool particle effects happening
| | 07:30 | whenever a bullet touches one of
the aliens, and you can imagine easily
| | 07:35 | creating multiple of these types of
particle effects for different things that
| | 07:39 | happen in your game.
| | 07:40 | Now it's important to note that you can
also adjust properties like the color of
| | 07:44 | these particles at run time.
| | 07:46 | So let's say we also had red aliens,
and we wouldn't have to create a whole
| | 07:51 | new particle effect, we can just change the
particular color of these existing particle effects.
| | 07:56 | So really cool that we can easily add
these kind of eye candy effects to our
| | 08:00 | game using the particle extension in Starling.
| | Collapse this transcript |
|
|
9. Finishing TouchesCreating sound effects with cfxr| 00:00 | So when it comes to creating sound
effects for your games, you have a lot of
| | 00:04 | different options. You can go to sites
where you can buy sound effects, you can
| | 00:08 | search online for free sound effects,
but there are some nice tools that allow
| | 00:12 | you to create some nice sounds for games.
Now these are kind of simple sounds,
| | 00:16 | kind of retro sounds, but they work
for a lot of different types of games. So
| | 00:21 | there is a cool tool called sfxr, and
this is created for Windows, and if you go
| | 00:28 | to this URL here, you can actually
download that if you're on Windows, and I'll
| | 00:31 | show you a screenshot of what it looks like.
| | 00:34 | It basically allows you to really
quickly create sound effects for different
| | 00:38 | types of things like picking up a coin
or shooting or explosions, power-ups, and
| | 00:44 | it's a really nice tool if you
want to quickly create sound effects.
| | 00:48 | And there is a Mac port of this tool
also called cfxr, and you can get it from
| | 00:54 | this URL, and this is the one I'm
going to be showing you how to use.
| | 00:58 | So once you've installed this tool,
either the Windows of the Mac version of
| | 01:03 | the tool, you can essentially pick a
certain genre of sound, so I'll try Pickup/coin.
| | 01:11 | And if I keep clicking it, it will
essentially give me a random sound effect.
| | 01:15 | (sound effect)
| | 01:16 | And I can increase the playback volume here.
| | 01:17 | (sound effect)
| | 01:19 | So I can just keep clicking this until
there is a sound that I actually like.
| | 01:23 | (sound effect)
| | 01:25 | Like maybe that one, and now I
can export this as a WAV file.
| | 01:29 | Now in Flash we need to turn it into an
MP3, which I usually use Adobe Audition
| | 01:35 | for that, but there is lots of
different tools out there for doing that.
| | 01:38 | So let's say an explosion,
I'll click Explosion--
| | 01:40 | (explosion)
| | 01:41 | --and we can hear an example explosion.
| | 01:43 | And if I say Play looping--
| | 01:44 | (sound effect)
| | 01:45 | --it will play that sound in a looping
manner, and then I can come and start
| | 01:51 | adjusting some of these sliders to
change the properties of these sounds.
| | 01:59 | And again, this is a lot of just
kind of trial and error that you have to
| | 02:03 | go about doing.
| | 02:04 | (sound effect)
| | 02:05 | But again you want to play around with
these, now these are kind of retro 8-bit
| | 02:09 | kind of sound effects, and so if
you're making a game like that you can
| | 02:13 | definitely create some really
interesting sound effects here.
| | 02:16 | So let's say for jumping.
(sound effect)
| | 02:22 | Press a couple of these, and these
are kind of like Super Mario Brothers type sounds.
| | 02:25 | (sound effect)
| | 02:29 | Power-ups.
| | 02:31 | (sound effect)
| | 02:33 | And shooting.
| | 02:34 | (sound effect)
| | 02:38 | So definitely this is a tool that's
just fun to come in and play around with,
| | 02:42 | and again you're going to be exporting
these sound effects as WAV files, and
| | 02:47 | then you're going to
need to turn them into MP3s.
| | 02:49 | Now for our example, in our game, we're
not going to have to worry about that,
| | 02:54 | because I've actually included a couple
of sound effects in the assets folder,
| | 02:57 | we have an explosion.mp3 file, and a
shoot.mp3 file, which we're going to use to
| | 03:03 | incorporate into our game.
| | Collapse this transcript |
| Adding the sound effects| 00:00 | So now we need to incorporate
our sound effects into our game.
| | 00:04 | So we have two MP3 files in the
assets folder, explosion.mp3 and shoot.mp3.
| | 00:10 | So I'm going to come into my assets
class and we're going to embed those.
| | 00:15 | So Embed(source="assets/explosion.mp3"),
and now for class I'm going to create
| | 00:27 | a private static var and call it explosionSound
and it's going to be of type class.
| | 00:36 | And now I'm going to create a public
static variable, which is going to be our
| | 00:40 | actual sound object ourself, so public
static var explosion, and this is going
| | 00:47 | to be of type sound.
| | 00:48 | So we're only going to create a single
sound instance and we're going to use
| | 00:52 | that, and that's going to help us
to save on memory and performance.
| | 00:55 | So I'm going to copy this embed block.
| | 00:57 | So we're going to do the same thing
for the shoot sound, so I'm going to
| | 01:01 | change this to shoot.
| | 01:04 | Change this to be shoot sound, and
we're going to call our sound object shoot.
| | 01:12 | So now if we come into the init
function, let's initialize those.
| | 01:16 | So explosion = new explosionSound,
and we're going to do the same for
| | 01:27 | shoot = new shootSound.
| | 01:31 | Now there is a bug in Flash Player and
that when you first play a sound back
| | 01:36 | there is a delay because it
actually has to load it into memory.
| | 01:40 | So what we're going to do in our init
function is to just play it once with no
| | 01:44 | volume, in that way it's
actually going to load it into memory.
| | 01:47 | So we'll say explosion.play, give 0 for
start time, 0 for the number of loops,
| | 01:54 | and pass in a new SoundTransform object,
and to that we're going to pass in a
| | 02:03 | volume of 0, so that way we don't hear
it, and we'll copy that, and come down,
| | 02:10 | we'll paste this in and change it to shoot.
| | 02:13 | And again, that's going to make sure
that this is actually in memory so when we
| | 02:16 | actually want to play the sound,
I'm just going to do it right away.
| | 02:20 | So let's do that, let's go now to our
CollisionManager class, we want to play an
| | 02:25 | explosion when there is a collision
between the bullets and the aliens.
| | 02:30 | So what I'm going to do is to come
down in this if statement and I'm going to
| | 02:34 | say Assets.explosion.play, and that's
going to play that explosion sound effect.
| | 02:41 | Now another thing I want to do is to
play a sound when I'm actually shooting a
| | 02:47 | bullet, so for that I'm going to go to
BulletManager, and we're going to come to
| | 02:52 | our fire method and I'll just come down
at the bottom here, and I'll say Assets,
| | 02:57 | make sure we have that
imported, .shoot.play, like that.
| | 03:04 | And now let's go ahead and test it.
| | 03:09 | (sound effects)
| | 03:12 | And now you can see we have those nice
sound effects happening, so as I hold
| | 03:16 | down the Mouse button, I'm playing
that shoot sound, and we're getting those
| | 03:20 | nice explosions when a bullet
actually hits one of these aliens.
| | 03:24 | (sound effects)
| | 03:27 | So you can see incorporating sound
effects is actually pretty simple, it's
| | 03:31 | exactly the way you're used to doing
it in other areas of Flash development.
| | 03:34 | But again, the trick is definitely to
play it one time with no volume, to make
| | 03:39 | sure that that sound effect is ready in memory.
| | Collapse this transcript |
| Creating the Score class| 00:00 | So the last thing we are going to
add to our game is just a simple high
| | 00:04 | score text field.
| | 00:05 | And what I'm going to do is create a
new object class. I am going to go to my
| | 00:10 | objects package, say New > ActionScript
Class, and I am going to call it Score.
| | 00:13 | Now I am just going to subclass Sprite.
| | 00:16 | Now if you only literally wanted a text
field, you could in subclass text field.
| | 00:20 | But I am just using this because,
generally speaking, you might want to add more
| | 00:24 | to it in the future, and if so,
you need to display object container.
| | 00:28 | So I am going to subclass starling.
display.Sprite, and in the constructor here I
| | 00:34 | am going to create a new variable
called score, and that's going to be equal to
| | 00:38 | a new text field object, a
new starling.text.TextField.
| | 00:43 | And to the constructor of this I am
going to give it a width of 300, height of 100.
| | 00:48 | I am going to give it an initial text
value of 0, because we don't have any
| | 00:54 | score when we come in.
| | 00:55 | I am going to use the KomikaAxis font.
| | 01:00 | That's our bitmap font that we included.
| | 01:02 | I am going to give it a size
of 32 and a color of white.
| | 01:07 | And let's create score as an
instance variable in our class here.
| | 01:12 | So now what I am going to do is to align
the text, the horizontal line to write,
| | 01:16 | so I am going to say score.hAlign = "right",
and I want to add this score text
| | 01:25 | field to the display list, like that.
| | 01:27 | So now I am going to create a public
function that we are going to call from
| | 01:32 | anywhere in our game to
essentially add a number to our score.
| | 01:36 | And I am just going to call it
addScore and we are going to send in an amount
| | 01:41 | variable which will just be a number,
just in case there is a decimal value.
| | 01:46 | We are not going to return anything here,
and what we are simply going to do is
| | 01:52 | to reset the score text property
equal to, and then I am going to open some
| | 01:58 | parentheses here. I am going to
parseInt the current value which is in there,
| | 02:03 | score.text, and I'm going to
add the amount that was sent in.
| | 02:09 | So you are going to imagine maybe
there would be a negative number if we did
| | 02:13 | something wrong in the game.
| | 02:15 | I'm going to close that parenthesis
and then just do a toString value here to
| | 02:20 | turn it back into a string.
| | 02:22 | And that will successfully change that
text field's text based on the number.
| | 02:27 | Okay, so now what I want to do is to go
into my CollisionManager class and every
| | 02:33 | time a bullet hits an alien we
want to add an amount to that.
| | 02:39 | So what I am going to do is to say play.score
and we haven't actually created
| | 02:45 | this property yet in our play state,
and we are going to call addScore, and we
| | 02:50 | are going to add 200 to the score
every time a bullet hits an alien.
| | 02:57 | And now let's go to our play state, I
am going to come into the init function,
| | 03:01 | let's just do it after we create our
hero, and I am going to create that score
| | 03:06 | variable is equal to new score, and I
want to create that as an instance variable
| | 03:15 | and this needs to be public because
again we are referencing it from the
| | 03:20 | CollisionManager class and let's
add this to the display list. So
| | 03:27 | addChild(score) and let's set its X
property, score.x = 450, like that.
| | 03:37 | So again in our CollisionManager we are
going to add 200 to the score every time
| | 03:41 | a bullet hits one of the aliens.
| | 03:44 | So let's test that now.
| | 03:46 | We'll come in, we can see
our score in the upper right.
| | 03:50 | And every time I successfully shoot
one of the aliens you can see my score
| | 03:55 | is going up by 200.
| | 03:57 | So again we took a really simple
approach to a high score read out, again you
| | 04:02 | are going to want to do things as your
game gets more complicated, you may want
| | 04:06 | to subtract scores and all
different types of things could happen.
| | 04:09 | But that's a general approach in
creating a score object and providing methods
| | 04:14 | to allow you to add or
subtract from the high score.
| | Collapse this transcript |
|
|
ConclusionStarling optimization tips| 00:00 | So now I want to take a couple of
minutes and just go over a couple of
| | 00:04 | optimizations that we can do to our game,
and also just in general how you might
| | 00:08 | want to optimize Starling content.
| | 00:10 | So first of all Starling has blend
modes associated with it on display objects,
| | 00:16 | so if you have, let's say, a background
image that doesn't have any alpha in it,
| | 00:21 | you don't need to worry about that, you
can set your blendMode to none, and you
| | 00:26 | will get some performance
increase from doing that.
| | 00:29 | So in our background class where I have
these two image objects, what I'm going
| | 00:33 | to do is first set sky1, I'm going to
set its blendmode = and get a constant
| | 00:41 | out of the Starling.display.BlendMode class, and
we are simply going to set it to BlendMode.NONE.
| | 00:48 | And I'm going to do that also for sky2,
and that's just a little thing but will
| | 00:54 | give you some performance increase
because again we don't need to worry about
| | 00:58 | blend modes on those background images.
| | 01:00 | Now another area which we can optimize
quite a bit is in our CollisionManager
| | 01:04 | class, because remember this update
method gets called on every frame, so that's
| | 01:09 | 60 frames per second that we're checking
for these collisions, which is way more
| | 01:13 | than we need to actually check
because we don't need to be checking for a
| | 01:17 | collision 60 times every second.
| | 01:19 | So we can reduce that a little bit.
| | 01:21 | Now I'm going to show you how you can
do that. I'm going to create a class
| | 01:25 | property up here, private var, and I'm
going to call it count. It is going to be
| | 01:32 | type integer, I'm going to set it to 0.
| | 01:34 | So at the bottom of our update
function, I'm going to increment that every
| | 01:38 | time we come in here.
| | 01:39 | And now I'm going to test if count is an odd number,
then we're going to do the bulletsAndAliens
| | 01:45 | collision detection check.
| | 01:46 | If it's an even number we'll do
heroAndAliens, that will make it happen at
| | 01:51 | least half as much, but we could
reduce it more but for this we're just going
| | 01:55 | to do it like this.
| | 01:56 | So I'm going to create an if statement.
| | 01:58 | Now a really quick way to test if a
number is even or odd is to say if(count
| | 02:05 | and we can use the bitwise & operator,
if(count & 1, that's going to mean it's
| | 02:12 | an odd number, so we're going to do
bulletsAndAliens and then we're going to do
| | 02:16 | our else statement.
| | 02:18 | And if it's an else, if it's an
even number, then we're going to
| | 02:22 | check heroAndAliens.
| | 02:24 | So again, this will make it so each
of these collision checks only happen
| | 02:27 | every other frame, which will give us
some performance increase, and again, you
| | 02:31 | can adjust this to maybe happen every
four or five frames, again depending on
| | 02:37 | how things are working in your game,
but this will give us some nice
| | 02:40 | performance increase.
| | 02:42 | Now another thing that we can do is to
set the touchable property of display
| | 02:47 | objects to false, if they don't need to
be interactive, meaning, we don't need
| | 02:52 | to click on these items.
| | 02:54 | Now in our game, again, since we're
using the mouse events on the actual
| | 02:58 | stage we're not going to need to
listen for touch events on any of these
| | 03:02 | objects in our play state.
| | 03:05 | Now in the GameOver and Menu states we
have those buttons so we're going to need
| | 03:10 | to do that, but in our actual play state,
we can come here in our constructor,
| | 03:18 | and actually just say touchable = false;
| | 03:26 | and that will trickle down to all of the
other objects that are actually in our play state.
| | 03:32 | So if I actually try this now, you can
see that everything is still working fine
| | 03:38 | in my actual game, because again, we're
listening for those mouse events on the
| | 03:43 | stage, and we're not needing to
interact with the mouse on any of the objects
| | 03:47 | actually inside of the play state.
| | 03:50 | So again those are some things you can
do for performance. A really important
| | 03:53 | one, of course, is using object pools
because while you may not see a huge
| | 03:58 | difference on the Desktop, if you
were to take this game on to a mobile
| | 04:01 | device, you would see a lot of
stuttering if you weren't using object pools
| | 04:06 | for your game.
| | Collapse this transcript |
| Helpful Starling resources| 00:00 | So before I leave you, I just wanted
to share some helpful resources as you
| | 00:04 | continue on with
developing Starling-based games.
| | 00:08 | Well there are some awesome
resources just on the Starling framework site
| | 00:12 | itself, so gamua.com/starling.
| | 00:16 | And if you click on the Help button,
you'll see first a First Steps guide,
| | 00:20 | which is really good;
| | 00:21 | your documentation reference, which of
course you are going to want to have on hand;
| | 00:26 | and there's a great Wiki, if we
click on this, there's a whole bunch of
| | 00:30 | tutorials, this is where you can also get
information about extensions that are available.
| | 00:35 | So if I go to Tutorials & Code Snippets,
there is a bunch of different tutorials
| | 00:40 | both from Gamua and from the community itself.
| | 00:44 | Now one of the best places if you
are having difficulties or if you have
| | 00:48 | questions is to go the Starling Forum.
| | 00:50 | And this is an incredibly active forum, so
you can either search, click on one of
| | 00:55 | the tags, if there is a topic that
you are looking for, let's say collision
| | 00:59 | detection, and it's just a really
nice active community. So I definitely
| | 01:02 | recommend signing up here and you can
learn a lot just by checking out the
| | 01:07 | problems that other people
have encountered and fixed.
| | 01:10 | Now another place is my tutorial site
at gotoandlearn.com; obviously I have
| | 01:15 | tutorials on a lot of different
topics, but you can see I have various
| | 01:19 | tutorials on Starling, like how to
incorporate physics engines and particle
| | 01:24 | effects and things like that.
| | 01:25 | So definitely check that out.
| | 01:27 | My evangelism colleague Hemanth Sharma
also has a tutorial site that you can go
| | 01:32 | to, and he has a whole sequence of
Starling tutorials in addition to other nice
| | 01:37 | game-related tutorials.
| | 01:39 | But definitely the Starling web site
itself, in this Help section, is the place
| | 01:43 | to go and you'll find links off to a
whole bunch of really helpful resources as
| | 01:49 | you go about increasing your
knowledge about the Starling framework.
| | Collapse this transcript |
|
|