This article is a tutorial which explains how to create a game using Flash CS3.
The game which I will study can be seen here:
Chicken and Eggs Game .
Of course, I will only explain the logic used by the game and will not go into creating the graphics.
You will need to change the used Movie Clip graphics to personalize the game to your liking.
I would also like to remind you that using the same graphics of the original game could be illegal.
Ready? Go...
I create a FLA and save it as ?main.fla?, inside which:
- A Movie Clip with an instance name of ?bg_mc? (background Movie Clip)
- A Movie Clip with an instance name of ?gallina_mc? (the hen throwing eggs)
- A Movie Clip with an instance name of ?cesto_mc? (the basket to raccolt the eggs)
- A Movie Clip with an instance name of ?linea_mc? (if the eggs go beyond that line, the game is over)
- A Movie Clip with an instance name of ?cambia_livello_mc? (signals to the user to have reach a new level and to click on it to continue)
- A Movie Clip with an instanze name of ?game_over_mc? (signals to the user that the game is over and to click to start a new game)
- A Movie Clip in library with an name of ?mc_uovo? (I will create more instance of this egg clip in runtime using for example attachMovie)
- a dynamic text field called ?punteggio_txt? (used to store the score)
- a dynamic text field called ? livello_txt? (used to store the actual level)
I create a Document Class, an AS file saved as ?Main.as?, implemented the following way:
Code:
package
{
import flash.display.MovieClip;
import flash.text.TextField;
import flash.utils.Timer;
import flash.events.*;
public class Main extends MovieClip
{
private var timer:Timer;
private var timer_uova:Timer;
public static var livello:int=1;
private var cambio:Number;
private var numUova:int=10;
public var punteggio:int=0;
private var isPressed:Boolean=false;
private var direzione:Boolean=true;
private var destra:Boolean=false;
private var sinistra:Boolean=false;
public function Main()
{
init();
attivaTimer();
listeners();
lanciaUova();
}
private function init():void
{
stage.frameRate=31;
gallina_mc.x=stage.stageWidth/2;
gallina_mc.y=gallina_mc.height+10;
cambio=1000+Math.floor(Math.random()*6000);
cambia_livello_mc.visible=false;
game_over_mc.visible=false;
punteggio_txt.text='punteggio: '+punteggio;
}
private function attivaTimer():void
{
livello_txt.text='livello: '+livello;
timer=new Timer(cambio,1);
timer.addEventListener(TimerEvent.TIMER,lanciaNumero);
timer.start();
}
private function lanciaNumero(t:TimerEvent):void
{
cambio=1000+Math.floor(Math.random()*4000);
livello*=-1;
attivaTimer();
}
private function listeners():void
{
this.addEventListener(MouseEvent.MOUSE_DOWN,settaFocus);
gallina_mc.addEventListener(Event.ENTER_FRAME,muoviGallina);
cesto_mc.addEventListener(Event.ENTER_FRAME,muoviCesto);
stage.stageFocusRect=false;
stage.focus=this;
this.addEventListener(KeyboardEvent.KEY_DOWN,controllaTasto);
this.addEventListener(KeyboardEvent.KEY_UP,azzeraTasto);
}
private function settaFocus(m:MouseEvent):void
{
stage.focus=this;
}
private function muoviGallina(e:Event):void
{
gallina_mc.x+=livello*4;
if(gallina_mc.x>=stage.stageWidth-gallina_mc.width/2)
livello*=-1;
if(gallina_mc.x<=gallina_mc.width/2)
livello*=-1;
}
private function muoviCesto(e:Event):void
{
if(isPressed&&direzione)
e.target.x+=Math.abs(livello)*5;
if(isPressed&&!direzione)
e.target.x-=Math.abs(livello)*5;
}
private function controllaTasto(k:KeyboardEvent):void
{
isPressed=true;
if(k.keyCode==39)
{
destra=true;
direzione=true;
}
if(k.keyCode==37)
{
sinistra=true;
direzione=false;
}
k.updateAfterEvent();
}
private function azzeraTasto(k:KeyboardEvent):void
{
if(k.keyCode==39)
destra=false;
if(k.keyCode==37)
sinistra=false;
if(!destra&&!sinistra)
isPressed=false;
}
private function lanciaUova():void
{
timer_uova=new Timer(1000-Math.abs(livello)*100,numUova);
timer_uova.addEventListener(TimerEvent.TIMER,sgancia);
timer_uova.start();
}
private function sgancia(t:TimerEvent):void
{
var uovo:Uovo=new Uovo(this,timer_uova.currentCount);
}
public function passaLivello():void
{
timer.stop();
this.removeEventListener(MouseEvent.MOUSE_DOWN,settaFocus);
gallina_mc.removeEventListener(Event.ENTER_FRAME,muoviGallina);
cesto_mc.removeEventListener(Event.ENTER_FRAME,muoviCesto);
this.removeEventListener(KeyboardEvent.KEY_DOWN,controllaTasto);
this.removeEventListener(KeyboardEvent.KEY_UP,azzeraTasto);
cambia_livello_mc.visible=true;
cambia_livello_mc.addEventListener(MouseEvent.MOUSE_DOWN,avanza);
}
private function avanza(m:MouseEvent):void
{
livello=Math.abs(livello);
livello++;
attivaTimer();
listeners();
lanciaUova();
cambia_livello_mc.visible=false;
}
public function gameOver():void
{
timer.stop();
timer_uova.stop();
this.removeEventListener(MouseEvent.MOUSE_DOWN,settaFocus);
gallina_mc.removeEventListener(Event.ENTER_FRAME,muoviGallina);
cesto_mc.removeEventListener(Event.ENTER_FRAME,muoviCesto);
this.removeEventListener(KeyboardEvent.KEY_DOWN,controllaTasto);
this.removeEventListener(KeyboardEvent.KEY_UP,azzeraTasto);
game_over_mc.visible=true;
game_over_mc.addEventListener(MouseEvent.MOUSE_DOWN,riprova);
}
private function riprova(m:MouseEvent):void
{
livello=1;
punteggio=0;
punteggio_txt.text='punteggio: '+punteggio;
attivaTimer();
listeners();
lanciaUova();
game_over_mc.visible=false;
}
}
}
I create the Uovo Class, an AS file saved as ?Uovo.as?, implemented the following way:
Code:
package
{
import flash.display.MovieClip;
import flash.events.Event;
public class Uovo extends MovieClip
{
private var Root:MovieClip;
private var id:int;
public function Uovo(m:MovieClip,n:int)
{
Root=m;
id=n;
Root.addChild(this);
init();
}
private function init():void
{
x=Root.gallina_mc.x;
y=Root.gallina_mc.y;
this.addEventListener(Event.ENTER_FRAME,cadi);
}
private function cadi(e:Event):void
{
y+=Math.abs(Main.livello)*3;
if(this.hitTestObject(Root.cesto_mc))
{
this.removeEventListener(Event.ENTER_FRAME,cadi);
Root.removeChild(this);
Root.punteggio++;
Root.punteggio_txt.text='punteggio: '+Root.punteggio;
if(id==10)
Root.passaLivello();
}
if(y>=Root.linea_mc.y)
{
this.removeEventListener(Event.ENTER_FRAME,cadi);
Root.gameOver();
}
}
}
}
The result:
Lets? analise the code step by step:
- the property that I created in the Document Class:
two Timer variables used to change direction to the gallina_mc and to throw the eggs at each interval
private var timer:Timer;
private var timer_uova:Timer;
a numerical variable ( an integrer from the int Class) used for the game?s level of difficulty
public var livello:int=1;
a numerical variable which memorizes a randomed interval of time used to change the direction of the gallina_mc
private var cambio:Number;
a numerical variable which indicates the total of eggs thrown by the hen for each level
private var numUova:int=10;
a numerical variable used to store the game?s score
public var punteggio:int=0;
four boolean variables used for the conditional logics of the user?s movement on cesto_mc using the keyboard
private var isPressed:Boolean=false;
private var direzione:Boolean=true;
private var destra:Boolean=false;
private var sinistra:Boolean=false;
NB: You will notice that some variable have private or public attributs. I need to be able to recuperate variables from the Uovo Class for which reason they are pubblic. For anyone with doubts, I advise you to read this article:
How to declare properties and methods.
- Document Class methods ( Main.as )
init();
I assign the timeline?s frame rate
stage.frameRate=31;
I position gallina_mc
gallina_mc.x=stage.stageWidth/2;
gallina_mc.y=gallina_mc.height+10;
I assign a value to the variable ?cambio?
cambio=1000+Math.floor(Math.random()*6000);
I render cambia_livello_mc and game_over_mc invisible
cambia_livello_mc.visible=false;
game_over_mc.visible=false;
I assign a text to the score?s text field
punteggio_txt.text='punteggio: '+punteggio;
attivaTimer();
I assign a text to livello_txt which indicates the level reached
livello_txt.text='livello: '+livello;
I declare the timer instance after tot seconds (based on the value of the numerical variable ?cambio?) for just one time the lanciaNumero() method and will we see why...
timer=new Timer(cambio,1);
timer.addEventListener(TimerEvent.TIMER,lanciaNume ro);
timer.start();
lanciaNumero();
I update ?cambio? with another random number which would be a second (1000 milliseconds) more a random number in between 0 and 4000 milliseconds
cambio=1000+Math.floor(Math.random()*4000);
I invert the sign of the numerical variable ?livello? (any number multiplied by -1 keeps its own value but change sign), we will see why...
livello*=-1;
I recall the attivaTimer() method
attivaTimer();
listeners();
I add the listeners needed to recall the methods.
I tell Flash to call the settaFocus() function/method for each click of the mouse on stage
this.addEventListener(MouseEvent.MOUSE_DOWN,settaF ocus);
I tell gallina_mc to create an interval (ENTER_FRAME) to call the muoviGallina() method
gallina_mc.addEventListener(Event.ENTER_FRAME,muov iGallina);
I tell cesto_mc to create an interval (ENTER_FRAME) to call the muoviCesto() method
cesto_mc.addEventListener(Event.ENTER_FRAME,muoviC esto);
I tell the stage not to show the focus rectangle which I will apply on the clips
stage.stageFocusRect=false;
I assign the focus to this class (which is nothing else than the timeline, an instance of the MovieClip Class)
stage.focus=this;
I tell Flash to listen to the users when they will press a key
this.addEventListener(KeyboardEvent.KEY_DOWN,contr ollaTasto);
I tell Flash to listen to the users when they will release a key
this.addEventListener(KeyboardEvent.KEY_UP,azzeraT asto);
settaFocus();
I assign the focus to all the stage
stage.focus=this;
muoviGallina();
I move the hen (let?s not forget that we are under the interval ENTER_FRAME) of the value of the variable ?livello? multiplied by four
gallina_mc.x+=livello*4;
I apply the conditional logics for which if the gallina_mc arrives to the end of the stage, or finds itself before the beginning of the stage, the sign of the value changes (here it is why I used *=-1)
if(gallina_mc.x>=stage.stageWidth-gallina_mc.width/2)
livello*=-1;
if(gallina_mc.x<=gallina_mc.width/2)
livello*=-1;
muoviCesto();
I check the movement of cesto_mc with the RIGHT and LEFT keys, applying conditional logics (e.target being who has call the event, in this case cesto_mc)
if(isPressed&&direzione)
e.target.x+=Math.abs(livello)*5;
if(isPressed&&!direzione)
e.target.x-=Math.abs(livello)*5;
NB: Explaining precisely the conditional logics is really difficult. They are calculations that are done in phase of development of the application so I suggest to study them for what they are or to apply others to your liking
controllaTasto();
Also here I apply some conditional logics to check when the keys Right and Left are pressed. To that point I change the value of some Boolean variables
isPressed=true;
if(k.keyCode==39)
{
destra=true;
direzione=true;
}
if(k.keyCode==37)
{
sinistra=true;
direzione=false;
}
azzeraTasto();
Same thing here, I apply conditional logics on the event of the release of a key.
if(k.keyCode==39)
destra=false;
if(k.keyCode==37)
sinistra=false;
if(!destra&&!sinistra)
isPressed=false;
lanciaUova();
I declare the timer instance which will call each tot of seconds (based on the value of 1000 less the absolute number, therefore always with positive sign, of the variable ?livello? multiplied for a cent of second) the sgancia() method as many times as the value of the variable ?numUova?
timer_uova=new Timer(1000-Math.abs(livello)*100,numUova);
timer_uova.addEventListener(TimerEvent.TIMER,sganc ia);
timer_uova.start();
sgancia();
I create an instance of the Uovo.as Class that does nothing else than to attach a Movie Clip from the library. For which reason, I return on main.fla, with the right click in the library on mc_uovo, I activate the option ?exports for Actionscript? and in the field Class I insert Uovo. To the Uovo.as Class, I pass the values of this (that is the Document Class, the timeline, the root...call it as you want) and a numerical value which is the number of times that timer_uova has called, in fact, this method sgancia();
var uovo:Uovo=new Uovo(this,timer_uova.currentCount);
passaLivello();
this method is called by the Egg.as Class (in fact it has a public attribut) and then we will see when it is called...
it does nothing else than to stop timer
timer.stop();
to remove all the listeners (to free some memory)
this.removeEventListener(MouseEvent.MOUSE_DOWN,set taFocus);
gallina_mc.removeEventListener(Event.ENTER_FRAME,m uoviGallina);
cesto_mc.removeEventListener(Event.ENTER_FRAME,muo viCesto);
this.removeEventListener(KeyboardEvent.KEY_DOWN,co ntrollaTasto);
this.removeEventListener(KeyboardEvent.KEY_UP,azze raTasto);
I render the Movie Clip cambia_livello_mc visible
cambia_livello_mc.visible=true;
I asssign a listener on cambia_livello_mc to know when it will be clicked and to that point, Flash will call the avanza() method
cambia_livello_mc.addEventListener(MouseEvent.MOUS E_DOWN,avanza);
avanza();
when cambia_livello_mc is clicked this method is called which...
converts the sign of the value of the variable ?livello? to positive
livello=Math.abs(livello);
adds one to the value of the variable ?livello?
livello++;
calls the attivaTimer() method
attivaTimer();
adds new listeners
listeners();
calls the lanciaUova() method
lanciaUova();
makes cambia_livello_mc invisible
cambia_livello_mc.visible=false;
NB: the same methods are being called as at the beginning the constructive Main class calls...the public function Main()
gameOver();
this method is called only under certain circunstances of the Uovo Class and we will see how...
I stop both timers
timer.stop();
timer_uova.stop();
I remove all the listeners
this.removeEventListener(MouseEvent.MOUSE_DOWN,set taFocus);
gallina_mc.removeEventListener(Event.ENTER_FRAME,m uoviGallina);
cesto_mc.removeEventListener(Event.ENTER_FRAME,muo viCesto);
this.removeEventListener(KeyboardEvent.KEY_DOWN,co ntrollaTasto);
this.removeEventListener(KeyboardEvent.KEY_UP,azze raTasto);
I render the Movie Clip game_over_mc visible
game_over_mc.visible=true;
I assign a listener to the game_over_mc to know when it will be clicked and to that point Flash will call the riprova() method
game_over_mc.addEventListener(MouseEvent.MOUSE_DOW N,riprova);
riprova();
when game_over_mc is clicked this method is called which...
brings back the level to one
livello=1;
brings back the score to zero
punteggio=0;
assigns a text to the punteggio_txt
punteggio_txt.text='punteggio: '+punteggio;
calls the methods of the constructive function...Main() public function
attivaTimer();
listeners();
lanciaUova();
renders the game_over_mc invisibe
game_over_mc.visible=false;
Now, let?s analise the Uovo Class.
Properties
- Root:MovieClip ( the application?s root, the Document Class )
- id:Number ( an ID number passed by Main.as )
In fact the constructive function of the Uovo Class wants 2 parameters:
public function Uovo(m:MovieClip,n:int)
I declare the value of ?Root? to be the same as ?m? passed by Main.as
Root=m;
I declare the value od ?id? to be the same as ?n? passed by Main.as
id=n;
I add this class to the Displyobject (let?s not forget that the ?this? here is refered to the MovieClip mc_uovo placed in library and which will be attached)
Root.addChild(this);
I call the init method
init();
Methods
init();
I position the MovieClip
x=Root.gallina_mc.x;
y=Root.gallina_mc.y;
I create a listener to the interval ENTER_FRAME that will call the cadi() method as many times by seconds based on the value of the frame rate
this.addEventListener(Event.ENTER_FRAME,cadi);
cadi();
I tell the egg to raise the value of Y based on the absolute value of the variable ?livello? of Main.as
(that is the Root) multiplied by 3
y+=Math.abs(Root.livello)*3;
I check if the egg collides with cesto_mc
if(this.hitTestObject(Root.cesto_mc))
{
If it collides, I stop the interval rimoving the listener
this.removeEventListener(Event.ENTER_FRAME,cadi);
I remove the egg from the stage
Root.removeChild(this);
I add the variable ?punteggio? of Main.as
Root.punteggio++;
I assign a text to punteggio_txt
Root.punteggio_txt.text='punteggio: '+Root.punteggio;
I check if the egg that has just touched cesto_mc is the last one asking if its id is equal to the value of the variable numUova of Main.as
if(id==Root.numUova)
If yes, I call the passaLivello() method of Main.as that we have already seen what will perform
Root.passaLivello();
}
I check if the egg?s y is bigger then linea_mc?s y
if(y>=Root.linea_mc.y)
{
If yes, I stop the interval removing the listener
this.removeEventListener(Event.ENTER_FRAME,cadi);
I call the gameOver() method of the Main Class that we have already see what will perform
Root.gameOver();
}
Download source files at downloadssection of this site.
Have fun!