AS3 Avoider Game Tutorial, Part 10: Multiple Levels

by Michael James Williams on March 10, 2009 · 114 comments

in Avoider Game Base,Tutorial

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:

screenshot

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.

screenshot

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:

screenshot

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:

screenshot

The level’s background is picked at random when you start playing:

screenshot

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.

screenshot

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:

?View Code ACTIONSCRIPT3
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):

screenshot

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:

screenshot

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:

screenshot

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:

?View Code ACTIONSCRIPT3
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:

?View Code ACTIONSCRIPT3
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:

?View Code ACTIONSCRIPT3
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:

?View Code ACTIONSCRIPT3
27
public var currentLevelData:LevelData;

In the constructor function, instantiate this object like so:

?View Code ACTIONSCRIPT3
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:

?View Code ACTIONSCRIPT3
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:

?View Code ACTIONSCRIPT3
currentLevelData = new LevelData( 1 );

to a 2:

?View Code ACTIONSCRIPT3
currentLevelData = new LevelData( 2 );

Save it and run it again:

screenshot

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:

?View Code ACTIONSCRIPT3
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():

?View Code ACTIONSCRIPT3
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:

?View Code ACTIONSCRIPT3
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:

?View Code ACTIONSCRIPT3
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:

?View Code ACTIONSCRIPT3
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):

?View Code ACTIONSCRIPT3
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):

?View Code ACTIONSCRIPT3
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:

?View Code ACTIONSCRIPT3
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:

?View Code ACTIONSCRIPT3
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:

?View Code ACTIONSCRIPT3
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:

?View Code ACTIONSCRIPT3
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:

?View Code ACTIONSCRIPT3
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:

?View Code ACTIONSCRIPT3
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.

{ 113 comments… read them below or add one }

Michael Williams September 26, 2009 at 7:34 pm

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 StandardFunctions in your /classes/ directory, and it contains a static function called getRotationToPoint(), you can just write:

import StandardFunctions;

…and then you can use it like this: StandardFunctions.getRotationToPoint()! :D

FlashN00b September 27, 2009 at 10:11 am

great hint! Thanks :)

FlashTrainee October 6, 2009 at 5:39 pm

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;

    public function LevelData(levelNumber:Number)
    {   
        super(x, y);
        levelNum = levelNumber;

        if (levelNumber == 1)
        {
            backgroundImage = "blue";
            pointsToReachNextLevel = 10;
            enemySpawnRate = 0.10;
            speedIncrease = ySpeed + 1;
        }
        else if (levelNumber == 2)
        {
            backgroundImage = "green";
            pointsToReachNextLevel = 50;
            enemySpawnRate = 0.15;
            speedIncrease = ySpeed + 2;
        }
        else if (levelNumber == 3)
        {
            backgroundImage = "blue";
            pointsToReachNextLevel = 150;
            enemySpawnRate = 0.25;
            speedIncrease = ySpeed + 3;
        }
        else if (levelNumber == 4)
        {
            backgroundImage = "green";
            pointsToReachNextLevel = 999;
            enemySpawnRate = 0.35;
            speedIncrease = ySpeed + 4;
        }

    }
}

}

Can you give me an hint on how to proceed?

Thank you again very much!

Michael Williams October 7, 2009 at 5:38 pm

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:Number inside LevelData, much as you have. Then, in each if statement, 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

enemy.x = enemy.x + xSpeed;

…you would need something like:

enemy.x = enemy.x + (xSpeed * enemySpeed);

The tricky part here is, how do you pass enemySpeed to the Enemy?

I’ll just give a hint here — you can do it the same way you pass startX and startY to the enemy when you create it.

Hope that helps :)

DudexD January 17, 2010 at 11:46 am

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…

Michael Williams January 17, 2010 at 3:43 pm

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 BackgroundContainer on the play screen does not have an instance name of backgroundContainer.

Hope that helps :)

DudexD January 17, 2010 at 5:08 pm

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.

DudexD January 17, 2010 at 6:03 pm

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.

Michael Williams January 17, 2010 at 8:02 pm

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?

DudexD January 17, 2010 at 8:27 pm

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

DudexD January 17, 2010 at 8:37 pm

HOLY! i did it! it worked! like, all by myself…. well almost :P

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?

Michael Williams January 17, 2010 at 8:41 pm

