Create an Epic War Game in Flash: Part 1


This Cyber Monday Envato Tuts+ courses will be reduced to just $3. Don't miss out.

Creating a game is definitely one of the most involved tasks in the world of programming. If you want to write your own game, be prepared to spend a lot of time trying to figure out how to work around a lot of different problems. My mission here is to help make this process a little bit easier.

Also available in this series:

  1. Create an Epic War Game in Flash: Part 1
  2. Create an Epic War Game in Flash: Part 2

In this two-part tutorial we'll be creating a top-down war game from scratch. It will implement many different concepts from building a background based on xml data to breaking colors into separate channels using bitwise operators. The game itself will not be like some MMORPG (it would probably take several volumes of a book to describe the process of complicated game creation). This game will only have a couple of types of player and enemy vehicles to check the movements, collisions and weapons, and two missions just to make sure everything works properly (you'll be able to create more missions anytime you want using the unified engine that we'll make in this tutorial).

The Game

Before we dive into any work, take a look at what the final result will look like, after completing both parts of this tutorial. Use the "View Demo" link above to check it out!


Let's begin by taking a quick look at the tools I used to create this game:

  1. FlashDevelop 3.2.2 (you may use Flex Builder or Flash authoring tool instead, but I'd recommend you to write the classes in FlashDevelop because it's much easier). It's absolutely free of charge, and can be downloaded here
  2. Flash IDE (Adobe Flash CS4). I used it only for 3 things: to create movie clips, as a container to hold most of the game assets, and as the compiler.
  3. Adobe Photoshop CS5 or below to edit bitmaps
  4. Google SketchUp 7 to model different vehicles, and Vray to render them (Of course you can use any other software which you're comfortable with)

Now look at the main features we'll be working towards:

  1. Create XML database that will be used to store missions data.
  2. Create the engine that will build game missions based on the information from XML database
  3. Write the camera object that will follow an active player character
  4. Create player and, of course, the enemy that will be able to detect player objects and destroy them.
  5. Make the system of collisions and destructions.
  6. And finally, the weapons! :)

It's just the general list of tasks, there's much more to do in reality, so, let's get started.

Step 1: Setting Up a Project

In this lesson we'll create all of the main classes needed to visualize the game.

At the beginning, we need to set up a project. Open up FlashDevelop and go to Project > New Project.

Choose Actionscript 3 Flash IDE (in case you use Flash to compile everything) project then directory and name for it and click ok.

Now right-click the newly created project file and chose add > New XML File

At this step, let's make something simple. Add just a couple of nodes that will contain the name of the mission and the map source path.

This is how our XML file's body should look for now:

Notice that the name of the mission is an attribute, not a separate node (we'll be using attributes a lot) To make an attribute just type its name (which can be any word) inside any tag (but make sure the tag's name goes before the attribute), put an equals sign and quotes. Everything inside quotes will be considered the attribute.

Ok, since the folder containing the map doesn't exist yet, we need to create it now. Again, right-click on the project file but now go to Add > New Folder. Give this folder a name of "maps" (without quotes) and put a map.jpg file inside it.

Now open up Flash IDE and create new Flash File (Actionscript 3). Save it as WarGame.fla in the same folder with your project.

Right-click the stage and change the document properties like so:

Step 2: Parsing XML

It's time to create an XML loader class. Since we want to keep it all clean, lets put our initialization classes into a separate package. Right-click the project file in FlashDevelop, go to Add > New Folder. Give it a name of "builder" then right-click this folder and choose Add > New Class. Call it "xmlParser"

This is what the structure should be like:

The code for is:

Now let's examine this line of code in detail:

When the xml is loaded and assigned to a variable, the method assignAssets() dispatches a custom event "MyEvent" (It can do so because the Sprite class also extends EventDispatcher). MyEvent event doesn't exist yet, so it's time to create it.

Right-click the project file in FlashDevelop (just like you did before) and go to Add > New Event. Give it a name of

You don't have to worry about the complexity of the Event code, FlashDevelop will do it all for you. You will get a code like this:

All you have to do now is to add a public static constant right before this line:

This is the final version of the event code:

