Creation of a complete Flash Astro-PANIC! game

If you havent’t not already bought Flash Game Development by Example and want to see how in detail I am explaining every game, after publishing the guide to Tetris creation, here it is the chapter covering Astro-PANIC!, with some minor change to make it fit on the blog.

Astro-PANIC! was released as an all machine language Commodore 64 game to be typed in the February 1984 issue of COMPUTE!’s Gazette magazine. At that time there wasn’t any blog with source codes to download or copy/paste into your projects, so the only way to learn from other programmers was buying computer magazines and typing the example codes on your computer.

Since I suppose you never played this game, I would recommend you play it a bit on this site.


Here are the rules to design our Astro-PANIC! prototype:

* The player controls a spaceship with the mouse, being able to move it horizontally on the bottom of the screen.
* At each level, a given number of enemy spaceships appear and roam around the stage at a constant speed in a constant direction.
* Enemies cannot leave the stage, and they will bounce inside it as they touch stage edges.
* Enemies don’t shoot, and the only way they will kill the player is by touching the spaceship.
* The player can only have one bullet on stage at any time, and hitting an enemy with the bullet will destroy it.
* Destroying all enemies means passing the level, and at each level the number of enemies and their speed increases.

These are the basic rules. We’ll add some minor improvements during the design of the game itself, but before we start drawing the graphics, keep in mind we’ll design something with the look and feel of old coin operator monitors, with bright glowing graphics.


Create a new file (File | New). Then, from New Document window select Actionscript 3.0. Set its properties as width to 640 px, height to 480 px, background color to #000000 (black) and frame rate to 60. Also define the Document Class as Main and save the file as astro-panic.fla.

Though 30 frames per second is the ideal choice for smooth animations, we will use 60 frames per second to create a very fast paced game.

There are three actors in this game: the player-controlled spaceship, the bullet and the enemy. In astro-panic.fla, create three new Movie Clip symbols and call them spaceship_mc for the spaceship, bullet_mc for the bullet, and enemy_mc for the enemy. Set them all as exportable for ActionScript. Leave all other settings at their default values, just like you did during the making of Tetris.

From left to right: The spaceship (spaceship_mc), the bullet (bullet_mc), and the enemy (enemy_mc).

I made all assets with the shape of a circle. The spaceship is half a circle with a radius of 30 pixels, the bullet is a circle with a 4 pixels radius, and the enemy is a circle with a radius of 25 pixels. All of them have the registration point in their centers, and enemy_mc has a dynamic text field in it called level. At the moment I am writing a couple of zeros to test how the dynamic text field fits in the enemy shape.

Now we are ready to code.


As usual we know we are going to use classes to manage both enter frame and mouse click events, so we’ll import all the required classes immediately.

The spaceship is controlled with the mouse, but can only move along x-axis.

Without closing astro_panic.fla, create a new file and from New Document window select ActionScript 3.0 Class. Save this file as in the same path you saved astro_panic.fla. Then write:

At this time you should know everything about the concept behind this script. placeSpaceship is the function which constructs, adds to Display List and places the spaceship_mc DisplayObject called spaceship.

In enter_frame function we just move the spaceship in the same position of the x-axis of the mouse. We don’t want the spaceship to hide in a corner, so it won’t be able to follow the axis of the mouse if it gets too close to stage edges.

Test the movie, and move the mouse. Your spaceship will follow it, while being bound to the ground.

Now we should give the spaceship an old arcade look.


AS3 allows us to dynamically apply a wide range of filters to DisplayObjects on the fly. We’ll add a glow filter to simulate old ‘arcades’ pixel luminosity.

flash.filters.GlowFilter class lets us apply a glow effect to DisplayObjects.

First, we need to import it.

At this time, we can simply create a new variable to construct a GlowFilter object. Change placeSpaceship function this way:

We specify the color as 0x00FFFF (cyan to draw the spaceship), the alpha (1 = full opacity), and the amount of horizontal and vertical blur (both 6).

I want you to notice that I used 6 for horizontal and vertical blur because I like the effect I achieve with such value. If you are planning to use a lot of filters, remember values that are a power of 2 (such as 4 and 8, but not 6) render more quickly than other values.

