Here’s what I plan to be a quick bit of information about how to turn the code that makes things move around the screen (which can be found in my beginner’s actionscript animation tutorial) into a game like Chase The Cheese.
Before we get started, if you haven’t already had a look at the game then go do that now, it’ll make the rest of this more easy to understand.
In the previous tutorial I showed you how to make things move around the screen using actionscript to make them shift along each time a frame loop happened. If you look at the game, there are three blocks bumping up and down, just like we set up in the tutorial, except that they are going vertically not horizontally.
This is very easily done, but first we set a few variables. Do this before you get into the game loop; I set-up my movies with the opening/loader page on frame one, my variables on frame two, then the game loop on frames three and four. If you put the variables in the loop frame then they will be reset everytime that frame is played. For example, you might have a speed variable that starts at 5 pixels per frame and you wanted to increase this in relation to the score, if everytime the loop plays the code sees ‘speed = 5;’ then it will never change. Put your variables before your loop and you avoid this problem and it also makes it easier to find them to adjust them. Believe me, finding things can be quite tricky in later stages of programming because things can quickly accumulate!
So, set some variables:
// init game variables
LEFT = 40;
RIGHT = 720;
TOP = 0;
BOTTOM = 315;ch2.gotoAndPlay(“start”);
playerhit._x = 20;
player._x = 20;
score = 0;//init block directions
b1move = 1;
b2move = -1;
b3move = 1;//block speeds
b1speed = 5;
b2speed = 5;
b3speed = 5;
What have we got here?
Firstly there are the limits of the screen that I want to use measured in pixels, that’s simple enough to understand.
The next block is more complicated:
ch2.gotoAndPlay(“start”);
‘ch2’ is the name of my cheese movieclip on the right of the screen (in case you’ve forgotten, you give things names by clicking on them then typing it into the name box on the Properties panel). It has a label on its own timeline called ‘start’ which triggers the animation of the cheese moving onto the screen. This gives our mousey something to chase when the game starts. Without this command the cheese would remain at frame one of its own timeline where there is a simple actionscript command telling it to ‘stop();’.
playerhit._x = 20;
player._x = 20;
Rather than have the mouse graphic as the thing that hits the blocks I go for a rectangle graphic called ‘playerhit’. This is a simple movieclip the size of the mouse-body that is drawn in a colour with an alpha level of 0%. This makes it invisible. By doing this I make sure that the player survives if only their tail hits the block. This gives the player a bit of leeway and improves the feeling of accuracy in the game. I’ve put the mousey (‘player’) and the thing that hits the blocks (‘playerhit’) on the stage at the same height, so I just need to make sure they are both beginning in the same place on the x-axis, so I set both the _x values to 20.
score = 0;
Obviously, this sets the score at 0. If we didn’t define this as zero now, when the game started the score would be ‘NaN’, which is Flash’s way of telling you that you’ve not given a variable a value yet. Setting the score to zero here also means that if a person chooses to play again then you can set the movie to loop to this point and they don’t get their last game’s score still stuck in the system.
What was next?
//init block directions
b1move = 1;
b2move = -1;
b3move = 1;
//block speeds
b1speed = 5;
b2speed = 5;
b3speed = 5;
Here we’re setting up a value for a block’s initial direction and its initial speed. We’ll use these in just a moment.
Okay, let’s get our blocks moving. I’m going to do this in the most simple way possible. There are more efficient ways of coding, but sometimes it saves brainpower to just do things the brute force way. The appeal of doing things simply is that if something goes wrong then there are less places to check. So, we’re onto code that we want to run every loop so let’s put this in the looping frames:
block1._y += b1speed*b1move;
if (block1._y >= BOTTOM) {
block1._y = BOTTOM;
b1move *= -1;
b1speed = Math.random()*(score/2)+5;
} else if (block1._y < = TOP) { block1._y = TOP; b1move *= -1; b1speed = Math.random()*(score/2)+5; }
Hopefully if you’ve gone through the previous tutorial you’ll be happy with ‘if’ statements. These are simply
if (this is true) {
do this;
}
So, firstly we move the movieclip called block1 along the y axis:
block1._y += b1speed*b1move;
We do this by getting it’s current position (block1._y) then adding to this (+=) the value of b1speed (which initially we set to be 5) multiplied by the value of b1move (which we set to be 1). This means that to begin with the block will move down the screen at a rate of 5 pixels per loop. Don’t forget that in Flash, and most web-design, the numbers on the y axis increase as you go down the screen.
We then have an if statement:
if (block1._y >= BOTTOM) {
Simply, if after the previous adjustment to the value of block1._y it is now a value bigger than or equal to BOTTOM then run the code in curly brackets. We set the variable BOTTOM in frame two, so this should be pretty easy to understand, it just means that if the block is at the bottom of the screen then the code is run. I put ‘BOTTOM’ in capital letters when I was defining my variables to remind me that this is a variable that isn’t changed by the code at any point.
Let’s have a look at what’s run next:
block1._y = BOTTOM;
b1move *= -1;
b1speed = Math.random()*(score/2)+5;
}
first we set bock1._y to be the same as the BOTTOM value, this makes sure it doesn’t disappear off the screen at any point. We then get the value ‘b1move’ and multiply it by -1. We could write this line as
b1move = b1move*1
but using the ‘*=’ code does this in a quicker way.
Lastly we set a new value for the speed of the block, b1speed. Let’s look at that line more carefully:
b1speed = Math.random()*(score/2)+5;
In English that says:
We’re talking about b1speed here and we want to change its value. Make the value of b1speed equal the following… Pick a random number between zero and one, multiply it by half the value of ‘score’, then add five.
‘Math.random()’ gives you a random number between zero and one. This is fine, but we want to change the speed a little more than just adding .3 of a pixel to each loop! To do this we multiply it by a number that is increasing as the player gets further into the game, ie. the score. Everytime a person gets a piece of cheese the score goes up. To begin with this won’t make much difference, if the score is ‘2’ then we get something like:
b1speed = (randomly generated .3) * (2/2) + 5
Which would mean that the new speed of the block is 5.3 . I decided to divide the score by two because otherwise the speed of the blocks increased too fast. Given that the game is perhaps a bit too difficult, maybe I should have divided it more… It’s in changing things like this that you can create difficulty levels for your games. Anyway, with a score of 2 things don’t change much, let’s have a look at a score of 8:
b1speed = (randomly generated .3) * (8/2) + 5
That gives us 6.2, which is more than 20% faster than the basic speed. With a score of eight you can get speed values between 5 and 9, making it far harder to get across safely.
These new values for b1move and b1speed are then applied each loop until the value of block1._y is less than or equal to TOP. I’m sure you get the idea of what’s going on here.
To keep things simple I then just copied this code out another two times and changed the names to block2, b2move, b2 speed, block3, etc.
So, how do we make things hit eachother?
At the very start of the actions for the frame, before the movement code, I put in this:
if (playerhit.hitTest(block1)) {
gotoAndPlay(“gameover”);
} else if (playerhit.hitTest(block2)) {
gotoAndPlay(“gameover”);
} else if(playerhit.hitTest(block3)) {
gotoAndPlay(“gameover”);
}
This is a simple bit of code that checks to see if ‘playerhit’ is overlapping ‘block1’, or ‘block2’, or ‘block3’. the ‘hitTest’ code is very useful, it also has optional parameters for greater accuracy, but if you use my method of having an invisible ‘playerhit’ box rather than using the actual visible mousey then you don’t really need to worry about those.
I think the hitTest code is pretty self-explanatory, and it triggers a movement to the timeline frame with the label ‘gameover’.
One quick point here: to begin with I had my hitTest code running after the movement code. As I said above, it’s important to put it above this. The reason for this is that when the movement code runs it sets the new values of x and y axis variables. If the player is hit and you check for that hit after the movement code has run then the person playing never actually sees the impact before getting sent to the gameover screen. If you check the hit before the code runs then the movement animation happens and the hit is detected on the next loop. You only see the changes made by actionscript on screen when the playhead goes to the next frame, so if you check the hit after the actionscript has moved the mousey then it won’t have time to be shown to the user before they are sent to the gameover point. If you check at the start of each loop then you are really checking to see if the movement from the previous loop has created a hit. ‘Hope that makes sense!
I’ve not covered here the ways to tie the movement of the mousey into the user’s mouse movements and I don’t have time at the moment, so I’ll just say this: if you have the mousey correspond precisely with the position of the user’s arrow then the user could take their arrow off the side of the movie (where Flash can’t detect it) on one side and bring it back on on the other and according to the movie the mouse will have warpped from one side to the other, missing all obstacles and rather defeating the point of the game. For this reason I put in place the acceleration scale at the bottom of the screen. It’s quite a neat idea, but I think it might be a bit too obscure for many players. Oh well, you live and you learn!
Control is a design challenge all on its own, so maybe I’ll tackle that another day. Until then, I hope this has been an interesting insight into the use of actionscript in Flash games programming.