Congrats :D

Nice code :)

You can use <pre> and </pre> to make simple code boxes, by the way. I’ve edited your comment to do this.

DudexD January 17, 2010 at 8:45 pm

Thank you :D

Well i better head on to the next tut.

Nik February 11, 2010 at 10:15 am

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;
        }

    public function getFinalClockTime():Number
    {
        return gameClock.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 = new GameOverScreen();
    gameOverScreen.addEventListener( NavigationEvent.RESTART, onRequestRestart );
    gameOverScreen.x = 0;
    gameOverScreen.y = 0;
    gameOverScreen.setFinalScore( finalScore );
    gameOverScreen.setFinalClockTime( finalClockTime );
    gameOverScreen.setFinalLevel( finalLevel );
    addChild( gameOverScreen );

    playScreen = null;
}

GameOverScreen class:

public function setFinalLevel( levelNumber:Number ):void
        {
            finalLevel.text = levelNumber.toString();
        }

where did i miss something? headache…….
if you can help, plz
thanks

Michael Williams February 13, 2010 at 2:12 am

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?

Nik February 22, 2010 at 2:58 am

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

Michael Williams February 22, 2010 at 9:30 pm

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.

Rick February 27, 2010 at 10:43 am

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!

Rick March 1, 2010 at 1:31 am

Solved! :D Thank you anyway!

Michael Williams March 20, 2010 at 10:50 am

Good to hear, Rick! How’d you fix it?

Brittney April 21, 2010 at 11:52 pm

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?

Michael Williams April 23, 2010 at 1:28 pm

Hi Brittney, nice idea :)

Hmm. In which class’s AS file are you trying to access avatarContainer?

Twan April 23, 2010 at 2:16 pm

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() );

        } else if ( currentLevelData.levelImage == "two" ) {
            levelContainer.addChild( new LevelTwo() );
        }
    }

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

levelContainer.addChild(new EndButton());

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

var end = new EndButton();
levelContainer.addChild(end);

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?

Twan April 23, 2010 at 2:24 pm

sigh seriously! I spend 2 days trying to fix this and 5mins after I typed all that stuff above I get it to work -_-

Michael Williams April 23, 2010 at 2:26 pm

Hehe, that often happens to me :P

How’d you fix it?

Twan April 23, 2010 at 2:43 pm

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.

Brittney April 23, 2010 at 7:59 pm

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() );
    }
}

Michael Williams April 25, 2010 at 5:31 pm

@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 your setAvatarImage() function; that’ll help narrow down the problem.

Graham (Tsolron) April 27, 2010 at 7:01 am

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.

Michael Williams April 27, 2010 at 1:10 pm

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?

Twan April 27, 2010 at 1:43 pm

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!

Michael Williams April 27, 2010 at 1:46 pm

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?

Twan April 27, 2010 at 1:55 pm

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;

        } else if ( currentLevelData.levelImage == "twee" ) {
            levelContainer.addChild( new LevelTwee() );
            levelContainer.addChild(eind = new eindKnop());
            eind.x = currentLevelData.finishX;
            eind.y = currentLevelData.finishY;
            avatar.x = currentLevelData.avatarX;
            avatar.y = currentLevelData.avatarY;

    } else if ( currentLevelData.levelImage == "drie" ) {
        levelContainer.addChild( new LevelDrie() );
        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;

        } else if (levelNumber == 2) {
            levelImage = "twee";
            finishX = 330;
            finishY = -100;
            avatarX = 200;
            avatarY = 500;

    } else if (levelNumber == 3) {
        levelImage = "drie";
        finishX = 3650;
        finishY = -190;
        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

Twan April 27, 2010 at 1:58 pm

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 ;)

Graham (Tsolron) April 29, 2010 at 3:22 am

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)

setEnemySpeed = currentLevelData.setEnemySpeed
var newEnemy:Enemy = new Enemy( randomX,-20,setEnemySpeed );

LevelData.as

setEnemySpeed = ( 0.9 + ( levelNumber * 0.9 ) );

Enemy.as

public function Enemy( startX:Number , startY:Number , setEnemySpeed )
.....
enemySpeed = setEnemySpeed;
.....
x += ( xSpeed * enemySpeed );
y += ( ySpeed * enemySpeed );

Michael Williams May 7, 2010 at 7:50 pm

