Tutorial: Make a Rhythm Game in AS2 – Part 6


Written By MrSun at 7:36 am - Monday, August 04th, 2008
Categories: All Tutorials, AS2, Flash, Game Development, Intermediate Tutorials

Table of Contents

Step 6: Scoring

The next step in making our rhythm game is scoring. The user will get points depending on how far away the arrow is from the receptor when it hits it. We’re also going to make the health bar gain and lose parts when the user hits or misses the receptor. First of all, we need to define a score variable at the top of the game frame. We also have to define a String variable that will show how well the user hit the arrow.

//the score variable
var score:Number = 0;
//either perfect, great, nice, or good
var scoreString:String = '';

That was pretty easy. Next, we want to increase the score whenever the user hits the right key when it hits the score. We’re going to make it increase by 10 for a perfect hit, 8 for a great hit, 6 for an nice hit, and 4 for a good hit.

if(this.hitTest(_root.mcReceptor)){
	if(Key.isDown(this.arrowCode)){
		//checking if the correct key is down
		//if the user hits it about perfectly
		//the receptors y coordinate is about 10 px away from the
		//symbol's y coordinate.
		if(this._y <= mcReceptor._y + 15 && this._y >= mcReceptor._y + 5){
			score += 10;
			scoreString = 'Perfect';
		} else if (this._y <= mcReceptor._y + 25 && this._y >= mcReceptor._y-5){
			score += 8;
			scoreString = 'Great';
		} else if (this._y <= mcReceptor._y + 40 && this._y >= mcReceptor._y -30){
			score += 6;
			scoreString = 'Nice';
		} else {
			score += 4;
			scoreString = 'Good';
		}
		this.removeMovieClip();
	}
}

The next thing we have to do now is program the health bar. If the user misses or hits the arrow key at the wrong time, then we have to lose health. If the user hits it right though, the health will increase. First of all, give the health bar an instance name, mcHealth. Then, we’re going to make a function for this, so we don’t have to write all the if statements repeatedly. Define this function at the bottom of your code.

//this function will change the health depending on how much health change
//it needs, positive or negative
function changeHealth(healthDiff:Number):Void{
	//checking if the health is already at it's full
	//or will be full after this hit
	if(mcHealth._xscale + healthDiff >= 100){
		mcHealth._xscale = 100;
	} else if(mcHealth._xscale + healthDiff <= 0){
		//checking if the health will be equal or below 0
		//lose function will go here
	} else {
		//if there are no problems
		mcHealth._xscale += healthDiff;
	}
}

The next thing we’re going to do is run this function positively when the user hits the key correctly. In the arrow’s code where it hit tests with the receptor, put this code for perfect:

changeHealth(5);

This will increase the health by 5. You can do the rest yourself, just keep on decrementing the health change by 1, and you’ll be good.

Next comes the hard part, making the user lose health. Again, we have to define a few variables at the top. They will be Booleans saying whether or not the receptor is touching a certain key.

//Booleans checking if the arrows are touching the receptor
var touchLeft:Boolean = false;
var touchUp:Boolean = false;
var touchDown:Boolean = false;
var touchRight:Boolean = false;

We’re also going to have to write a new function for it. This will be an onEnterFrame function for the receptor.

//the receptor will need this onEnterFrame function
mcReceptor.onEnterFrame = function(){
	//first we reset the variables we got last time
	//just in case they aren't true anymore
	touchLeft = false;
	touchUp = false;
	touchDown = false;
	touchRight = false;
	//this for loop will be used for the hit testing
	//it starts off with sArrow-10 because
	//more than that probably will not fit onto the screen and it would
	//waste processing power to start with 0.
	//we might change this later for even better efficiency
	for(i=sArrow-10;i<sArrow;i++){
		//checking if its touching a left arrow
		if(this.hitTest(_root['arrow'+i]) && _root['arrow'+i].arrowCode == Key.LEFT){
			touchLeft = true;
		}
		//checking if its touching a up arrow
		if(this.hitTest(_root['arrow'+i]) && _root['arrow'+i].arrowCode == Key.UP){
			touchUp = true;
		}
		//checking if its touching a down arrow
		if(this.hitTest(_root['arrow'+i]) && _root['arrow'+i].arrowCode == Key.DOWN){
			touchDown = true;
		}
		//checking if its touching a right arrow
		if(this.hitTest(_root['arrow'+i]) && _root['arrow'+i].arrowCode == Key.RIGHT){
			touchRight = true;
		}
	}	
}

Now that we have the variables checking which arrow is touching the receptor, now we need some Key.isDown checkers. We can just add those to the bottom of the mcReceptor function.

//checking if the keys are down when they aren't supposed to be
//and making the user lose health :O
if(Key.isDown(Key.LEFT) && !touchLeft){
	changeHealth(-10);
}
if(Key.isDown(Key.UP) && !touchUp){
	changeHealth(-10);
}
if(Key.isDown(Key.DOWN) && !touchDown){
	changeHealth(-10);
}
if(Key.isDown(Key.RIGHT) && !touchRight){
	changeHealth(-10);
}

The problem with this code is that the user will lose health even when it hits a key, unless he’s amazingly quick. It doesn’t give the user any time to let go of the key before making them lose a bunch of health. There are a few ways to fix this problem. If you find a better way to do it, then go ahead, but this is how my idea works.

Instead of removing the arrow when the user hits the key, we just make it invisible, inactive, but still moving. This way, it’ll still be hit testing the receptor until it leaves. It also helps with the next part of losing health, missing the arrow itself. Place this code in the spot where this.removeMovieClip(); is in the arrow’s enterFrame function.

this._visible = false;
this.gotHit = true;

Now we have to define the gotHit variable. We can do this in the spot where we also define the _y coordinate.

_root['arrow'+sArrow].gotHit = false;

Right now, the variable really doesn’t do anything. We have to turn off the hit testing when gotHit is true. Just replace the hitTest condition with this.

if(this.hitTest(_root.mcReceptor) && !this.gotHit){

Phew, that took a while. Now, for the final part of losing health, when the person misses the arrow altogether. Place this code at the end of the arrow’s onEnterFrame function.

//if the arrow leaves the stage
if(this._y <= -50){
	//if the user didn't already hit the arrow
	if(!this.gotHit){
		changeHealth(-10);
	}
	//destroy this movieclip
	this.removeMovieClip();
}

Well, that’s all for scoring. This probably has been the longest lesson in the series. If you survived through this without having any trouble, then you can do the next part without my help, the finishing touches.

The Final Product:

Source .fla File

«
»