The remaining two arguments are the strength, that determines the spread of the filter (if you use Photoshop, it’s something like spread and size of the glow filter you can apply on layers) and the quality.

Quality can range from 1 to 15 but values higher than 3 may affect performances and the same final effect can be set playing with blur.

Finally the filter is added.

filters DisplayObject’s property wants an array with all the filters you want to associate to the DisplayObject. In our case, we are adding only one filter but we have to include it in the array anyway.

Test the movie and you will see your spaceship glow.

In the previous picture, you can see the difference between the spaceship without and with the glow effect applied.

Now your spaceship is ready to fire.


Nobody would face an alien invasion with a harmless spaceship, so we are going to make it fire.

We need to create a variable to manage bullet_mc DisplayObject and I have said the spaceship can fire only one bullet at a time, so we need another variable to tell us if the spaceship is already firing. If it’s firing, it cannot fire. If it’s not firing, it can fire.

Add two new class level variables:

isFiring is the Boolean variable that we’ll use to determine if the spaceship is firing. false means it’s not firing.

bullet will represent the bullet itself.

The player will be able to fire with mouse click, so a listener is needed in Main function:

Now every time the player clicks the mouse, onMouseCk function is called.

This is the function:

It’s very easy: if isFiring is false (the spaceship isn’t already firing), placeBullet function is called to physically place a bullet then isFiring is set to true because now the spaceship is firing.

The same placeBullet function isn’t complex:

It’s very similar to placeSpaceship function, the bullet is created, added to Display List, placed on screen, and a red glow effect is added.

The only thing I would explain is the concept behind x and y properties:

Setting bullet’s x property equal to spaceship’s x property will place the bullet exactly where the spaceship is at the moment of firing.

430 is a good y value to make the bullet seem as it were just fired from the turret. Test the movie, and you will be able to fire a bullet with a mouse click.

The bullet at the moment remains static in the point where we fired it.


To make the bullet fly, we have to define its speed and move it upwards. Then we’ll remove it once it leaves the stage and reset isFiring to false to let the player fire again.

Add a constant to class level variables:

BULLET_SPEED is the amount of pixels the bullet will fly at each frame. We won’t manage upgrades or power-ups, so we can say its value will never change. That’s why it’s defined as a constant.

To manage bullet movement, we need to add some lines at the end of onEnterFrm function.

You may wonder why we are managing both the spaceship and the bullet inside the same class rather than creating a separate class for each one. You’ll discover it when you manage enemies’ movement, later in this article.

Meanwhile, add this code to onEnterFrm function.

The new code is executed only if isFiring is true. We are sure we have a bullet on stage when isFiring is true.

Moves the bullet upward by BULLET_SPEED pixels.

This if statement checks if y property is less than 0. This means the bullet flew off the screen. In this case we physically remove the bullet from the game with

and we give the player the capability of firing again with

Test the movie and fire, now your bullets will fly until they reach the top of the stage. Then you will be able to fire again.

Since nobody wants to fire for the sake of firing, we’ll add some enemies to shoot down.


We want a battle with more and more enemies as the player progresses through levels, so we have to define a variable to tell us which level is currently being played and a variable to manage the enemy DisplayObject. Add these two class level variables:

level is the current level, that starts from 1.

As the game starts, we have to place enemies on the screen according to level number. Add these lines to Main function:

The for loop will call placeEnemy function (which obviously places an enemy) for level+2 times, so we’ll have 3 enemies at level one, 4 enemies on level two, and so on.

Notice how an argument with the current enemy count is passed: knowing the cardinality of an enemy will come in hand later.

As you can imagine, placeEnemy function at the moment is not that much more than a copy/paste of placeBullet function, we are just placing enemies in a random position, not too close to the edges of the stage, and not too close to the player.

Test the game and you will see three enemies appear in random positions.

Don’t worry if in some cases they overlap: the game won’t deal with collisions among enemies so it does not matter.


As a static enemy won’t scare anyone, let’s make enemies move.

With the knowledge you have at the moment, you would suggest creating spaceship_mc class and using an enter frame listener to update each enemy position. Most scripts relies on Event.ENTER_FRAME event is simultaneously dispatched to all DisplayObjects listening for it, so you don’t have to synchronize animations.

