Talking about Circle Chain game, Actionscript 3, Flash and Game development.
If you are a long time reader, you know Circle Chain was my first Flash game released to start experimenting how to monetize Flash games.
More than four years have passed, and I ported my old AS2 game to AS3, giving you the commented source code of a complete game.
But it’s not over… since it was my first Flash game, it will also be my first iPhone game. While you are reading this post, I am porting it to iPhone using Air for Flash. I will keep you updated about the making and the submission of the game in the App Store.
This is the AS3 game, with the same flaws as the original:
and this is the source code, keep in mind my library is made this way:
BackGroundImage: the background image
BlueMob: the blue circle (for some reason I used “mob” rather than “circle”)
CongratzScreen: the congratulations screen you see when you complete the game
GameMusic: the music
GameTitle: the splash screen
GreenBullet: the green bullet
GreenMob: the green circle
HowMany: contains a dynamic text field called howManyText
LevelIntro: contains two dynamic text fields called levelName
and levelNotes
PlayerBullet: the player bullet
PlayerCircle: the circle controlled by the player
PurpleBullet: the purple bullet
PurpleMob: the purple circle
YellowBullet: the yellow bullet
YellowMob: the yellow circle
And here we go:
package {
import flash.display.Sprite;
import flash.ui.Mouse;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.media.SoundChannel;
import flash.utils.getQualifiedClassName;
public class Main extends Sprite {
/* LEVEL DESIGN VARIABLES */
// green mobs per level
private var greenMobs=new Array(5,10,15,20,6,10,7,25,5,10,0,10,2,1,10,0,5,0,25,2,0);
// blue mobs per level
private var blueMobs=new Array(0,0,0,0,1,2,6,0,0,1,15,0,1,1,0,1,0,6,0,1,0);
// yellow mobs per level
private var yellowMobs=new Array(0,0,0,0,0,0,0,0,5,4,1,10,1,1,10,0,5,0,20,2,0);
// purple mobs per level
private var purpleMobs=new Array(0,0,0,0,0,0,0,0,0,0,0,0,0,1,10,5,5,1,5,2,0);
// mobs to destroy to pass the level
private var mobsToDestroy=new Array(2,5,10,15,3,4,1,24,3,5,1,18,3,3,30,1,13,1,50,5,0);
// levels description array
private var levelDescription=new Array();
/* GAME LOGIC VARIABLES */
// are we playing the game?
private var playingGame:Boolean=false;
// level to play, from 0 to 19 = 20 levels
private var levelToPlay:Number=0;
// destroyed mobs counter
private var mobsDestroyed:Number;
// Boolean variable to determine if the player exploded
private var playerExploded:Boolean=false;
// Boolean variable to determine if the player started the level
private var playerStarted:Boolean=false;
// Boolean variable to know if the level shouldn't be considered completed anyway
private var dieAnyway:Boolean;
// Vector of mobs on screen
private var mobVector:Vector.=new Vector.();
// Vector of bullet on screen
private var bulletVector:Vector.=new Vector.();
/* SPRITES INSTANCES */
// the circle controlled by the player. It's you!!
private var playerCircle:PlayerCircle=new PlayerCircle();
// game title splash screen
private var gameTitle:GameTitle=new GameTitle();
// sprite container where to play the game
private var battleField:Sprite;
// level intro, the big box with instructions
private var levelIntro:LevelIntro;
// text showing how many mobs you destroyed so far
private var howMany:HowMany=new HowMany();
public function Main() {
// adding the music
var gameMusic:GameMusic = new GameMusic();
var soundChannel:SoundChannel=gameMusic.play(0,10000);
// initializing level descriptions
levelDescription[0]="This is the first level.\nJust move the red circle with the mouse\nand click to start the chain reaction\nand explode other cirlces\n\nClick anywhere to begin";
levelDescription[1]="If you can see this message,\nyou are on level 2.\n\nYou have to destroy as many circles as\nreported in the upper left corner to\nadvance levels\n\nClick anywhere to begin";
levelDescription[2]="Well done\n\nYou can proceed\nThis is the last time I tell you that...\n\nyou have to press mouse anywhere\nto begin";
levelDescription[3]="Ok\n\nYou managed the game.\n\nThis is the last normal stage";
levelDescription[4]="Ok\n\nLet's make things harder.\n\nYou can't touch blue circles";
levelDescription[5]="Hmmmm\n\nLet me see if you can save TWO blues";
levelDescription[6]="If your boss knew you are\ntrying to save all those blues...";
levelDescription[7]="Now a bit of mess, then you'll meet\na new circle type";
levelDescription[8]="Yellow circles explode in a different way";
levelDescription[9]="All 3 colors together";
levelDescription[10]="Feeling blue?";
levelDescription[11]="Destroy them all! (well, almost)";
levelDescription[12]="Easy?";
levelDescription[13]="What!\n\nAnother kind of circle!\nHow does it work?";
levelDescription[14]="Destroy them all! (this time 4 real)";
levelDescription[15]="It sucks, I know...\n\nBut I just do not want you\nto pass this level";
levelDescription[16]="There are 20 levels in this game\n\nBut the sequel is on its way!";
levelDescription[17]="This is so bad...";
levelDescription[18]="It's not a level.\n\nIt's a stress test!";
levelDescription[19]="One last level and...\n\nBACK AT WORK!!";
// adding the background image
var backgroundImage:BackgroundImage=new BackgroundImage();
addChild(backgroundImage);
// adding game title
addChild(gameTitle);
// adding the player
addChild(playerCircle);
// hiding the mouse
Mouse.hide();
// listeners
addEventListener(Event.ENTER_FRAME,updateGame);
stage.addEventListener(MouseEvent.CLICK,mouseClicked);
}
/* FUNCTION TO BE EXECUTED AT EVERY FRAME */
private function updateGame(e:Event):void {
// adjusting circle position according to mouse position
playerCircle.x=stage.mouseX;
playerCircle.y=stage.mouseY;
// looping through mobs Vector
for (var i:Number=0; i500) {
mobVector[i].theSprite.x-=500;
}
if (mobVector[i].theSprite.x<0) {
mobVector[i].theSprite.x+=500;
}
if (mobVector[i].theSprite.y>500) {
mobVector[i].theSprite.y-=500;
}
if (mobVector[i].theSprite.y<0) {
mobVector[i].theSprite.y+=500;
}
}
// looping through bullet Vector
for (i=0; i0) {
i--;
}
if (j>0) {
j--;
}
// incrementing the counter of destroyed mobs
mobsDestroyed++;
// updating the dynamic text showing the current destroyed/needed mob counters
howMany.howManyText.text="Exploded: "+mobsDestroyed+"/"+mobsToDestroy[levelToPlay];
}
}
// checking if the bullets are out of the stage
if (bulletVector[i].theSprite.y>500||bulletVector[i].theSprite.y<0||bulletVector[i].theSprite.x>500||bulletVector[i].theSprite.x<0) {
// removing bullets out of the stage
battleField.removeChild(bulletVector[i].theSprite);
bulletVector.splice(i,1);
// if there aren't bullets on the stage...
if (bulletVector.length==0) {
// if we destroyed the required amount of mobs...
if (mobsDestroyed>=mobsToDestroy[levelToPlay] && !dieAnyway) {
// we are ready to play next level!!
levelToPlay++;
}
// play a new level (or the current level if you did not pass it)
playLevel();
}
}
}
}
/* FUNCTION TO BE EXECUTED WHEN THE PLAYER CLICKS THE MOUSE */
private function mouseClicked(e:MouseEvent):void {
// if we aren't playing the game (we still are on the splash screen);
if (! playingGame) {
// now we are playing!!
playingGame=true;
// removing unnecessary assets
removeChild(gameTitle);
removeChild(playerCircle);
// play the level
playLevel();
}
// otherwise it means we are already playing
else {
// if we are playing AND we aren't exploded yet...
if (playerStarted && !playerExploded) {
// time to explode!!
playerExploded=true;
// let's create four red bullets
for (var i:Number=1; i<=4; i++) {
var theBullet:TheBullet=new TheBullet(new PlayerBullet(),playerCircle,Math.PI*i/2);
bulletVector.push(theBullet);
battleField.addChild(theBullet.theSprite);
}
// set player alpha to almost transparent
playerCircle.alpha=0.25;
}
// otherwise it means we are on the level intro
if (! playerStarted) {
// removing level intro
battleField.removeChild(levelIntro);
// let's start
playerStarted=true;
}
}
}
/* FUNCTION TO BUILD A LEVEL */
private function playLevel():void {
// if we are on level 20 (congratz screen since levels range from 0 to 19)
if (levelToPlay==20) {
// show the congratz screen
var congratzScreen:CongratzScreen=new CongratzScreen();
addChild(congratzScreen);
}
// otherwise let's get ready to play
else {
// the remaning lines just initialize variables and place mobs on screen
// nothing interesting here
dieAnyway=false;
mobVector=new Vector.();
bulletVector=new Vector.();
playerStarted=false;
playerExploded=false;
if (battleField!=null) {
removeChild(battleField);
}
battleField=new Sprite();
addChild(battleField);
var loseAnyway:Boolean=false;
var numberOfMobs:Number=greenMobs[levelToPlay]+blueMobs[levelToPlay]+yellowMobs[levelToPlay]+purpleMobs[levelToPlay];
mobsDestroyed=0;
var collisionArray:Array= new Array();
howMany=new HowMany();
howMany.howManyText.text="Exploded: "+mobsDestroyed+"/"+mobsToDestroy[levelToPlay];
battleField.addChild(howMany);
levelIntro=new LevelIntro();
levelIntro.x=250;
levelIntro.y=250;
levelIntro.levelName.text="Level "+(levelToPlay+1);
levelIntro.levelNotes.text=levelDescription[levelToPlay];
battleField.addChild(levelIntro);
playerCircle=new PlayerCircle();
battleField.addChild(playerCircle);
for (var i:Number=0; i
This is the content of TheBullet
class:
package {
import flash.display.Sprite;
public class TheBullet extends Sprite{
public var theSprite:Sprite;
public var xSpeed:Number;
public var ySpeed:Number;
public function TheBullet(sprite:Sprite,father:Sprite,bulletDirection:Number) {
theSprite=sprite;
xSpeed=6*Math.cos(bulletDirection);
ySpeed=6*Math.sin(bulletDirection);
theSprite.x=father.x;
theSprite.y=father.y;
}
}
}
And this is the content of TheMob
class:
package {
import flash.display.Sprite;
public class TheMob extends Sprite {
public var theSprite:Sprite;
public var xSpeed:Number;
public var ySpeed:Number;
public function TheMob(sprite:Sprite) {
theSprite=sprite;
theSprite.x=Math.random()*500;
theSprite.y=Math.random()*500;
var randomDirection:Number=Math.random()*2*Math.PI;
xSpeed=2*Math.cos(randomDirection);
ySpeed=2*Math.sin(randomDirection);
}
}
}
Download the source code and see you soon in the App Store.
Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.