@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.

piemaker16 August 1, 2010 at 4:05 pm

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;

    public function LevelData( levelNumber:Number )
    {
        levelNum = levelNumber;

    if ( levelNumber == 1 )
    {
        backgroundImage = "A";
        pointsToReachNextLevel = 250;
        enemySpawnRate = 0.03;
    }
    else if ( levelNumber == 2 )
    {
        backgroundImage = "B";
        pointsToReachNextLevel = 400;
        enemySpawnRate = 0.5;
    }
    else if ( levelNumber == 3 )
    {
        backgroundImage = "C";
        pointsToReachNextLevel = 600;
        enemySpawnRate = 0.7;
    }
    else if ( levelNumber == 4 )
    {
        backgroundImage = "D";
        pointsToReachNextLevel = 800;
        enemySpawnRate = 0.1;
    }
    else if ( levelNumber == 5 )
    {
        backgroundImage = "E";
        pointsToReachNextLevel = 1000;
        enemySpawnRate = 1.3;
    }
    else if ( levelNumber == 6 )
    {
        backgroundImage = "F";
        pointsToReachNextLevel = 999999;
        enemySpawnRate = 1.5;
    }
}

}

}
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;

        var avatarHasBeenHit:Boolean = false;
        for each ( var enemy:Enemy in army ) 
        {
            enemy.moveABit();
            if ( PixelPerfectCollisionDetection.isColliding( avatar, enemy, this, true ) )
            {
                gameTimer.stop();
                avatarHasBeenHit = true;
            }
        }
        if ( avatarHasBeenHit )
        {
            bgmSoundChannel.stop();
            dispatchEvent( new AvatarEvent( AvatarEvent.DEAD ) );
        }

    if ( gameScore.currentValue &gt;= currentLevelData.pointsToReachNextLevel )
    {
        currentLevelData = new LevelData( currentLevelData.levelNum + 1 );
        setBackgroundImage();
    }
}&lt;/pre&gt;

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() );
            }
        }

piemaker16 August 2, 2010 at 1:22 pm

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.

Michael Williams August 21, 2010 at 12:24 am

Sorry for the delay on this reply, piemaker16. Ahh, I see what you mean. I make the same mistake when writing the tut originally ;)

pepeu October 3, 2010 at 4:07 pm

Hello again! Still a great tutorial but there is one little thing… You wrote that we need to add the BackgroundContainer to the AssetHolder movie clip. But we already did that with all the objects earlier on, and there is no need for it since the PlayScreen that is in AssetHolder now contains the BackgroundContainer.

Michael Williams October 5, 2010 at 1:23 am

Hey Pepeu! Ooh, good point, well spotted :) You’re totally right.

as3coder November 2, 2010 at 5:22 pm

Hi there. I’ve followed the tutorial up to part 10. However, i did not want to change background every level, but rather the image of Enemy unit with every passing stage (like you supposed in the challenge). But I cant seem to wrap my head around it, I’ve done it similar to how you changed Backgrounds… but i keep getting
Error #1136. Incorrect number of arguments .Expected 2

Did i go about this completely wrong??

Mark Timmins December 9, 2010 at 7:41 pm

Hi Michael,

I’m taking a slightly different approach to structuring my levels. I’m extending avoiderGame in separate class files, ‘Level1′, ‘Level2′ etc. In the Document class I have a function called ‘nextLevel’ – the idea is that once the current level is over, a button on the Level Complete screen dispatches an event that calls this function and then takes the player to the next level. I’m having difficulty calling the classes though, and I want to do so without a lengthy ‘If’ statement. Here’s an example of what i’m trying to do:

public function nextLevel(navigationEvent:NavigationEvent):void
{
playScreen = new Level+"levelNumber"() //level number is a variable in the document class
...
}

As you can see i'm trying to append the level number onto the word 'Level' and then call the relevant class. But it's not working. Can you point me in the right direction please?

Cheers,
Mark

Hege Baraldsnes December 12, 2010 at 7:38 pm

This tutorial is BRILLIANT, I just want to thank you for sharing your knowledge.

I am a user interface designer (not programmer), but the game industry is using Flash and Scaleform more and more even for bigger mmo’s and I’ve been looking for a fun way to extend my AS skills and learn about OOP, and this is great stuff. (I never understood the concept of objects and classes, but I’m starting to get my head around it now, thanks to you).