That’s true, but with many DisplayObjects to be updated, this technique although being the most correct from a programming point of view can dramatically increase the work of the Flash player.

In this game we won’t deal with such an huge number of moving DisplayObjects to represent a risk for your CPU, anyway it’s time to learn something new.

Add this new class level variable:

You just defined your first Vector.

A Vector is an array with elements of the same predefined type. Such type is defined as “base type”, and can be any kind of type, including custom classes like I’ve done.

The base type must be specified when the Vector is created or when an instance is created using the class constructor.

So to declare a Vector of enemy_mc class we’ll use:

Notice how the base type is declared using a dot (.) then writing the class name between angle brackets (< and >).

Then you would construct it declaring base type again, this way:

Now the question is: when should you use a Vector rather than an Array? You should use a Vector every time you are dealing with collections of data of the same type, as Vector management has been proved to be faster than Array management.

Again, the increased performance in this game would be unnoticeable since the data we manage isn’t that big, anyway it’s important you know how to use vectors.

Back to our enemies, we have to make them move in a random direction at a constant speed, but we said tougher enemies will move faster, so it’s time to learn some trigonometry basics. Look at this picture:

We have a circle, and a radius that we know has the same length no matter its angle. The radius represents the constant enemy speed, to be split into horizontal and vertical speed, called vx and vy.

Thanks to trigonometry, we can determine vx by multiplying the radius by the cosine of the angle formed by the radius and the horizontal axis, and vy multiplying the radius by the sine of such angle.

This concept can be translated into AS3 adding these lines at the end of placeEnemy function:

Let’s see how we can choose a random direction:

dir is the variable which stores the random direction. It’s a random number between 0 and 360 degrees, just expressed in radians. The radian is the standard unit of angular measure, and describes the plane angle subtended by a circular arc as the length of the arc divided by the radius of the arc.

Math.PI returns the value of PI, 3.141592653589793

Once we know enemy direction, it’s easy to determine its horizontal and vertical speed thanks to the trigonometry formulas you just learned. Just notice how speed is multiplied by enemy_level argument. This way the latest enemies to be added are the faster and consequently the harder to kill.

This simple feature will allow us to have levels with increasing difficulty, with a new, fastest enemy spaceship to be added at every level.

Finally, the enemy itself is added to enemyVector Vector with push method as if it was an array, since push works in the same way for both Arrays and Vectors.

Everything is now ready to make onEnterFrm function iterate through enemyVector Vector and update each enemy position according to its x and y speed.

Add this line to onEnterFrm function:

forEach method (notice the uppercase E) executes a function for each item in the Vector.

This means manageEnemy function will be executed for each enemyVector item, but you can’t define this function as you like, because it must have some mandatory arguments.

The function has to be created with three arguments: the current Vector item, the index of such item, and the Vector itself. Also, the function won’t return anything, so we will declare as void.

This is manageEnemy function:

let’s see first how it has been declared:

As you can see, the three arguments are the current enemy, its index in the Vector and the Vector itself. All arguments are automatically passed to the function; you don’t have to worry about anything when calling it in the forEach method.

Then in comes a line I used only for the sake of layout:

I was forced to call the first argument c to make a function declaration fit in a single row, but obviously it would have been better to call it currentEnemy, so just created a variable with a more appropriate name.

That’s how I update currentEnemy position according to its xspeed and yspeed properties.

Enemies cannot fly off the stage, so the remaining lines are just to make them bounce inside stage edges. I will explain only the first situation: when the enemy is about to leave the stage to the left.

The if statement checks if enemy x position is less than 25 (enemy’s radius). This would mean the enemy is flying off the stage to the left, and we must prevent it. First we stop it at the very leftmost position it can go with:

Then, we invert its horizontal speed this way:

The remaining if statements check and prevent the enemies from flying off the stage respectively to right, up, and down sides.

Test the movie and you will see three enemies moving and bouncing around the stage, at a constant speed while each one has a different speed.

Now enemies are quite dangerous because they move around the screen, anyway nothing happens when they touch your spaceship.

Obviously hitting an enemy with the spaceship means losing the game or at least one life, so let’s make enemies deadly.


Both enemies and the spaceship have a perfect circular shape. This will help us to determine when an enemy and the spaceship collide. Being basically two circles, we can say they collide when the distance between their centers is less than the sum of both the radius.

