In this Premium Tutorial, we'll be building a Breakout game; "Brick Breaker" from scratch using Flash and AS3.
Step 1: Brief Overview
Using the Flash drawing tools we'll create a good looking graphic interface that will be powered by several ActionScript 3 classes.
The user will be able to play through a series of levels, you can easily add as many levels as you want!
Step 2: Flash Document Settings
Open Flash and create a 320 pixels wide, 480 pixels tall document. Set the Frame rate to 24fps.

Step 3: Interface

A colorful, nice-looking interface will be displayed. It will contain multiple shapes, buttons, bitmaps and more.
Let's jump straight into creating this GUI.
Step 4: Main Screen

This is the Main Screen or view, it will be the first graphic to appear in our game.
Step 5: Background
Create a 320x480 rectangle and fill it with this radial gradient: #3A9826, #102A07.

We're going to give it a little more detail by adding a Photoshop filter, if you don't have Photoshop you can try to add a nice effect using the Flash Tools.
Open the image in Photoshop and go to Filters > Texture > Patchwork, use the following settings:

You will end up with something like this:

This Background will be on stage as well as the paddle, ball and text indicators. Convert the background to a MovieClip and name it bg.
Step 6: Title
Select the Text Tool (T), select a suitable font and write your game title. I used this format: Akashi, 55pt, #FFCC33.

Select the TextField and use the Filters panel to add a Drop Shadow:

Duplicate the text (Cmd + D) and move it 3px up to give it some emboss.

Convert the graphics to a MovieClip and name it MenuScreen, remember to mark the Export for ActionScript box. You can delete this from stage when finished, as it will be called using AS3.
Step 7: Paddle
Use the Rectangle Primitive Tool (R) to create a 57x11.5px round rectangle, change the corner radius to 10 and apply this gradient: #4E4E4E, #BABABA, #B0B3BA.

Add some detail lines with the Rectangle Tool, use your own style!

You can also add some color to your paddle, here is the final result of mine, the color used is: #CC0000.

Convert the graphics to a MovieClip and name it paddle.
Step 8: Ball
To create the ball, select the Oval Tool (O) and use it to create a 12x12px, #CCCCCC circle.

Duplicate the circle (Cmd + D) change its size to 10x10px and fill it with this radial gradient: #95D4FF, #0099FF.

Lastly, cut the second circle in half and use the Selection Tool (V) to make a curve in the bottom. Change its color to a white linear gradient with alpha 60, 10.

Convert the graphics to a MovieClip and name it ball.
Step 9: Brick
Our Brick will be very simple.
Use the Rectangle tool to create a 38x18px rectangle and apply the next gradient: #CC0000, #8E0000, #FF5656.

Convert the rectangle to a MovieClip and apply the shadow filter used in the title text to give it a nicer look.
Convert again the graphic to a MovieClip and name it Brick, remember to mark the Export for ActionScript box.
Step 10: About Screen
The About Screen will show the credits, year and copyright of the game.
It will be pretty simple to create as we already have all the elements used in it.

Convert the graphics to a MovieClip and name it AboutScreen, remember to mark the Export for ActionScript box.
Step 11: Game Screen
This is the game screen, it will be on stage from the beginning and it will contain the paddle, ball, background and text indicators. (We will add the bricks using code.)

The instance names are pretty easy and self explanatory: paddle, ball, bg, scoreTF, livesTF and levelTF.
Step 12: Embed Fonts
In order to use the custom font dynamically we will need to embed it in the application.
Select a dynamic textfield and click the Embed... button in the Properties Panel.

Select/add all the necessary characters and click OK.
Step 13: Alert Screen
This screen will appear when the game has been decided; either you win, lose or you reach game over (winning all the levels or losing all the lives).
Two Dynamic TextFields are used in this view, they will display the current game state plus a short message. The TextFields are named titleTF and msgTF.

Convert the graphics to a MovieClip and mark the Export for ActionScript box, set the class name to AlertScreen.
This ends the graphics part, let the ActionScript begin!
Step 14: Tween Nano

We'll use a different tween engine from the default included in flash, this will increase performance and be easier to use.
You can download Tween Nano from its official website.
Step 15: New ActionScript Class
Create a new (Cmd + N) ActionScript 3.0 Class and save it as Main.as in your class folder.