Cheers!

Adam April 23, 2011 at 9:32 pm

Ok, so I was attempting to write some code on increasing the Enemy’s speed after reading FlashTrainee’s comment, and your response. I took into account the things you said, and what I came up wont work for me. Maybe you could give me some insight. I am just learning AS3, so I am really trying to grasp some of these things. I did as you said in the LevelData.as (public var enemySpeed:Number;) and no problems there. But then here is what I did with the Enemy.as:

package 
{
    import flash.display.MovieClip;
    public class Enemy extends MovieClip 
    {
        public var xSpeed:Number;
        public var ySpeed:Number;

    public function Enemy( startX:Number, startY:Number, enemySpeed:Number  ) 
    {
        x = startX;
        y = startY;

    xSpeed = 0;
    ySpeed = 3;
}

public function moveABit():void 
{
    x = x + xSpeed;
    y = y + ySpeed;

    enemy.x = enemy.x + (xSpeed * enemySpeed);
}

}

}
I thought I had to call out the enemySpeed in the Enemy fucntion like:

public function Enemy( startX:Number, startY:Number, enemySpeed:Number  ) 

and then in AvoiderGame.as I put:

var newEnemy:Enemy = new Enemy( randomX, -15, 3 );

since that is where it calls the Enemy function. But I get these errors:

Enemy.as, Line 23  1120: Access of undefined property enemy.
Enemy.as, Line 23   1120: Access of undefined property enemy.
Enemy.as, Line 23   1120: Access of undefined property enemySpeed.

I guess I am a little confused. I can’t quite figure out how to properly call enemy and enemySpeed. Any tips or other hints?
Thank you for your time
-Adam

Dawn Hanson May 12, 2011 at 10:53 pm

This comment area hasn’t been visited in a while so I am hoping that maybe someone still replies to this? I would like to know an easy to make the avatar “shoot” lasers and make the hit object test the bullet to avatar and still run the same outcomes that this tutorial already had in play. Any ideas? I am assuming it would be a lot like the stopwatch to clock with the new instance inside the existing avatar – but how would you tweak the coding to make it respond it the new hit test object and not crack the code I have already created using this tutorial. Any help is appreciated.

Mark Timmins May 17, 2011 at 12:24 am

@ Adam – in your enemy.as file you have enemySpeed in the constructor function, but then you are trying to use that variable in the moveABit function – but remember that functions operate in isolation; just because you pass a variable into a constructor doesn’t mean the rest of the class can use it. There is an extra step before this can happen. Look at how xSpeed and ySpeed are being passed into the moveABit function. Essentially, you need to create a public variable (enemySpd for instance) and then in the constructor say enemySpd = enemySpeed. That means you now have a variable the entire class can use. Then you simply use enemySpd in the moveABit function. Hopefully this makes sense.

@ Dawn – I think this is what you are after: http://gamedev.michaeljameswilliams.com/2009/05/20/avoider-game-shmup/

There’s a bunch of avoider game add ons that do different things. That one turns it into a shmup. You can access this page via the ‘Avoider Game Extras’ on the right hand column.

Mark Timmins May 17, 2011 at 12:28 am

@ Adam – in addition, since you are inside the class that is ‘driving’ enemy – you don’t need to use the word ‘enemy’ as in ‘enemy.x = …’ you simply use ‘x = x + ….’

Dawn Hanson June 9, 2011 at 9:33 pm

I have a question to see if anyone else has gotten this issue:

After we did part 10 of the tutorial our game lags going between level 1 and level 2 – I have rechecked the code multiple times and cannot figure out what happened. Have you ever heard of this happening before and if you have, how did you fix it? Any help would be greatly appreciated!

Losty McLost July 23, 2011 at 7:56 pm

Earlier in this tutorial, when I change “1″ to “2″ the background doesn’t change from my blue background to my red one. I’ve been trying to fix it, nothing works. Also, for some reason it says that my BackgroundContainer is an instance of BlueBackground. Is that correct? I tried to use the “Swap” button to change it, but it wouldn’t let me. I’m lost!

Leave a Comment

Writing code? Write <pre> at the start and </pre> at the end to keep it looking neat.

Anti-Spam Protection by WP-SpamFree

{ 1 trackback }

Previous post:

Next post: