Table of contents for AS3 Avoider Game Tutorial
- Learn ActionScript 3 by Following this Simple Avoider Game Tutorial
- AS3 Avoider Game Tutorial, Part 2: Multiple Enemies
- AS3 Avoider Game Tutorial, Part 3: Game Over
- AS3 Avoider Game Tutorial, Part 4: Menus and Buttons
- AS3 Avoider Game Tutorial, Part 5: A Score and a Clock
- AS3 Avoider Game Tutorial, Part 6: Several Small Improvements
- AS3 Avoider Game Tutorial, Part 7: Keyboard Control
- AS3 Avoider Game Tutorial, Part 8: Adding a Preloader
- AS3 Avoider Game Tutorial, Part 9: Music and Sound Effects
- AS3 Avoider Game Tutorial, Part 10: Multiple Levels
- AS3 Avoider Game Tutorial, Part 11: Saving and Loading
- AS3 Avoider Game Tutorial, Part 12: Garbage Collection
We’ve got a lot of the features necessary for a game to be considered a game, but we’re missing a key ingredient: progression. At the minute, the game doesn’t get any harder, so there’s no real sense of achievement for surviving the game for a long time, since it all comes down to luck and stamina. It’s also the case that after a few seconds of play, you’ve seen everything the game has to show you — not just from a graphics point of view, but from a gameplay/experience point of view, too.
Therefore, in this part of my AS3 and Flash CS3 conversion of Frozen Haddock’s avoider game tutorial, we’ll add new levels the player can reach.
Click the preview image below to check out how this will play:
If you’ve not been following the tutorial, grab the zip file of the game so far here and extract it somewhere. Otherwise, copy the files you’ve been working on so far to a new folder, as usual. Open the FLA file, and let’s get started.
What Are Levels?
Before we decide to add levels to our game, let’s look at the different ways other game developers have incorporated levels.
In Dodge, you start off pitted against a few yellow enemies.

When you destroy all enemies, you’re given a quick breather and a chance to trade points for health before moving on to the next level. Later levels increase the number of enemies on-screen, and also introduce more kinds of enemies, like this blue one:
Amorphous+ does not have the same sort of level structure. You effectively choose what level to play at the start, picking the number of enemies to fight or the rate at which the difficulty increases, or specifying a specific type of enemy to practise against. Within the game, you play the level through to the end (or until you die), and the longer you survive, the more vicious the enemies that spawn:
The level’s background is picked at random when you start playing:
Finally, Four Second Frenzy is different from all the above. Like the WarioWare series of games, it uses “microgames” with completely different objectives, rather than simply adding new elements to a single core game.
The microgames do all tie in to a single control structure and set of lives, though.
So, clearly, there are a lot of different meanings to this idea of a “level”. A change in level might simply mean a visual change, but more often it’ll mean a change in the difficulty, the types of enemies, the scoring conditions, or even the entire ruleset of the game! You need to decide what levelling up means in your game.
What I’ll Do
Based on what I’ve said in previous parts of this tutorial, it may seem natural to make one class per level, with each class extending AvoiderGame, and use events to switch between them. So, we might have classes named AvoiderGameLevelOne, AvoiderGameLevelTwo, etc., and let each one fire off a “NavigationEvent.NEXT_LEVEL” when appropriate. Presumably then the document class would listen for this event, and when it heard it, it would run “playScreen = new AvoiderGameLevelTwo()” (or whichever level was appropriate), and pass through all the information such as score and time to this new playScreen instance.
That structure would work, and it does seem to follow what we’ve already done with the different screens in the game. It would also be particularly useful for a game like the aforementioned Four Second Frenzy, whose levels were made by different people. The trouble is, it’s very restrictive for any game that wants to keep a single set of rules.
For one thing, we’d be restricted to a finite set of levels. If the player finishes AvoiderGameLevelTen and there’s no AvoiderGameLevelEleven, then that’s it, game over. This is fine for some games, especially if a story is involved, but for an arcade-style game that we want to keep getting more challenging rather than just ending, it’s hardly ideal.
Consider Tetris. At the end of each level, all that happens is the blocks fall faster, and the score earned for making a line increases. Some versions change the background colour too. If we were going to use one class per level, then we’d lose all the blocks that had already fallen each time we created a new level. If we wanted to keep them, we’d have to pass all the information about where they were up to the document class, and then let the document class pass that information back down into the new level. And we’d still have to stop increasing the falling speed and points earned per line once we ran out of level classes.
I’m going to base my level structure on Tetris, with a new level meaning a change in background and a greater number of enemies appearing per tick. Therefore, I don’t want to use the class-per-level approach. But what can we do instead?
When you think about it, all the AvoiderGame class contains is a set of rules, the mechanics of the game. When you press “up”, AvoiderGame checks its list of rules and sees that this means the avatar should be moved up a few pixels. Every time a new enemy is created, AvoiderGame knows to add some points to the score. But we could easily alter the exact number of pixels the avatar should move, or the exact number of points to add to the score, without changing the underlying structure of the rules.
So, we can create new levels simply by changing these values depending on what level the player is on. We could use if statements, like so:
if ( currentLevel == 1 ) { gameScore.addToValue( 10 ); } else if ( currentLevel == 2 ) { gameScore.addToValue( 15 ); } else if ( currentLevel == 3 ) { gameScore.addToValue( 22 ); } |
…but then we end up with bits of level-specific code dotted all around the class, with no easy way to find or edit it all at once. Close, very close, but not quite good enough.
The best solution I know of is to store all the level-specific information in a separate place from the rules, and then have the AvoiderGame class request the values it needs for the current level. Read on to find just how to do that.
The LevelData Class
Let’s start by making a striking and obvious visual change between levels: the background.
Start by opening up the PlayScreen symbol in the library (remember this is linked to the AvoiderGame class file). At the minute, the background is just sort of drawn on to the PlayScreen itself. If we want to be able to change it using code, we’ll have to make it a symbol of some kind. Select all of it, being careful not to select the clock and score (you can select multiple objects by holding shift while clicking them):
To make this into a symbol (in this case, we’ll make it a movie clip), click Modify > Convert To Symbol. Call it BackgroundContainer — I’ll explain why in a minute — and export it for actionscript with the same name.
Because we have a preloader, we need to uncheck the Export in first frame box, and add the movie clip to the AssetHolder movie clip. For more information on doing that, check out Part 8. From now on, I’m not going to mention it, so be sure you remember to do it for each symbol. You can of course leave it, then do it for a bunch of symbols at once, perhaps when you finish the game.
Anyway, edit the BackgroundContainer if you’re not doing so already, and again select all of the background elements and convert them to a new symbol of type movie clip. I’m calling mine BlueBackground but of course this might not be appropriate for whatever you’ve drawn, so name it accordingly. Export it for ActionScript with the same name, too.
Now, go back to editing PlayScreen, and give the BackgroundContainer movie clip an instance name of backgroundContainer. It’ll probably be in front of the score and clock, so right-click it, select Arrange, and click Send to Back:
So now the PlayScreen contains a movie clip of class BackgroundContainer, which in turn contains another movie clip that is our BlueBackground.
Great. Now right-click the BlueBackground in the library, and select Duplicate. Call it RedBackground, export it for ActionScript, and start editing it. Here’s what mine looks like:
No surprises there. Save it and run it to make sure everything’s still working with the blue background.
Now it’s time to make the class that’ll contain the level-specific information. Create a new AS file, and save it as LevelData.as in the Classes directory. Here’s the base code:
1 2 3 4 5 6 7 8 9 10 | package { public class LevelData { public function LevelData() { } } } |
Note that it’s not extending anything — it doesn’t need to. We want this to contain all the data relevant to the level, and at the minute that’s just the background colour, so add a class-level variable called backgroundImage:
1 2 3 4 5 6 7 8 9 10 11 12 | package { public class LevelData { public var backgroundImage:String; public function LevelData() { } } } |
How do we link the level number to the background, though? Like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | package { public class LevelData { public var backgroundImage:String; public function LevelData( levelNumber:Number ) { if ( levelNumber == 1 ) { backgroundImage = "blue"; } else if ( levelNumber == 2 ) { backgroundImage = "red"; } } } } |
So when we create a new instance of this LevelData class, we’ll pass through the number of the level that we’re currently on, and it’ll set its backgroundImage variable to the colour corresponding to that level’s background. We can then obtain this variable from within AvoiderGame. Let’s do that now.
Save this class file, and go back to AvoiderGame.as. Create a new class-level variable to hold the current level’s data:
27 | public var currentLevelData:LevelData; |
In the constructor function, instantiate this object like so:
29 30 31 | public function AvoiderGame() { currentLevelData = new LevelData( 1 ); |
Now, currentLevelData.backgroundImage will contain the text “blue”. Feel free to trace() it to check it’s working. What we’re going to do now is put the correct background into the, well, background:
29 30 31 32 33 34 35 36 37 38 39 | public function AvoiderGame() { currentLevelData = new LevelData( 1 ); if ( currentLevelData.backgroundImage == "blue" ) { backgroundContainer.addChild( new BlueBackground() ); } else if ( currentLevelData.backgroundImage == "red" ) { backgroundContainer.addChild( new RedBackground() ); } |
What this is doing is addChild-ing the correct background image to the backgroundContainer clip, not to the play screen. Since the background container is already right at the back, this means it’ll stay behind the score, the clock, the avatar and the enemies. If we just wrote addChild( new BlueBackground() ) we’d have to manually move it to the back. This solution is kind of like painting over a wall with the background image we want to display; we’re not actually removing the image that’s already there, just sticking something new on top of it. Obviously this is inefficient.
You might be wondering why we don’t just place an instance of BlueBackground on the play screen, with an instance name of backgroundImage, and then write, backgroundImage = new RedBackground() as we need to. The issue is that since BlueBackground and RedBackground are different classes, we can’t just swap them like that, even though they are both just sub-classes of MovieClips. We can get around this by unchecking the Automatically declare stage instances option in the Publish Settings, and this is not very complicated, but it’d require adding quite a lot of code so I don’t want to go into it now.
Anyway, if you save and run it, you’ll see that the game has a blue background. Great, but that doesn’t exactly prove anything. So change the 1 in this line:
currentLevelData = new LevelData( 1 ); |
to a 2:
currentLevelData = new LevelData( 2 ); |
Save it and run it again:
Awesome.
Level Up!
That basically shows that we can skip to a specific level, but how about actually progressing to a new level from within the game?
First we need to decide what a player needs to do to get to the next level. One idea I’ve seen a couple of people suggest in the comments and by email is placing a target on-screen that the avatar has to reach to get to the next level. That’s a cool idea, but I’m going to do something simpler for now; I’m just going to put the player in a new level when they reach a certain score.
Change that 2 back to a 1 so that the player starts on the first level. Now, the best place to check the player’s score is in the onTick() function, so move to that part of the code. I’m going to add the check right at the end of the function, so that everything else can happen first:
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 | if ( avatarHasBeenHit ) { bgmSoundChannel.stop(); dispatchEvent( new AvatarEvent( AvatarEvent.DEAD ) ); } if ( gameScore.currentValue >= 150 ) { currentLevelData = new LevelData( 2 ); if ( currentLevelData.backgroundImage == "blue" ) { backgroundContainer.addChild( new BlueBackground() ); } else if ( currentLevelData.backgroundImage == "red" ) { backgroundContainer.addChild( new RedBackground() ); } } } |
Lines 183-194 are the new ones. Well, I say that, but lines 186-193 are copied from above, so let’s move them to a new function, setBackgroundImage():
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 | if ( avatarHasBeenHit ) { bgmSoundChannel.stop(); dispatchEvent( new AvatarEvent( AvatarEvent.DEAD ) ); } if ( gameScore.currentValue >= 150 ) { currentLevelData = new LevelData( 2 ); setBackgroundImage(); } } public function setBackgroundImage():void { if ( currentLevelData.backgroundImage == "blue" ) { backgroundContainer.addChild( new BlueBackground() ); } else if ( currentLevelData.backgroundImage == "red" ) { backgroundContainer.addChild( new RedBackground() ); } } |
That’s neater. Go back and replace those lines with a call to setBackgroundImage() in the constructor function, too.
If you save and run this, you’ll find that although it does change the background after you get enough points, it runs awfully slowly. The reason for this is the if statement that we’re using:
if ( gameScore.currentValue >= 150 ) |
Obviously that’ll still be true if the score is 160, 170, or over 9000. So every tick after you get 150 points for the first time, it’s going to run; 40 times a second, a new background will be created and painted over the old one. No wonder it gets a bit laggy.
How can we fix this? Well, here’s my solution. First, add a new variable, pointsToReachNextLevel, to the LevelData class, and set it up like so:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | package { public class LevelData { public var backgroundImage:String; public var pointsToReachNextLevel:Number; public function LevelData( levelNumber:Number ) { if ( levelNumber == 1 ) { backgroundImage = "blue"; pointsToReachNextLevel = 150; } else if ( levelNumber == 2 ) { backgroundImage = "red"; pointsToReachNextLevel = 9999999; } } } } |
(I’ve temporarily set it to some ridiculously huge number to reach level three since we haven’t got there yet.) Now, back in AvoiderGame, just set that troublesome if statement to use this new variable:
176 177 178 179 180 | if ( gameScore.currentValue >= currentLevelData.pointsToReachNextLevel ) { currentLevelData = new LevelData( 2 ); setBackgroundImage(); } |
Test it out, and it should work fine. Excellent! Now how about increasing the rate at which enemies appear on level two? It’s really simple; you might want to try it out yourself before reading on.
All you need to do is add a new variable to the LevelData class (and set it up):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | package { public class LevelData { public var backgroundImage:String; public var pointsToReachNextLevel:Number; public var enemySpawnRate:Number; public function LevelData( levelNumber:Number ) { if ( levelNumber == 1 ) { backgroundImage = "blue"; pointsToReachNextLevel = 150; enemySpawnRate = 0.05; } else if ( levelNumber == 2 ) { backgroundImage = "red"; pointsToReachNextLevel = 9999999; enemySpawnRate = 0.1; } } } } |
…and then use this in AvoiderGame (see line 126 below):
126 127 128 129 130 131 132 133 134 | if ( Math.random() < currentLevelData.enemySpawnRate ) { var randomX:Number = Math.random() * 400; var newEnemy:Enemy = new Enemy( randomX, -15 ); army.push( newEnemy ); addChild( newEnemy ); gameScore.addToValue( 10 ); sfxSoundChannel = enemyAppearSound.play(); } |
Infinite Levels
I said above that one of the disadvantages of using one class per level was that we would be restricted to a finite set of levels. So far, we’ve only got two, which is hardly worth boasting about. Let’s add a couple more. Start by adding the level-specific data to the LevelData class:
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | public function LevelData( levelNumber:Number ) { if ( levelNumber == 1 ) { backgroundImage = "blue"; pointsToReachNextLevel = 150; enemySpawnRate = 0.05; } else if ( levelNumber == 2 ) { backgroundImage = "red"; pointsToReachNextLevel = 350; enemySpawnRate = 0.1; } else if ( levelNumber == 3 ) { backgroundImage = "blue"; pointsToReachNextLevel = 600; enemySpawnRate = 0.13; } else if ( levelNumber == 4 ) { backgroundImage = "red"; pointsToReachNextLevel = 9999999; enemySpawnRate = 0.15; } } |
Since I’ve only got two backgrounds, I’m just alternating between them. Naturally you can make more and use those, as long as you alter the setBackgroundImage() function accordingly.
We’ve got a problem, though. Check out that if statement again:
176 177 178 179 180 | if ( gameScore.currentValue >= currentLevelData.pointsToReachNextLevel ) { currentLevelData = new LevelData( 2 ); setBackgroundImage(); } |
Line 178 above shows us that we’re just going to keep loading level 2 over and over again. We need to move it to the next level, i.e. we need to run something like, currentLevelData = new LevelData( currentLevelNumber + 1 );. We could create a new variable within AvoiderGame called currentLevelNumber, but I think we might as well store this in LevelData as well. Just alter it like so:
5 6 7 8 9 10 11 12 | public var backgroundImage:String; public var pointsToReachNextLevel:Number; public var enemySpawnRate:Number; public var levelNum:Number; public function LevelData( levelNumber:Number ) { levelNum = levelNumber; |
I’d call the variable levelNumber, but that’s what I’ve called the variable I’m passing into the constructor function, so levelNum will have to do. Now in AvoiderGame we just have to refer to this value:
176 177 178 179 180 | if ( gameScore.currentValue >= currentLevelData.pointsToReachNextLevel ) { currentLevelData = new LevelData( currentLevelData.levelNum + 1 ); setBackgroundImage(); } |
Save it and run it, and you’ll see we now have four levels (but if you manage to get ten million points you’ll get a lot of errors). That’s fine and all, but why not shoot for infinitely many levels?
All we have to do for that is decide on a general rule for setting these values. If you’ve done “nth term” sequences in algebra class you’ll understand this. Take a look how I’ve done it for the numeric values:
31 32 33 34 35 36 37 38 39 40 41 42 | else if ( levelNumber == 4 ) { backgroundImage = "red"; pointsToReachNextLevel = 770; enemySpawnRate = 0.15; } else { backgroundImage = "blue"; pointsToReachNextLevel = levelNumber * 200; enemySpawnRate = 0.6 - ( 2 / levelNumber ); } |
(Don’t forget to change the points to reach level 5 to be something a bit more manageable!)
If you work the maths out, you can see that when the player gets to level five, they need 1000 points to reach the next level, and the enemies spawn at a rate of 0.2 per tick. Level six requires 1200 points to pass, and the enemies spawn at a rate of roughly 0.27 per tick. You can continue this onwards forever, though the game does get pretty slow once a lot of enemies have been spawned (we’ll talk about fixing this problem in Part 12).
We’re nearly done, but there’s one thing that still bugs me — the background stays blue from level five onwards. Of course, we could use Math.random() to pick the colour of the background after level four, but I’d much rather have it alternate between blue and red.
To achieve this, we can use the modulo function, which I’ve not introduced yet. Modulo gets you the remainder after a division. One divided by two is zero remainder one, so one modulo two is one. Two divided by two is one remainder zero, so two modulo two is zero. Three divided by two is one remainder one, so three modulo two is one. You get the idea; basically levelNumber modulo two will alternate between one and two; levelNumber modulo five would count from one to five and then start again. If you’d like to read lots and lots about the modulo operation, check out Wikipedia’s article.
Anyway, it’s simple to add. Modulo is represented in code by the percentage sign, %, so we can use it like so:
37 38 39 40 41 42 43 44 45 46 47 48 49 | else { if ( levelNumber % 2 == 1 ) { backgroundImage = "blue"; } else { backgroundImage = "red"; } pointsToReachNextLevel = levelNumber * 200; enemySpawnRate = 0.5 - ( 2 / levelNumber ); } |
Easy.
Challenges
This opens up a huge range of challenges you can attempt. For starters, how about displaying the current level number and the number of points required to reach the next level? You could also alter the speed of the enemies or the avatar as the player gets further through the game. And if I tell you that all movie clips (and thus all classes extending movie clips) have .scaleX and .scaleY properties that alters the width and height of the object (so that setting it to 1 is normal size, 2 is twice as big as normal, and 0.5 is half as big as normal), could you alter the size of the enemies and avatar according to the level?
If you’ve added different kinds of enemies to your game, you might want to have multiple spawn rates, one for each kind, so that you can let the nastier enemies appear more and more often as the player gets further through the game (like in Amorphous+). If you haven’t done this, you could combine this idea with the above tip regarding scaleX and scaleY, and use different sizes of the standard enemy instead of different types.
How about splash screens between levels? You can use gameTimer.stop() to effectively pause the game, and then pop up a simple button for the player to click to move on to the next level using the “GameOverText” method from Part 3. You could even create cutscene movie clips to go in-between certain levels.
Bonus levels could be cool, too. For example, every fifth level make coins appear instead of enemies, and hitting them adds to your score instead of killing the player.
You could also alter the conditions for moving to the next level. Perhaps base them on time rather than score, or on reaching a different point in the level. Maybe you could make a level select screen, or have a cheat code that players can enter to skip a level.
If you have any other ideas, please stick them in the comments so that other people can try them!
Wrapping up
Hey, look at that, we’re all done and we didn’t import or extend anything, or add any event listeners! That’s pretty unusual.
As always, you can download a zip with all the files relating to this part of the tutorial here.
In the next part, we’ll look at creating and reloading savegames.

{ 90 comments… read them below or add one }
← Previous Comments
Oh, when I talked about implementation I meant “are you going to change your game to work this way?”
Good tip with including separate files, but actually you don’t need to switch to frame-based code to do that. If you have a class called
StandardFunctionsin your/classes/directory, and it contains a static function called getRotationToPoint(), you can just write:…and then you can use it like this:
StandardFunctions.getRotationToPoint()!great hint! Thanks
Hello,
first of all, thanks for this amazing tutorials!
I am a real newbie, and I’m getting really frustrated trying to understand how ActionScript works.
I’m getting there really slowly but at least I can see the potential of such a useful tool.
Now, I’m trying to do something that is apparently not too hard, but that I can’t really figure it out.
I would like to increase the speed of the enemies every level more. I tried to work on the levelData.as using different solutions involving the Enemy.as file as well, but nothing happenened, I mean at the moment I’m not even getting any error from flash, it just doesn’t work
that’s the last try:
package { import flash.display.MovieClip public class LevelData extends Enemy { //public var backgroundImage:String; public var pointsToReachNextLevel:Number; public var enemySpawnRate:Number; public var speedIncrease:Number; public var levelNum:Number;}
Can you give me an hint on how to proceed?
Thank you again very much!
Hey FlashTrainee, thanks for the kind words
That’s an interesting idea, making the LevelData extend Enemy. I see what you were trying to do there, and I think it’d be neat to see that taken further. However, just to keep things simple for myself and for other readers, I’m going to talk as though you hadn’t made any changes from the tutorial yet, i.e. as though LevelData did not extend Enemy.
In this case, I would suggest creating a
public var enemySpeed:Numberinside LevelData, much as you have. Then, in eachifstatement, I’d set that to a new number, like so:if (levelNumber == 1) { backgroundImage = "blue"; pointsToReachNextLevel = 10; enemySpawnRate = 0.10; enemySpeed = 1; } else if (levelNumber == 2) { backgroundImage = "green"; pointsToReachNextLevel = 50; enemySpawnRate = 0.15; enemySpeed = 1.2; } else if (levelNumber == 3) { backgroundImage = "blue"; pointsToReachNextLevel = 150; enemySpawnRate = 0.25; enemySpeed = 1.35; }… and so on.
My idea is to make the enemy’s speed be multiplied by this enemySpeed value. So, if on level one the enemies move at 3 pixels per second, then on level two they will move at (3 * 1.2) pixels per second, and so on. The best place to do this is in the
moveABit()function inside Enemy.as. Instead of…you would need something like:
The tricky part here is, how do you pass
enemySpeedto the Enemy?I’ll just give a hint here — you can do it the same way you pass
startXandstartYto the enemy when you create it.Hope that helps
I’m getting an error that i need help with, iv tryed to figure it out what, and how to fix, but with no luck.
I think the mistake is in the Flash file, but not totaly sure…
Please help:D
Errors:
AvoiderGame.as, Line 204 1120: Acess of undefined property backgroundContainer.
AvoiderGame.as, Line 204 1180: Call to a possibly undefined method BlueBackground.
AvoiderGame.as, Line 208 1120: Acess of undefined property backgroundContainer.
Codes:
204: backgroundContainer.addChild( new BlueBackground() );
208: backgroundContainer.addChild( new RedBackground() );
I both got a Blue and a Red background, so i don’t understand why the 1180 error only comes on the blue and not the red one…
Hey DudexD,
That is weird that only the blue background causes the #1180. Is the symbol definitely exported for AS with the name
BlueBackground?As for the #1120, it sounds like perhaps your
BackgroundContaineron the play screen does not have an instance name ofbackgroundContainer.Hope that helps
Woops
Shouldn’t be working on this early in the morning:D
Atleast i got it to work now thanks to your guiding.
By the way great tutorials!:D
But there was also something i was wondering, about the Arrow Movement, and it is that if you Hold both Left and Up it should go in both direction at the same time. because as it is now, it is really anoying.
Also, in the LevelData.as i’m having a problem now,
Since i got 4 backgrounds red, blue, yellow and green i’m not totaly sure about how to fix it with the:
else
{
if ( levelNumber % 2 == 1 )
{
backgroundImage = “blue”;
}
else
{
backgroundImage = “red”;
}
I understand that if i set:
else
{
backgroundImage = “yellow”;
}
after that it wont work. i think maybe i know what to do, but i don’t wanna mess it up, so ill ask instead.
Re. diagonal movement: I actually left that out on purpose as a challenge for you
But Daniel Sidhion has written a tutorial to explain it here, if you’d like more direct instructions.
For the different backgrounds, why don’t you post your idea?
so you want it that way??:D
Well i’m not good at explaining tho. so i’m going to test my theories out, then come with feedback:P
HOLY! i did it! it worked! like, all by myself…. well almost
Heres my code
if ( levelNumber % 4 == 1 ) { backgroundImage = "blue"; } else if ( levelNumber % 4 == 2 ) { backgroundImage = "red"; } else if ( levelNumber % 4 == 3 ) { backgroundImage = "yellow"; } else { backgroundImage = "green"; }By the way how do you add those fancy code thingys in comments on this page?
Congrats
Nice code
You can use <pre> and </pre> to make simple code boxes, by the way. I’ve edited your comment to do this.
Thank you
Well i better head on to the next tut.
i tried to put level display on the game overscreen, but none work
under AvoiderGame:
public function getFinalLevel():Number { return gameLevel.levelNum; } public function getFinalScore():Number { return gameScore.currentValue; }under Doc class:
public function onAvatarDeath( avatarEvent:AvatarEvent ):void { var finalScore:Number = playScreen.getFinalScore(); var finalClockTime:Number = playScreen.getFinalClockTime(); var finalLevel:Number = playScreen.getFinalLevel();GameOverScreen class:
public function setFinalLevel( levelNumber:Number ):void { finalLevel.text = levelNumber.toString(); }where did i miss something? headache…….
if you can help, plz
thanks
Hey Nik,
I can’t see anything that you’ve missed :S
Let’s figure out where it’s going wrong. Put a trace() in your GameOverScreen like this:
public function getFinalLevel():Number { trace( gameLevel.levelNum ); return gameLevel.levelNum; }Let me know what pops up in the Output panel.
Oh, are you getting any errors, by the way?
i get error when my avatar die
TypeError: Error #1009: Cannot access a property or method of a null object reference. at AvoiderGame/getFinalLevel() at DocumentClass/onAvatarDeath() at flash.events::EventDispatcher/dispatchEventFunction() at flash.events::EventDispatcher/dispatchEvent() at AvoiderGame/onTick() at flash.utils::Timer/_timerDispatch() at flash.utils::Timer/tick()How to send you my project files? i think easier if you write fix “//note” on the code
thanks
Hey Nik,
Kinda busy at the moment, don’t have time to go rooting through other people’s code — sorry!
Check out my debugging guide to find out which line is triggering that error. If you paste the code here (and point out which line it is) I can probably help.
Hey there! Those tutorial are great, thanks for the help you give to us Michael..
I have a problem too with a features : increase speed of the enemy every level more. I saw the hint you gave to FlashTrainee, but i’m stuck.. can’t figure out what to do.
Can you give me another good hint for that?
Sorry for the “inconvenience”.. hope to see your answer!
Solved!
Thank you anyway!
Good to hear, Rick! How’d you fix it?
I thought it would be interesting to have different avatars and enemies in each level, but ran into a problem. I just followed the directions exactly the same as with the background, except changing Avatar instead of PlayScreen, making an AvatarContainer, etc. I added it in the code the same way, but an error keeps popping up “1120: Access of undefined property avatarContainer.” I don’t understand how it’s undefined because I named the instance of the movie clip “avatarContainer.” I added all of the new movie clips in the AssetHolder as well. Any idea why this could be?
Hi Brittney, nice idea
Hmm. In which class’s AS file are you trying to access
avatarContainer?Hmm a little question.
I’ve used this code in a way to load a maze that the player has to walk through like
public function setLevel():void { if ( currentLevelData.levelImage == "one" ) { levelContainer.addChild( new LevelOne() );Now this all works fine and I figured out that I can make the maze move while keeping the character I made in the center by translating the levelContainer.x and .y values when a key is pressed.
My problem is this, I want to add Items and a finish to each map. I have them as movieclips in my library but how do I add them to the levelContainer in a way that I can detect collisions on them?
If I add the EndButton movieclip with
it does show up correctly and it moves with the level when I walk around but there is no way to check for collision. It just sees both as the same levelContainer instance.
I also tried
Then I still can’t reach levelContainer.end.x
I hope this description is a bit clear but does anyone have any hints how to get this to work?
sigh seriously! I spend 2 days trying to fix this and 5mins after I typed all that stuff above I get it to work -_-
Hehe, that often happens to me
How’d you fix it?
Made a global var end:EndButton;
and then initiated that with levelContainer.addChild(end = new EndButton());
for some reason I can now reach it with a simple end.x /.y and test collision on it.
I’m just wondering if this aproach (my java teacher always told me global variables are evil
) will bite me in the ass when I start adding multiple instances of the same object as is not the case with a single exit to a level.
By class do you mean .as file? (sorry, very very new at this…) It’s all in avoidergame.as. Here are the sections that are creating errors:
currentLevelData=new LevelData(1); if (currentLevelData.avatarImage=="kong") { avatarContainer.addChild( new DonkeyKong() ); } else if ( currentLevelData.avatarImage == "pac" ) { avatarContainer.addChild( new PacMan() ); }and
public function setAvatarImage():void { if (currentLevelData.avatarImage=="kong") { avatarContainer.addChild( new DonkeyKong() ); } else if ( currentLevelData.backgroundImage == "pac" ) { avatarContainer.addChild( new PacMan() ); } }@Twan: Depends what you mean by global var. You mean a public var?
For adding multiple instances of an object it’d probably be best to use an array, like we do with the enemies.
@Brittney: Whoops, I meant to write “In which class’s AS file…”. Sorry — typo corrected.
Well, I can’t see anything wrong with your code, which usually means there’s a silly typo somewhere that you’ll kick yourself when you notice
Try putting
trace( "avatarContainer:", avatarContainer );inside yoursetAvatarImage()function; that’ll help narrow down the problem.I tried to change the speed of the enemies when the levels progress. I have gone through the 12 tutorials, but I’m not sure how exactly to do it.
I don’t want you to tell me how with the exact things, but would you recommend doing this by using a global var (I don’t think so), using this:
public function Enemy(startX:Number,startY:Number, enemySpeed:Number) { //function stuff here }Or what?
And if it’s the variable enemySpeed, how would I change it in the LevelData class and still reference it in AvatarGame?
While typing this I’m thinking a possible option would be creating a function in the LevelData class that sets the enemy’s speed variable in the AvatarGame class (using 2 variables). And then do what I said in code above.
Thanks for whatever help you can give.
Hey Graham,
What do you mean by a “global var”?
Sounds like your idea of using a function in the LevelData class would work. Why not try it out, and post another comment saying how it worked out?
Hi Michael,
What I mean by a global variable (and I think Graham as well) is a variable that you declare at the top of a class making it reachable in whatever code you have below. As far as I know it’s common practise in programming languages like java or c that you do not try to use this option but instead temporarily declaring local variables within a function.
By using global variables you violate referential transparancy and it makes it harder to analyze the code afterwards.
http://en.wikipedia.org/wiki/Global_variable
Hope this helps
greets!
Gotcha. I thought that’s what you meant, but it’s confusing because in AS2 you could set _global variables that were accessible anywhere in the code, not just in the same class.
I think having your end button as a public var makes sense, as it belongs to the class itself, rather than being defined by (and restricted to) any one function. Would you agree?
Well right now my code looks like this in my “AvoiderGame.as”
public function setLevel():void { if ( currentLevelData.levelImage == "een" ) { levelContainer.addChild(levelEen = new LevelEen() ); levelContainer.addChild(eind = new eindKnop()); eind.x = currentLevelData.finishX; eind.y = currentLevelData.finishY; avatar.x = currentLevelData.avatarX; avatar.y = currentLevelData.avatarY;While my GameCode.as looks like:
public function LevelData(levelNumber:Number) { levelNum = levelNumber; if (levelNumber == 1) { levelImage = "een"; finishX = -300; finishY = -200; avatarX = 200; avatarY = 500;}
I don’t know, it works but it seems kind of messy. Especially when I will add enemies and other stuff to the maze.
What I would like is to able to place enemies etc in each level using the UI and being able to reach them in the code. Haven’t got time to try it today but I’ll see if that works.
//levelContainer.addChild(new Enemy(80,80)); // zo wil ik ze toevoegen maar hoe test ik dan op collision? anders moet ik ze allemaal een naam geven en dat slaat nergens op
Oops forgot that last line of code. That was another idea but I couldn’t test collision detection on them then. Tomorrow I’ll meet with my prof so I might have some nifty solutions then
Well I looked at what I was doing, and I ended up finding a way to do it by looking at the already made “currentLevelData.enemySpawnRate”
To simplify a little, I did make the variables at the class level. If you want to see more of the code, let me know.
AvoiderGame.as (onTick function)
LevelData.as
Enemy.as
@Twan: Have you seen this tut? How to Use the Flash IDE as a Level Editor
@Graham: Nice! That is exactly what I would have done! Great job figuring it out.
i know almost nothing about code, i have manged/understood up to here because i am having a problem. In my game when i reach level 2 (250) points the spawn rate goes crazy and my point jump from 250-600 in a seccond (at 10 points per enemy entering) My code for my LevelData class is…
package { public class LevelData { public var backgroundImage:String; public var pointsToReachNextLevel:Number; public var enemySpawnRate:Number; public var levelNum:Number;}
}
and the letters are they because i have 6 different backgrounds 1 for each letter (ABCDEF). They code of my on tick function is…
public function onTick( timerEvent:TimerEvent ):void { if ( Math.random() < currentLevelData.enemySpawnRate ) { var randomX:Number = Math.random() * 400; var newEnemy:Enemy = new Enemy( randomX, -44 ); army.push( newEnemy ); addChild( newEnemy ); gameScore.addToValue( 10 ); } avatar.x = mouseX; avatar.y = mouseY;Take note i did not use the keybord controls (i stuck with the mouse ones)
the code for my setBackgroundImage function is....
public function setBackgroundImage():void { if ( currentLevelData.backgroundImage == "A" ) { backgroundContainer.addChild( new A_Background() ); } else if ( currentLevelData.backgroundImage == "B" ) { backgroundContainer.addChild( new B_Background() ); } else if ( currentLevelData.backgroundImage == "C" ) { backgroundContainer.addChild( new C_Background() ); } else if ( currentLevelData.backgroundImage == "D" ) { backgroundContainer.addChild( new D_Background() ); } else if ( currentLevelData.backgroundImage == "E" ) { backgroundContainer.addChild( new E_Background() ); } else if ( currentLevelData.backgroundImage == "F" ) { backgroundContainer.addChild( new F_Background() ); } }never mind i fixed it (my spawn rate was way too high you can see from the code i posteed in my last post it went from .03 to .3 and on.
Sorry for the delay on this reply, piemaker16. Ahh, I see what you mean. I make the same mistake when writing the tut originally
← Previous Comments
{ 1 trackback }