Let’s start creating a quick function to determine the distance between two Sprites using the Pythagorean Theorem:

There isn’t that much to explain, since we are just applying a world famous formula, but I want you to notice I am not performing any square root because it’s quite CPU-expensive. It won’t be a problem as long as I remember to compare the collision distance applying the power of two, which is way faster than applying a square root.

Everything is ready to check for collisions, so add these lines at the end of manageEnemy function:

Look at this statement:

It determines if the distance between the spaceship and the current enemy is less than 3025, which is 25 (enemy radius) + 30 (spaceship radius) = 55 (collision distance) by the power of two. Easy and fast. Obviously you are free to store all these values in constants; I am using these raw values for a matter of speed.

Once an enemy collides with the spaceship, die function is called. Here it is:

I am sure you figured out how it works: first a new, bigger glow is applied to the spaceship, and then all the event listeners are removed. The game stops.

Test the game, and let an enemy hit the spaceship. The game will stop with the enemy hitting a greatly glowing spaceship and nothing more will happen.

That’s enough at the moment, because before making something interesting happen when the spaceship dies, we must make it able to kill enemies with its bullets.


Knowing the bullet has a perfect circular shape, there’s nothing easier at this time than letting the spaceship kill an enemy. We have to check if the distance between the bullet (if any) and the enemy is less than the sum of their radius, just as we made it with the spaceship.

At the end of manageEnemy function, add these lines:

First we check if there’s a bullet flying around the game just looking at isFiring value. If it’s true, then we see if the distance between the current spaceship and the bullet is less than 841, which is 25 (enemy radius) + 4 (bullet radius) = 29 (collision distance) by the power of two. In this case, killEnemy function is called; just like die function was called when the enemy and the spaceship collided. The only difference is we need to know which enemy the player killed, so we pass it as argument. Again, feel free to replace numbers with constants.

This is killEnemy function:

The function works absolutely the same way as die function does: adds a glow to the dying enemy and completely stops the game.

Test the movie and shoot to an enemy, and you will see it glow and the game will stop.

At this time all main events are defined. We can work on level progression.


A level is completed when all enemies have been killed. When you kill an enemy, the game must continue rather than stop like it does now. We must flag enemies killed by the spaceship so they won’t harm anymore, and let the game continue.

First, when we create a new enemy, let’s set a new property called killed. It will be true if the enemy has been killed, so it starts with false.

Then we have to heavily recode killEnemy function. We won’t remove listeners as we don’t want the game to stop, but we’ll set killed property to true and remove the bullet as if it had flown out of the stage.

Last but not least, we’ll update enemy position and check for collision with the player or the bullet only if the enemy is still alive, that means its killed property is false.

This way the whole function is executed only if killed property is false.

Test the movie, and you will be able to kill all enemies.

At this time the player would expect to see killed enemies removed from the screen, maybe with some kind of animation.


To make something happen to the enemy when it’s about to die, we could make it grow and fade out. It’s a good and simple way to animate its death.

Moreover, we have to remove dead enemies from enemyVector Vector because there’s no point in managing them as they should be removed from stage.

We know there is only one bullet at a time, so there can be only one enemy hit by a bullet in a single frame. This is precious information because it allows us to manage all deaths with a single class level variable, which we’ll call enemyToRemove, indicating the index in enemyVector Vector of the enemy to remove. It starts at -1 which means there’s no enemy to remove.

Once the variable is declared, we have to add a new block of code to manage dying enemies. Do you remember the whole manageEnemy function is executed only if killed property is false?

Now it’s time to execute some code when it’s true and the enemy has been hit by the bullet.

Let’s see what we are doing:

Increases enemy width and height to make it bigger.

Makes it a bit less opaque decreasing its alpha property by 0.01.

Checks if the alpha property is less than 0. This means the enemy is completely transparent and it’s time to remove it from the game.

Removes the enemy from the Display List and clears its variable.

Finally, setting the new currentEnemy variable to index, that represents the current index in enemyVector Vector.

Now in onEnterFrm function we can remove the corresponding item from the Vector. Doing it in a function called by forEach method would produce some warnings as you are making the Vector shorter while it’s currently being scanned.