What is the word "static" for? Static variables or constants do not have to be instantiated, which means they are created right away, without the keyword "new" and can be accessed from other classes directly. Sometimes it's very handy, and this event is not the only case we'll be using static constants or variables in our game.

Step 3: MapBuilder Class

At this point we have all means to load a game map source, but there's no class to build map. Let's fix it now. Right-click the builder folder and add a new class "". FlashDevelop creates a new class but does not extend it. You'll have to do it manually. This class won't need a time line so it will extend Sprite. Once you write "extends Sprite" and hit enter, FlashDevelop will automatically import the Sprite class to our library path.

Create a public (class level) variable with the data type of xmlParser.
Here's the code for the class at this point:

Look at the event listener. Remember, MyEvent.MAP_STRUCTURED is dispatched by xmlParser class when the XML file is loaded and assigned to a variable. In this class we listen for that event and when it occurs, trigger readyToBuildMap() method.

Important note: Only the objects that dispatch a custom event can listen for that event! This means that only instances that can listen for the MAP_STRUCTURED event in this case are the instances with xmlParser data type.

The method itself isn't created yet but there's a good trick in FlashDevelop. Click on the method's name "readyToBuildMap" and hit Ctrl + Shift + 1.
FlashDevelop will show you this hint:

Select "Generate MyEvent handler" and it will create the method for you (of course you can create it all manually in case you're not using FlashDevelop).

Step 4: Testing MapBuilder

A good programming practice is to write everything in small pieces. So all we will do now is add a little trace statement inside this method, just to make sure everything works ok.

Finally open up the WarGame.fla file, and for the document class name type in builder.MapBuilder (remember this is the name of our package).

Now hit Ctrl + Enter on PC (Command + RETURN on mac) to test it.

Wow! It works.

If you get the same result, you did everything correctly. If not, go thru all the steps once again more thoroughly.

Step 5: More Methods and Variables for the MapBuilder

Open up MapBuilder class in FlashDevelop and add new variables:

The first one is a very important variable. It will let our MapBuilder know what map source and assets positions to use in a particular mission. It is equal to 0 now because XMLList is like Array. It counts from 0, not 1. So the first mission will have to use 0 node index.

The second one is a BitmapData object that will be used to copy our map data into.

Since the map is supposed to be tile-based, let's add two more variables to hold the numbers of rows and columns.

The data type for them is integer because we will use only full value tiles (no halves).

Step 6: What Kind of Tiles to Use?

Talking about tile engine construction, we cannot leave behind the tiles themselves. Many tutorials that you can find on the Internet work with tiles based on sprites or movie clips using addChild() method every time they need to add another tile. This approach has a lot of disadvantages.

And the biggest of them is a huge resource consumption. Really, try to add 300 (200x200) MovieClip tiles to the screen and see what happens. This will terribly slow your system down (I tried it myself and Flash Player even froze a couple of times).

Another disadvantage is their "floating position". If you add e.g. 100 MovieClip tiles to the display list and try to move some character over them, you will see how they vibrate. This bug doesn't look very attractive, believe me.

So, the experience of many Flash developers shows that the best way to build tiled map is to use a single BitmapData object, then, after the map is built into it convert it to Bitmap and add to the display list.

Step 7: Bitmap Creation

Let's get started with map creation. First of all, we need a "map.jpg" the path to which we used in our xml file before. To create map.jpg you will need any seamless texture. In this case it will be grass. The texture size for this project must be 200x200 px. So open it up in Photoshop and go to Image > Image size. If it's bigger or smaller, make it 200x200.

Save the tile to our project's map folder as map.jpg.

Step 8: Enumerated Tiles for Test

Actually, one tile will be enough to use with this tile engine. But as we need to test it, we'll create at least 2 more tiles in one background and number them. In Photoshop, double-click the word Background in the layers palette to unlock it.

Then go to Image – Canvas Size. And make the canvas width 200%, like so:

Pay attention to the Anchor. Once it's done, go to View – New Guide and add 2 vertical guides for 200 and 400 pixels.

Now Alt-Click the tile and simply drag it to the right. Repeat it once again to get this:

Now, choose Type Tool (T on your keyboard) and put numbers 1 to 3 over each tile.

Save it as map2.jpg to the same folder as map.jpg.

Step 9: Update XML

Since we have our tiles ready. It's time to update the XML file. Open up Assets.xml in FlashDevelop and add node containing 2 attributes for rows and columns to it.

This will let the engine know how many tile to add vertically and horizontally. (Note: I've changes map.jpg to map2.jpg for now. Pay special attention to this.)

I've added types of tiles for each row (1,1,2,2, 2,2,2,1, 3,2,2,1, 1,1,1,1)
The numbers are supposed to represent the tiles from map2.jpg.

Step 10: More Methods and Variables for

Let's get back to I've modified it's code now. New variables and methods were commented so you can understand what they're supposed to do:

If you trace _levelDesign at this point, you'll get the next output:

This signals that everything's just fine. Hit Ctrl + Enter (or F6 in FlashDevelop) to check it out.

Now it's time to initialize out _rows and _cols variable. Modify the loadBitmap() method like this:

Notice, that we can now use _levelDesign variable instead of typing the whole path again. And pay special attention to the "at sign" @. It's used because rows and columns are the attributes of the tiles node, not the stand-alone nodes. You can trace _cols and _rows if you want, and you'll get 4 for each one. But we won't do it here.

Step 11: Loading Map Image

To load something like an image you will need a Loader object. So, add the loader variable to your MapBuilder:

Now go down to loadBitmap() method again and initialize the _loader. Basically, you will also have to add one more function at this step. What function? Let's look at it now to see what we're getting into.

onLoadComplete is an event handler for the event that will be triggered after our _loader loads the map. Just put a trace statement into it for now and hit Ctrl + ENTER to test it.
If you get "map loaded!" string in Flash's output panel – everything works correctly. This means that you can now use map2.jpg to actually build the game's background from its tiles.

Step 12: Globals Class

Globals is a special class which is not obligatory but it will definitely make the process of game creation a little bit easier. What is it used for?

Well, it's used as a centralized storage container for some data that is supposed to be used many times by many other classes. For example, the class may store some constants that convert angles from degrees to radians and vice versa, or to keep some dimensions like the width and height of the tile. That's what we'll use it for. Right click the project file in FlashDevelop and go to Add > New Class. Name it Globals. And all we will do with this class is add three constants.

Here's the body of it:

That's it for the class. You may close it now.

Step 13: Main BitmapData Object

In order to create a map using our palette we'll need a BitmapData object to copy the palette's pixels to. The BitmapData object must be the size of the map we wanna create. So, let's go back to the MapBuilder class and declare two more variables.

The first one is the BitmapData object we need, and the second (note: it's declared as public) is a Bitmap to hold our BitmapData since the BitmapData object cannot be added to the display list itself.

Now go down to the loadBitmap() method and instantiate _bitmapData and _bmdContainer

The parameters for BitmapData object are: width, height, transparent, and fillColor.

The width of the BitmapData equals the number of columns multiplied by tile width which we've put into our Globals class. The same with height. It will be transparent so you may choose any fill color. Then, pass this _bitmapData to the _bmdContainer's constructor.

Step 14: Using Palette

Declare three more private variables in MapBuilder class:

And go down to the onLoadComplete() method. Delete the trace("map loaded!"); statement.

Let's break down this line:

Actually, the program knows that the loader's content is bitmap now, but we want to make sure it's bitmap in any case, that's why the _loader content is passed to the Bitmap's constructor. It's like you're telling the program "Yes, it's bitmap, so treat it the way you treat bitmaps".

If you didn't understand what bitmap it is, it's our map2.jpg.

Step 15: Populate _tileArray with Tiles

As you can see, onLoadComplete() method calls tileMap() method which is not created yet.
Lets fix it now. Create this method under onLoadComplete()

Let's test it now. If you get this output: works alright.

Check Milestone

It looks exactly like the output we had before but actually it's not an XMLList anymore, it's an array of tiles that can be used to tile map.

Step 16: Tiling the Map

At this point we need six more variables in our MapBuilder:

The first two are the coordinates in the _bitmapData object to which each tile is supposed to be copied. Right now they both equal 0 and it means the the first tile will be copied into the top left corner of the _bitmapData. These coordinates will change after each tile is copied (you'll see that a bit later)

_tileRectX and _tileRectY are the coordinates of the top-left corner of the rectangle which copies pixels from the palette.
These coordinates vary depending on the type of tile in the _tileArray.

If you look at the palette from Step 8, it has three types of tiles. So if tile type is 1, _tileRectX and _tileRectY will both be 0 but if the type is 3, _tileRectX will be 400.

The width and height of this rectangle equal to width and height of the tile (Globals.TILE)

tileRow is a variable that holds the row's number into which the last tile was copied (You'll understand it later).

And tileHorCoord holds the horizontal coordinate of this tile.

Now let's update tileMap() method:

And finally, let's overview the whole MapBuilder class:

If you test it now, you'll get this output:

Compare these numbers to the ones in Assets XML (1,1,2,2, 2,2,2,1, 3,2,2,1, 1,1,1,1) and if they are the same for each row and column, the engine works! Praise yourself :)

Step 17: First Map Design

The design with numbers doesn't look very attractive but at least we know everything works. You may now delete map2.jpg file and change the "path to map" in Assets.xml back to map.jpg. And don't forget to change tile types to 1 here:

...because map.jpg has only one tile by now. Open it up in Photoshop again and unlock the background layer like you did before (Step 8). Go to Image > Canvas Size and increase its width by 200 percent and height by 400;

Now Alt–click the tile and drag it until you fill the whole area. Well, generally speaking, do the same work you did in Step 8 but for the bigger area.

At this step you can make each tile unique. I added road with a couple of turns, crossroads and a small pond. You can do whatever you like and make this map as big as you want. As it's not a graphics tutorial, I won't explain the way I made everything up in details, I'll show you just a final result.

We'll need 2 versions of the same map. The first one is the actual map we'll use in our game:

...and the second is the numerated map, in order to know what tiles to use and where.

Let's try and design our first map. First of all, decide how many rows and tiles you want. If you're following along, we'll make the map 5 x 6. Not very big but it will definitely need more room the the stage can give it. That's what we need.

Open up Assets.xml and type this:

You can put tabs after each row to make it look cleaner. XML ignores white spaces.

Check Milestone

Step 18: MAP_BUILT Custom Event

The MapBuilder class is almost ready, except for two things. Right now WarGame.fla calls its constructor method and does not check if the map is already built or not. To fix this, open up and add one more constant to it:

Now, since we have another custom event, we can add it to the MapBuilder class. Open up, find this line:

And put this line:

right below it.

What is it for?
This event is like a permission that lets the program add another stuff only after the map is ready. Just to make sure that nothing is under the map when it's added to the display list. It wouldn't be so good if some tank or jeep moves underground :)

Step 19: Last Big Stroke for MapBuilder

You can now build a map using MapBuilder engine but, imagine, if you want to build a map that's much bigger than the visible part of the screen. You just wouldn't know what coordinates what tile is at. So you will definitely need some debugging grid that will define borders between tiles, show their coordinates and types. It may sound a little scary but actually, can be fixed pretty easily.

Let's do it now.

Add three more variables to the MapBuilder:

It's time to initialize these variables.
Find this code:

and put this:

right below it.

Now, put this line:

under this:

Initialize _container in the constructor and add it to the screen:

find this line once again:

and change it to:

It's needed to visualize the debugging grid. If you don't do this, your grid will be placed under the map and you just won't see it, even though it will exist. Doing it, you're placing the container to the stage before anything else, so the grid will be added above this anyway.

Now create a private function setDebugger().
Here's the body of it:

That's it. You just have to call this method.
Find this line:

and put this right below it:

Ough, you may probably be a little confused now. So let's overview the whole class just to make sure you did everything right:

You can turn the debugging grid on and off anytime, just commenting and uncommenting this line:

Click to Check Milestone

Step 20: Introducing Camera

The camera object in the game has nothing to do with a real camera. Basically it's just a container that will hold all of the game objects.

Right-click the project's file in FlashDevelop and add a new Class. Call it Camera and just put this code inside:

Now look at the constructor. Its first parameter is a parent that camera will be added to. Since we don't know what type of parent will use yet, its data type is DisplayObjectContainer. Because Sprites, MovieClips and even the Stage itself are all DisplayObjectContainers.

So, in order to add camera to the display list we will only need to pass a parent object to its constructor later. The second parameter is the location of the top left corner of the Camera object. This is more than enough for the camera. You'll see how to use it a little bit later.

Make sure you have the same files structure at this point.

Step 21: Game Structure Class Creation

Right-click project's file again and add another class. Name it GameStructure.

Now open up WarGame.fla and change its document class from builder.MapBuilder to GameStructure.

If you test the game now it will not show anything at all. Just a blank screen. From now on we have to initialize the map construction from inside the GameStructure class.

If you test it now, you'll get the exact same result as in Step 19 but in this case MapBuilder was not instantiated by WarGame.fla file.

Step 22: Keys to Control Camera

In addMap() method, add two event listeners:

And once you do it, create event handlers for each listener:

Before you can add any code to these methods you need to declare four boolean variables for each arrow key:

They will be true or false according to the key state to which they're tied.

Step 23: Populate releaseKey() and buttonControls() Methods

Go to releaseKey() method and modify it like so:

This method is called every time any key is released. The switch statement checks the key code of the released key and according to this reaches one of the blocks.

The buttonControls() method will do more job that this one. But for now it will only need to keep track of these four variables and ENTER_FRAME listener.

On to buttonControls(). Here's the code for buttonControls() method:

To understand what it does, let's look at one of the "if" statements:

When one of the arrow keys is pressed, this method is called. Then it checks what arrow key exactly was pressed. For example it was left arrow key. It turns leftPressed variable to true and then check if the camera has an event listener for Event.ENTER_FRAME. And in case the camera already has event listener it does nothing. Else it adds the event listeners to the camera which calls moveMap() method (which doesn't exist yet but we're about to create it).

What is it for?

It's pretty simple; the more ENTER_FRAME listeners you have in a program, the more calculations your computer has to make every frame, the slower your system works. And this construction makes sure that camera has only one ENTER_FRAME listener in any case.
The other blocks do exactly the same job but for other arrows.

Step 24: Moving The Map With Keyboard

The only thing left to make our map move is moveMap() method. Let's create one.

You can test it now, and you'll probably think there's a bug with this method, because doesn't let the map get back exactly to 0 x-position when you move it to the right. But I can assure you, there's no bug, you will understand why when we add come characters to the game, but for now, let's leave it as is.

And the last part of the method:

Checks if no key is pressed and if so, removes ENTER_FRAME listener from camera.

Overview the whole class in case you have some problems with it:

Click to Check Milestone

Step 25: Additional Assets: Trees and Houses

To add some trees and houses to the game we need another BitmapData object and Bitmap to store it. So, let's create two new variables in our GameStructure class.

And, of course add these objects to our Assets.xml.

I added only one tree for now, just for a test.

Step 26: Create Assets Palette in Photoshop

Open up Photoshop and create new file 600 x 200 pixels, and transparent background.

Now go to View – New Guide. And add vertical guide at 200 px. Do the same for 400 px.
You'll get three imaginary cells, to which you can add different assets.

I've modeled a house roof in Google SketchUp and found a fir tree in SketchUp free Warehouse
You can add any graphics you like. Press Ctrl+Shift+Alt+S or just go to "File > Save For Web and Devices" and save it as statics.png (png24) to the same folder where you have map.jpg.

Step 27: Loading Assets

Open Assets.xml and right under this node:


add one more node: maps/statics.png

Add one more variable to GameStructure class:

This variable needs to be instantiated in addMap() method. I've modified it and removed camera.addChildAt(map, 0); line. We'll add it again later in another method.

Don't forget to create event handler setEnvironment():

If you test it now and get blank stage and "set environment" string in the Output panel, everything's alright.

Let's instantiate treesBMD and treesBM variables:

The width and height of treesBMD must correspond to the width and height of the map. It must be transparent; fillColor isn't important, choose whatever you want or leave default.

Update setEnvironment() once again:

Notice, I've created new Loader object to load assets.png.

The URLRequest is a path to assets.png taken from Assets.xml. We can do it this way because _assets is an instance of xmlParser and so has access to its public variable missionAssets.

[map.mission] is a node index that is equal to the current mission in MapBuilder class.

Now create assetsLoaded() event handler:

Step 28: Parsing Path to Assets and Placing Them

At this point, we can add a block of code that will copy trees and houses to our treesBMD.
For this purpose we need to update assetsLoaded() method.

In each case we copy pixels to treesBMD bitmap data from our statics.png's bitmap data. The pixels are copied from the rectangular area which represents the area in our statics.png. The Point objects is the coordinates of the place in treesBMD where the pixels will be copied to. These coordinates are taken out of Assets.xml.

Check Milestone

Step 29: Organizing Environment

Having the engine built, all we need to create a mission map is to type all necessary objects into our Assets.xml. I've already made one map:

You can use this or create your own map.

After you finish with the map, open up MapBuilder class and comment out setDebugger() method call

to remove the debugging grid.

Check Milestone

Step 30: First Test Character

By now we have a map and a camera but still we can't see how the camera follows the characters since we don't have a single character. It's time to create one for testing.
I've modeled I very primitive tank in Google SketchUp:

And rendered the top of its body and turret with V-Ray. Basically it has only turret and body. No tracks, no wheels etc. You won't need a detailed tank because it will be so small that it's going to be hard to see any details.

Next I opened turret and tank body in one Photoshop document:

...went to Image > Image Size and made it 30 pixels wide with "constant proportions" checked. Then I right-clicked each layer and converted it to smart objects. Once again I right-clicked these smart objects and chose "Edit Contents". Thus I could open tank's body and turret in separate documents and then save them for web and devices as png 24.

Step 31: Assembling Tank MovieClip in Flash

If you're following along, open up Flash and go to File > Import > Import to Library. Navigate to the folder where you saved your tank and turret images, select them both and import to library. Or you can just select the images in the folder and simply drag them onto your library panel. As they appear in the library, you have to change their properties. Right-click each image and choose Properties. For the compression select lossless and check allow smoothing.

Now go to Insert – New Symbol. Create new MovieClip symbol and call it Tank. After the symbol is created go to library and drag the tank's body onto the stage, align it like this:

Then convert this body to Movie Clip (Hit F8). Give it any name (it doesn't matter).
Go to its filters panel and add new drop shadow filter.

Lock the body's layer and create new layer above it. Call it turret, and drag an instance of the turret from the library.

Also convert the turret to Movie Clip and give it any name. Then click it to select (if it's not selected yet) and give it an instance name of mTurret

Don't forget to save the file.

Step 32: Custom Class for the Tank.

Go back to FlashDevelop, right-click projects file and chose Add > New Folder. Name it "tanks" (without quotes). Then right click this folder and add new class. Give it a name of Ptank (for player tank). The class must extend MovieClip since we'll need its timeline for animation.

Now open up Flash and find your Tank MovieClip in the library. Right-click it and go to Properties (or Linkage in CS3). Check Export For Actionscript and give it a full path to your Ptank class. Also clear the "Base class" entry box since you don't need this line any more.

Click OL, and if it doesn't give you any errors, everything's right, and you've successfully attached Tank MovieClip to your custom class.

Step 33: First Modification to Ptank's Constructor Method

The tank will be added to stage just like camera. So first thing to do is modify its constructor method.

The first two parameters are the same as parameters for camera, and the third one will let the program know what angle the tank should be at when it's first added to stage.
Right now we have all means to add the tank to the screen. Let's do it. Open up in FlashDevelop and in the assetsLoaded() method, right below this line:

...add new tank:

The parent object will be camera, position it at 100 x and 100 y and rotate the tank by 90 degrees. One more thing you need now is to create an array of player's objects and push tank into it. You'll understand why later, just create the array now:

Then, right after the line where you created tank, push it into this array:

If you test it now, you should see new tank in the top left corner, but of course it won't respond to your mouse or keyboard input.

Step 34: prepareToMove() Method

In order to move tank, we need to add several variables to Ptank class:

Step 35: Tween Rotation Drawback

As you can see I used tween to rotate tank to the destination point. It would be just perfect if tween had not had a little problem. When you use tweens for changing rotation property of an object it always chooses the shortest way from one angle to another between 0 and – 180 and 0 and 180 and if you get rig of all negative angles it will choose the angle between 0 and 360.
I know it sounds very confusing, so I'll try to explain it in a more practical example.
Imagine your tank is turned at 350 degrees and you click at 10 degrees:

The red point is where you click. Now guess what will the tank do? Will it rotate Clockwise or Counter Clockwise?
It will rotate clockwise because if it rotated CCW it would have to go to "370 degrees" but it cannot figure this out itself because there's no 370 angle in its coordinate system, even though it would look more natural. The code I've designed resolves this problem and the object rotates naturally every time. It's pretty complicated but you can guess what it does if you look through it very carefully.

Step 36: Method to Move Player Objects

All of our game objects that belong to player will be moved from inside GameStructure class. For this purpose we need to add MouseEvent.CLICK listener to the Camera object.

Open up, find where you added listeners for KEY_DOWN and KEY_UP events and add MouseEvent.CLICK listener right below them:

Now create event handler called moveObjects.

Check Milestone

Step 37: moveMe() Method

If you test the game right now, you can see how tank reacts to the mouse clicks. It turns but doesn't move. Lets create a method that will fix this. But before we can move the tank we should define its speed.
Add one more variable:

And initialize it inside of prepareToMove() method:

So every time you click the speed resets to 2 despite its current value.
Go to prepareToMove() method and find this line:

Add Event.ENTER_FRAME listener right after it.

And create event handler:

(I won't explain this code 'cause I had already explained it in one of my previous tutorials
The tank is able to move now but it never stops. In my previous tut I used Math.abs() to stop tank, nevertheless we won't do it in this game because it stops tank immediately after it reaches the destination but we need it to slow down gradually. So, we'll use a Pythagorean theorem to solve this problem.

Step 38: Slow Down Gradually

Update moveMe() method again:

I won't explain the theorem here, I'll just say that the two cathetuses -- shorter sides of a right-angled triangle -- are the distances to destination point at Y and X directions. I just took the tank's current position point, subtracted it from destination point and thus I found 2 cathetuses. And the distance that is left for out tank to go is hypotenuse. It's actually the square root from the sum of cathetuses.

You can trace it to show how it veries when the tank moves.

There's a couple more things to do to stop the tank.
Add an "if statement" to moveMe() method:

I think it's pretty clear. When the distance to go is less than 50 pixels, the tank will decelerate until its speed reaches 0 or below, and then ENTER_FRAME listener that moves tanks is removed.
To reader: If you wanna test your skills, try to figure out a way how to make tank accelerate gradually, using the same approach.

Step 39: Rotate Turret

To rotate the turret to face the direction of your pointer, you will just need to add these three lines to the top of the moveMe() method:

Note: mTurret object is nested inside tank and despite the tank's current rotation it thinks it's rotated at 0 degrees so we must take the tank's rotation into consideration and subtract it from the turret's rotation.

There's one little problem with it right now. Remember, when the tank reaches its destination, the ENTER_FRAME listeners are removed so the turret will also stop aiming at the pointer when the tank stops. Actually, we won't use this ENTER_FRAME listener later in the tutorial (when we make a centralized controls system) but at this point let's just fix this little trouble real quick.

Go to the top of your Ptank class and declare one more variable:

Now go to moveMe() method and add all code you see there (except for the code that rotates the turret) into this conditional statements:

And one last thing find where you added event listener for ENTER_FRAME, and add this line right after it:

and add this line:

instead of this:

Test the game.

Check Milestone

Step 40: Camera Tracking

The last thing we do in this part of the tutorial will be active camera tracking.

Before the camera can follow the tank, it should know where it's moving. So we need two more variables for

Then modify moveMe() method adding this code to the end of it:

Just to make sure there's no confusion about anything, look the the class's code in its entirety:


Well, that's it for Part 1 of the tutorial, you may test the game now. In the next lesson we'll create the system of collisions with another vehicles and static objects like trees and houses. The system of water detection, some basic artificial intelligence for enemies that will let them find player objects and destroy them, the system of player objects selection, and of course the weapons.

I hope you enjoyed following along so far :)