Step 16: Class Structure
Create your basic class structure to begin writing your code.
package { import flash.display.Sprite; public class Main extends Sprite { public function Main():void { // constructor code } } }
Step 17: Required Classes
These are the classes we'll need to import for our class to work, the import directive makes externally defined classes and packages available to your code.
import flash.display.Sprite; import flash.ui.Mouse; import flash.events.MouseEvent; import flash.events.KeyboardEvent; import flash.events.Event; import com.greensock.TweenNano; import com.greensock.easing.Circ;
Step 18: Variables and Constants
These are the variables and constants we'll use, read the comments in the code to discover more about them.
private const BRICK_W:int = 39; //brick's width private const BRICK_H:int = 19; //brick's height private const OFFSET:int = 6; //An offset used to center the bricks private const W_LEN:int = 8; //the length of the levels, only 8 horizontal bricks should be created on stage private const SCORE_CONST:int = 100; //the amount to add to the score when a brick is hit private var bricks:Vector.<Sprite> = new Vector.<Sprite>(); //stores all the bricks private var xSpeed:int = 5; private var ySpeed:int = -5; private var xDir:int = 1; //x direction private var yDir:int = 1; private var gameEvent:String = ''; //stores events like win, lose, gameover private var currentLevel:int = 0; private var menuScreen:MenuScreen; //an instance of the menu screen private var aboutScreen:AboutScreen; private var alertScreen:AlertScreen; private var lives:int = 3; private var levels:Array = []; //stores the levels
Step 19: Levels
All our levels will be stored in multidimensional arrayss.
These are arrays containing arrays; you can write them in a single line, but if you align them you can actually see the form that the level will take.
private const LEVEL_1:Array = [[0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0], [0,0,0,1,1,0,0,0], [0,0,0,1,1,0,0,0], [0,1,1,1,1,1,1,0], [0,1,1,1,1,1,1,0], [0,0,0,1,1,0,0,0], [0,0,0,1,1,0,0,0], [0,0,0,0,0,0,0,0],]; //this forms a + sign! private const LEVEL_2:Array = [[0,0,0,0,0,0,0,0], [0,0,0,1,1,0,0,0], [0,0,1,0,0,1,0,0], [0,0,0,0,0,1,0,0], [0,0,0,0,1,0,0,0], [0,0,0,1,0,0,0,0], [0,0,1,0,0,0,0,0], [0,0,1,1,1,1,0,0],]; //this forms a number 2!
In these levels the 1s are representing the space in the stage where a brick will be placed, and the 0s are just empty space. These levels will be later read by a function that will place the bricks on the stage. You can add as many levels as you want using this class!
Step 20: Constructor Code
The constructor is a function that runs when an object is created from a class; this code is the first to execute when you make an instance of an object (or runs when the game loads, in the case of a document class).
It calls the necessary functions to start the game. Check out these functions in the following steps.
public final function Main():void { /* Add Levels */ levels.push(LEVEL_1, LEVEL_2); //we add the levels to the array in order to know how many they are /* Menu Screen, Buttons Listeners */ menuScreen = new MenuScreen(); addChild(menuScreen); menuScreen.startB.addEventListener(MouseEvent.MOUSE_UP, tweenMS); menuScreen.aboutB.addEventListener(MouseEvent.MOUSE_UP, tweenMS); }
Step 21: Menu Screen & About View Animation
The next lines handle the Menu Screen buttons and tween the Menu or About view depending on the button pressed.
private final function tweenMS(e:MouseEvent):void { if(e.target.name == 'startB') //if start button is clicked { TweenNano.to(menuScreen, 0.3, {y: -menuScreen.height, ease: Circ, onComplete: init}); //tween menu screen } else //if about button is clicked { aboutScreen = new AboutScreen();//add about screen addChild(aboutScreen); TweenNano.from(aboutScreen, 0.3, {x: stage.stageWidth, ease: Circ}); //tween about screen aboutScreen.addEventListener(MouseEvent.MOUSE_UP, hideAbout); //add a mouse listener to remove it } } /* Removes About view */ private final function hideAbout(e:MouseEvent):void { TweenNano.to(aboutScreen, 0.3, {x:stage.stageWidth, ease:Circ, onComplete:function rmv():void{ aboutScreen.removeEventListener(MouseEvent.MOUSE_UP, hideAbout); removeChild(aboutScreen); }}); }
Step 22: Init Function
This function performs the necessary operations to start the game, read the comments in the code to know more about it.
private final function init():void { /* Destroy Menu Screen */ menuScreen.startB.removeEventListener(MouseEvent.MOUSE_UP, tweenMS); menuScreen.aboutB.removeEventListener(MouseEvent.MOUSE_UP, tweenMS); removeChild(menuScreen); menuScreen = null; /* Hide Cursor */ Mouse.hide(); /* Build Level Bricks */ buildLevel(LEVEL_1); /* Start Listener */ bg.addEventListener(MouseEvent.MOUSE_UP, startGame); }
Step 23: Move Paddle
The Paddle will be Mouse Controlled, it will follow the mouse x position .
private final function movePaddle(e:MouseEvent):void { /* Follow Mouse */ paddle.x = mouseX; }
Step 24: Paddle Border Collision
To stop the paddle from leaving the stage, we create invisible boundaries on the sides of the screen.
{ /* Follow Mouse */ paddle.x = mouseX; /* Borders */ if((paddle.x - paddle.width / 2) < 0) { paddle.x = paddle.width / 2; } else if((paddle.x + paddle.width / 2) > stage.stageWidth) { paddle.x = stage.stageWidth - paddle.width / 2; } }
Step 25: Build Level Function
The levels will be built by this function.
It uses a parameter to obtain the level to build, calculates its size and runs a nested for-loop, with one loop for the height and one for the width. Next, it creates a new Brick instance that is placed according its width, height and the number corresponding to i and j.
Lastly, the brick is added to the bricks
vector to access it outside this function.
private final function buildLevel(level:Array):void { /* Level length, height */ var len:int = level.length; for(var i:int = 0; i < len; i++) { for(var j:int = 0; j < W_LEN; j++) { if(level[i][j] == 1) { var brick:Brick = new Brick(); brick.x = OFFSET + (BRICK_W * j); brick.y = BRICK_H * i; addChild(brick); bricks.push(brick); } } } }
Step 26: Game Listeners
This function adds or removes the mouse and enter frame listeners. It uses a parameter to determine if the listeners should be added or removed: default is add.
private final function gameListeners(action:String = 'add'):void { if(action == 'add') { stage.addEventListener(MouseEvent.MOUSE_MOVE, movePaddle); stage.addEventListener(Event.ENTER_FRAME, update); } else { stage.removeEventListener(MouseEvent.MOUSE_MOVE, movePaddle); stage.removeEventListener(Event.ENTER_FRAME, update); } }
Step 27: Start Game Function
The next code calls the gameListeners()
function to start the game.
private final function startGame(e:KeyboardEvent):void { bg.removeEventListener(MouseEvent.MOUSE_UP, startGame); gameListeners(); }
Step 28: Ball Movement
The ball speed is determined by the xSpeed and ySpeed variables, when the update function is executed, the ball starts moving using theses values every frame.
private final function update(e:Event):void { /* Ball Movement */ ball.x += xSpeed; ball.y += ySpeed;
Step 29: Wall Collision
This code checks for collisions between the ball and the walls.
/* Wall Collision */ if(ball.x < 0){ball.x = ball.x + 3;xSpeed = -xSpeed;};//Left if((ball.x + ball.width) > stage.stageWidth){ball.x = ball.x - 3;xSpeed = -xSpeed;};//Right if(ball.y < 0){ySpeed = -ySpeed;};//Up
Step 30: Lose Game Event
An if-statement is used to check for when the paddle misses the ball. If so, the player loses a life.
if(ball.y + ball.height > paddle.y + paddle.height){alert('You Lose', 'Play Again ›');gameEvent = 'lose';lives--;livesTF.text = String(lives);};//down/lose
Step 31: Paddle-Ball Collisions
When the ball hits the paddle, the ySpeed is set to negative to make the ball go up. We also check in which side of the paddle the ball has hit to choose the side where it will move next.
/* Paddle Collision, check the which side of the paddle the ball hits*/ if(paddle.hitTestObject(ball) && (ball.x + ball.width / 2) < paddle.x) { ySpeed = -5; xSpeed = -5; //left } else if(paddle.hitTestObject(ball) && (ball.x + ball.width / 2) >= paddle.x) { ySpeed = -5; xSpeed = 5; //right }
Step 32: Brick Collisions
We use a for and hitTest to check for bricks collisions, when the ball hits a brick the same technique used in the paddle is used to determine the side the ball will follow.
/* Bricks Collision */ for(var i:int = 0; i < bricks.length; i++) { if(ball.hitTestObject(bricks[i])) { /* Check the which side of the brick the ball hits, left, right */ if((ball.x + ball.width / 2) < (bricks[i].x + bricks[i].width / 2)) { xSpeed = -5; } else if((ball.x + ball.width / 2) >= (bricks[i].x + bricks[i].width / 2)) { xSpeed = 5; }
Step 33: Change Ball Direction & Remove Brick
The following code changes the Y direction of the ball and removes the brick from stage and the vector.
/* Change ball y direction */ ySpeed = -ySpeed; removeChild(bricks[i]); bricks.splice(i, 1);
If you like, you could change this logic so that the ball's y-speed is only reversed if it hits the top or bottom of a brick, and not when it hits the sides. Try it out and see what you think.
Step 34: Add Score and Check Win
Each brick hit will add 100 to the score, the score will be taken from the score constant and added to the current score using int and String functions. This code also checks whether there are no more bricks in the Vector and displays an alert if so.
/* Score++ */ scoreTF.text = String(int(scoreTF.text) + SCORE_CONST); } } /* Check if all bricks are destroyed */ if(bricks.length < 1) { alert('You Win!', 'Next Level ›'); gameEvent = 'win'; } }
Step 35: Alert Screen
The Alert Screen shows the player information about the status of the game, it is shown when a game event is reached, such as losing a life or completing a level.
Two parameters are used in this function:
- t: The alert title
- m: A short message
private final function alert(t:String, m:String):void { gameListeners('remove'); Mouse.show(); alertScreen = new AlertScreen(); addChild(alertScreen); TweenNano.from(alertScreen.box, 0.3, {scaleX: 0.5, scaleY:0.5, ease:Circ}); alertScreen.box.titleTF.text = t; alertScreen.box.msgTF.text = m; alertScreen.box.boxB.addEventListener(MouseEvent.MOUSE_UP, restart); }
Step 36: Restart Function
The next function checks the game status (win, lose, finished) and performs an action according to it.
private final function restart(e:MouseEvent):void { if(gameEvent == 'win' && levels.length > currentLevel+1) //if level is clear but more levels are left { currentLevel++; changeLevel(levels[currentLevel]);//next level levelTF.text = 'Level ' + String(currentLevel + 1); } else if(gameEvent == 'win' && levels.length <= currentLevel+1) //if level is clear and no more levels are available { alertScreen.box.boxB.removeEventListener(MouseEvent.MOUSE_UP, restart); removeChild(alertScreen); alertScreen = null; alert('Game Over', 'Congratulations!'); gameEvent = 'finished'; } else if(gameEvent == 'lose' && lives > 0) //if level failed but lives > 0 { changeLevel(levels[currentLevel]);//same level } else if(gameEvent == 'lose' && lives <= 0) //if level failed and no more lives left { alertScreen.box.boxB.removeEventListener(MouseEvent.MOUSE_UP, restart); removeChild(alertScreen); alertScreen = null; alert('Game Over', 'Try Again!'); gameEvent = 'finished'; } else if(gameEvent == 'finished') //reached when no more lives or levels are available { /* Add menu screen */ menuScreen = new MenuScreen(); addChild(menuScreen); menuScreen.startB.addEventListener(MouseEvent.MOUSE_UP, tweenMS); menuScreen.aboutB.addEventListener(MouseEvent.MOUSE_UP, tweenMS); TweenNano.from(menuScreen, 0.3, {y: -menuScreen.height, ease: Circ}); /* Reset vars */ currentLevel = 0; lives = 3; livesTF.text = String(lives); scoreTF.text = '0'; levelTF.text = 'Level ' + String(currentLevel + 1); xSpeed = 5; ySpeed = -5; clearLevel(); } }
Step 38: Change Level
This function changes to the level written in the parameter.
private final function changeLevel(level:Array):void { /* Clear */ clearLevel(); /* Redraw Bricks */ buildLevel(level); /* Start */ Mouse.hide(); bg.addEventListener(MouseEvent.MOUSE_UP, startGame); }
Step 39: Clear Level
A function to clear the remaining bricks and alerts from stage. It will also reset the position of the paddle and ball.
private final function clearLevel():void { /* Remove Alert Screen */ alertScreen.box.boxB.removeEventListener(MouseEvent.MOUSE_UP, restart); removeChild(alertScreen); alertScreen = null; /* Clear Level Bricks */ var bricksLen:int = bricks.length; for(var i:int = 0; i < bricksLen; i++) { removeChild(bricks[i]); } bricks.length = 0; /* Reset Ball and Paddle position */ ball.x = (stage.stageWidth / 2) - (ball.width / 2); ball.y = (paddle.y - paddle.height) - (ball.height / 2) -2; paddle.x = stage.stageWidth / 2; }
Step 40: Set Main Class

We'll make use of the Document Class in this tutorial, if you don't know how to use it or are a bit confused please read this QuickTip.
Conclusion
The final result is a customizable and entertaining game, try adding your custom graphics and levels!
I hope you liked this Active Premium tutorial, thank you for reading!
Subscribe below and we’ll send you a weekly email summary of all new Game Development tutorials. Never miss out on learning about the next big thing.
Update me weeklyEnvato Tuts+ tutorials are translated into other languages by our community members—you can be involved too!
Translate this post