At the end of onEnterFrm function, add these lines:

Their meaning is quite obvious: if enemyToRemove has a value greater than its default value -1, then remove the item from enemyVector Vector with splice method, then set enemyToRemove to -1 again as there aren’t any more enemies to remove.

splice method adds elements to and removes elements from the Vector. The same method is also available for arrays. In our case, the first parameter (enemyToRemove) is the index of the element where the deletion begins, and the second parameter (1) the number of elements to be deleted. Basically I am saying the Vector to remove one element starting from index enemyToRemove. An optional third parameter can be used to provide a list of one or more comma-separated values to insert into the Vector starting from the index specified in the first parameter. We don’t need this optional third parameter in this case.

Test the movie and shoot to an enemy to see it explode.

The game now starts to look good, but once you destroyed all enemies nothing happens.


Once all enemies have been destroyed, the player must be able to play the next level, with more enemies moving faster.

For our convenience, we should manage level creation with a function, changing Main function removing the for loop and adding a new function called playLevel.

This function is just a cut/paste of the for loop previously included in Main function, but this way we can call playLevel from elsewhere.

And in this specific case, we are calling it from onEnterFrm function once we removed an enemy:

If the length of enemyVector Vector is 0, there are no enemies left, so it’s time to increase level variable and call playLevel function to start a new level.

Test the movie and try to beat as many levels as you can.

In the previous picture, level 2 with four enemies and level 4 with six enemies. The game gets harder as the player progresses through levels.

Now, something for the score maniacs.


When playing games with a specific goal, such as saving the princess or escaping from the castle, players know exactly why they are playing: they must save the princess or escape from the castle.

In games like Astro-PANIC!, where there’s no goal and you just have to survive as long as possible, the only way to have players come back to our game and play it again is giving the possibility to save their best score.

People will play again and again to achieve a better score.

At this time, we need two more class level variables: one to save the current score, which we call score, and another variable called hiscore, which will save our best score ever.

Add these two new variables:

Finally, it’s time to make a good use of the level dynamic text. We’ll display the number of the enemy. The higher the number, the faster the enemy, and the more points it will give once killed. This will help the player to choose which enemy to kill, making his own strategy.

