Tutorial: Make a Rhythm Game in AS3 – Part 4
Categories: Flash
Step 4: Programming the Arrows: Part 2
Ok, now that we’ve gotten the arrows onto the stage, we can actually make them move up the stage and hitTest them with the receptors. We’re going to do all of this by making a base arrow class.
The first step to creating such a thing is to create a new Actionscript (.as) file. Immediately save it as “Arrow.as” and place the following code into it:
package{
import flash.display.MovieClip;
import flash.events.*;
public class Arrow extends MovieClip{
public function Arrow(){
}
}
}
This is the basic skeleton for any AS3 class. But, before we add any more code to it, we have to set it as the base class for all of the arrows. Right click on any of the arrow symbols in the library and click on “Properties…”. Under the “Class:” field, there should be another field called “Base Class:”. Right now, it’s set as flash.display.MovieClip. Set it now as “Arrow”. Do this for all four of the arrows. Now, we can add code to the class:
package{
import flash.display.MovieClip;
import flash.events.*;
public class Arrow extends MovieClip{
private var _root:Object;//we'll use this to refer to main timeline
public var arrowCode:int;//the key that needs to be pressed
public function Arrow(){
this.addEventListener(Event.ADDED, beginClass);
this.addEventListener(Event.ENTER_FRAME, eFrame);
}
private function beginClass(e:Event):void{
_root = MovieClip(root); //typing _root is much easier than MovieClip(root)
stage.addEventListener(KeyboardEvent.KEY_DOWN, checkKeys);
}
private function eFrame(e:Event):void{
this.y -= _root.arrowSpeed;//move it up the stage
//if game is over or it's off the stage, destroy it
if(_root.gameOver || this.y < -60){
destroyThis();
}
}
private function checkKeys(e:KeyboardEvent):void{
//checking if a certain key is down and it's touching the receptor
if(e.keyCode == arrowCode && this.hitTestObject(_root.mcReceptor)){
destroyThis();//remove it from stage
}
}
private function destroyThis():void{
this.removeEventListener(Event.ENTER_FRAME, eFrame);
stage.removeEventListener(KeyboardEvent.KEY_DOWN, checkKeys);
_root.removeChild(this);
}
}
}
Now, in order for this code to work, we have to add some stuff to the makeLvl function. Just change it to this:
function makeLvl(e:Event):void{
//code here will create the level
if(sTime < sTempo){
//if the required time hasn't reached the limit
//then update the time
sTime ++;
} else {
//if the time has reached the limit
//then reset the time
sTime = 0;
//if an actual arrow can be made
if(lvlArrayAll[lvlCurrent][sArrow] != 0){
var currentArrow:MovieClip; //this will hold the current arrow
if(lvlArrayAll[lvlCurrent][sArrow] == 1){
//place a left arrow onto the stage
currentArrow = new arrowLeft();
//set the _x value of the arrow so that it is in the
//right place to touch the receptor
currentArrow.x = 135;
//set the arrow's y coordinate off of the stage
//so that the user can't see it when it appears
currentArrow.y = 500;
//setting the key that needs to be pressed
currentArrow.arrowCode = 37;
addChild(currentArrow);//add it to stage
} else if(lvlArrayAll[lvlCurrent][sArrow] == 2){
//place an up arrow onto the stage
currentArrow = new arrowUp();
currentArrow.x = 205;
currentArrow.y = 500;
currentArrow.arrowCode = 38;
addChild(currentArrow);
} else if(lvlArrayAll[lvlCurrent][sArrow] == 3){
//place a down arrow onto the stage
currentArrow = new arrowDown();
currentArrow.x = 275;
currentArrow.y = 500;
currentArrow.arrowCode = 40;
addChild(currentArrow);
} else if(lvlArrayAll[lvlCurrent][sArrow] == 4){
//place a right arrow onto the stage
currentArrow = new arrowRight();
currentArrow.x = 345;
currentArrow.y = 500;
currentArrow.arrowCode = 39;
addChild(currentArrow);
}
}
//get the next arrow if it the song isn't finished
if(sArrow < lvlArrayAll[lvlCurrent].length){
sArrow ++;
} else {
//if the song is finished, then reset the game
//of course, we don't have the code for that yet
//so we're just going to go back to the first frame
gotoAndPlay(1);
gameIsOver = true;
}
}
}
Now, if you test the game now, there's going to be a problem. The game will reset before all of the arrows even reach the receptor. There are two ways that I can think of to fix this. The first option is to count all of the arrow instances on stage and when it's 0, then end the game. The second, which I prefer, is to just add a certain amount of "0"'s to the end of the array each time the game begins. The second option is what I'm going to do. In the beginCode() function, add the following code.
//make the level array longer
lvlArrayAll[lvlCurrent].push(0,0,0,0,0);
Now, the game should be working out pretty well. I'm pretty proud of our progress this lesson, so I'm going to end it now. We've finished the basic gameplay of the game. Next lesson, we will make a menu system where the player can choose which games to play. It'll be great.
Sorry for that post.
I was using AS 2.0 not 3.0. so it didn’t work.
Sorry.
April 22nd, 2009 at 5:03 pm
I can’t get this to work for some reason.
Whenever I try to destroy the objects I keep getting this output error:
TypeError: Error #2007: Parameter hitTestObject must be non-null.
at flash.display::DisplayObject/_hitTest()
at flash.display::DisplayObject/hitTestObject()
at Arrow/checkKeys()
That being said I did tamper with the code a little to allow for five objects instead of the four arrows.
August 31st, 2009 at 11:28 pm
Hey great tutorial so far.
Im having some problem with the receptor i always get this error
when i hit the keys.
TypeError: Error #2007: Parameter hitTestObject must be non-null.
at flash.display::DisplayObject/_hitTest()
at flash.display::DisplayObject/hitTestObject()
at Arrow/checkKeys()
Does anyone have an idea what im doing wrong?
November 10th, 2009 at 12:06 pm
after saving the code as a as. file, now i went to properties and typed “arrow” by the catagory “Base Class” but it says it cannot be changed. does typing it in “Class” differ from typing it in the “base class”?
April 9th, 2010 at 10:03 am