private function placeEnemy(enemy_level:uint):void {
enemy=new enemy_mc ;

Once an enemy dies, the score is updated. Although being a very simple game, we can add complex scoring system by giving the enemy a score based on its level and its height.

The higher you kill an enemy, the more points it will give you.

Once you die, I want the score to be written on the output window, and eventually the high score to be updated.

There’s not that much to explain in this code, as it’s just a bunch of screen outputs.

Test the movie and play until you die:

You should see in the output window something like this:

Your score: 66
Current hiscore: 0

So you are able to manage scores and high scores.

The big problem is the high score is reset to 0 every time you start a new game, making it useless. We have to find a way to save data on players’ local computers.


AS3 provides a class, SharedObject, to let us save a limited amount of data on our local computer. The class does not create cookies, but something very similar called LocalSharedObjects, and the concept is the same.

It’s very important to understand that LocalSharedObjects maintain local persistence. This means that you can play the game, make an high score, turn off your computer, and next time you’ll play the game on the same computer, it will retrieve the high score.

Exactly what we need. Let’s see how to use it. First, we need to import the SharedObject class:

Then we will remove hiscore class level variable as we won’t use it anymore as it just keeps the high score when the script is running, and we will create a new variable called sharedHiScore, to handle with SharedObject class.

At this time, when the game is run, we can face two cases:

1: The game has never been run on the computer, so we have to somehow initialize the SharedObject.
2: The game has already been run on the computer, no matter if someone made an high score or not, no matter even if someone has played. In this case the SharedObject is initiazlied.

To make this, we need to add this code to Main function:

Let’s see its meaning:

getLocal method returns a reference to a locally persistent SharedObject (in this case hiscores) that is available only on the current client. If the SharedObject does not already exist, getLocal method creates one.

When looking at score value inside hiscores SharedObject, if it’s undefined it means there isn’t any variable called score in hiscores SharedObject or there isn’t any hiscores SharedObject at all.

In this case we need to initialize score variable in hiscores SharedObject. We’ll set it to zero. At the same time, we print a message in the Output window saying we did not find any high score.

If we found a high score, we show it in the Output window.

When we are done with the SharedObject, we have to close it. close method does this job.

Now, when the player dies, we have to check his score with the SharedObject high scores and eventually update it. The last part of die function must be changed this way:

As you can see, the SharedObject is opened once again, and its score variable is compared with score class level variable. As you can see, both variables can have the same name because they refer to different classes. Then if needed we update the SharedObject and finally we close it.

Test the movie and the first time you will see in the Output window:

No High Score found

Now play a game, and if when you die you scored, let’s say, 18, you will see in the Output window:

Your score: 18

Current hiscore: 0


At this time you must close and restart the game as it does not provide a “replay”, and once you restart it (you can also restart you computer if you want) you will see:

Current High Score: 18

The game remembered the latest high score you made.


The most important things you learned during this article are the capability of adding filters on the fly to your DisplayObjects and the feature of saving data on your computer using SharedObjects. You can manage any kind of save game with SharedObjects, such as the latest level beaten, the amount of gold the player owns, or any other kind of information.


To provide a better experience to players, you could place some dynamic text fields showing the current level and the score, as well as the high score. Then you can add some lines to onMouseCk function, you can make the player restart the game if he clicks the mouse when the game is over. You only have to reset the score, the level, and the variable that states the game is over.

  • Please add the swf on the post so we can test it online.

  • W

    Interesting post, I’m working on a game also with ground cannon and spaceships like that, the old graphics are so much beautiful :-)

    Go on Emanuele !

  • I liked your book a lot! You definitely show how you can build a ton of games, and how a lot of the ones I didn’t realize are grid/array based actually are.

    I followed along and copy and pasted all the code from the packt publishing pdf (better than kindle for coding books) into flash and put up the demos of all the games (using my not so good artwork based on the books artwork) at:

    And you seem to be an expert at using recursive functions!

    Great book and tutorial!

  • Jason Aunkst

    this is a perfect game to teach about collision detection. color me impressed when u show us how to create a quad tree to reduce the callbacks using the pythagorean theorem. =)

  • hersch

    i become an error if i make this tutorial….

    Error #1009
    Error #2025

    i cant find the problem… pls help :)

  • Anonymous
  • 9000 points

  • Anonymous

    After 10 days, Arcade Shooter has gotten 40,000 sessions, 60,000 gameplays, and $7 with an eCPM of $0.12.

  • hi! again. I posted on the kongregate, but didnt seem like you read there a lot, so thought to post it here, maybe to inspire some more people to buy your book:)
    i bought your book almost a month ago!:)
    i have a great pleasure reading it:)
    Guess what! i do most of what i can with the examples you gave in the book and publish here on kongregate, coz i have a lot of fun with as3 and making games:D
    hope its ok!:)
    i could comment a little bit about the book, (which one it is you can guess by the games i uploaded, or the way i speak maybe:)
    you introduce to some a bit more complex ideas, like math, but do not explain it too much, and on the other hand the things that looks really simple, like in chapter 7 you already did most of the as3 sintax and get it a bit, but still explain it more than the complex things.
    And the other thing is, no introduction to creating at least simple seperate class than, yes there is those classes but agh, they are really to short to get hang of what you could do and how to manage different class files. And now im struggling. Ill have to read another book to learn that. I would have exchanged the Connect4 game for introduction to using classes!:) but all in all, the book gave me a lot of pleasure to learn as3, like no other books, that for example go into complexity too fast!
    Btw to the people reading this, i got the book from, now in oktober they have really good deals!
    Just a thank you from a pleased reader, and Good Luck:)

  • Emanuele Feronato

    Thank you Drny,I’ve read your Kong message too.

  • asdText

    Hello , i tried following this tutorial , and i have problem at the beginning of it , i know its stupid beginners mistakes , but it is really frustrating
    i created new flash file put a spaceship image converted it to mc and its instance is spaceship_mc saved it and created the as3 class file and wrote the code of the class as shown above . saved every thing “same path” and i got these errors ., Line 6 1046: Type was not found or was not a compile-time constant: spaceship_mc., Line 12 1180: Call to a possibly undefined method spaceship_mc.
    and i was getting 5008 error and its gone , i did not know what i did to fix it ???