Accessibility
 
Home / Developer Center / Macromedia Flash Developer Center /

Macromedia Flash Article

Make an asteroid move

Lesson objective: By the time you're done with this lesson, you'll be able to take movie clips you've created and animate them in simple, yet random ways. You'll also be able to make these movie clips seem to wrap within the screen size you assign them.

You're going to alter your createAsteroid() function now and add a lot more code. Enter the code for this lesson or simply download lesson_2.fla and follow along.

First of all, you want more than one asteroid to be generated. You're going to accomplish this with a simple for-next loop to create an array of object references to the asteroid movie clips:

	// at will be an array of object references to the Asteroids on the screen.
	at = new Array();

Here you initialize at as an array. In my experience, I've found that working with arrays in Macromedia Flash is much faster and easier than looping through movie clips with a similar naming convention. You're setting up an array of object references to the asteroid movie clips for the following reasons:

· Keep track of how many asteroids are on the stage throughout the game play
· Refer to individual asteroids without knowing what their instance name is
· Assign similar, randomized actions to individual asteroids without having to retype those actions for every asteroid that's created:


	// diffLevel is initialized here.
	// it's used for determining the difficulty at each level.
	diffLevel = 1;

	// a variable to keep track of the depths of 
	// our movie clips is initialized here:
	_root.depth=0;

	// let's create a set amount of Asteroids depending on the level.
	for (i=0; i<_root.diffLevel+1; i++) {
		at[i] = new Object ();
		at[i] = createAsteroid(1, mf(mr()*400), mf(mr()*400));
	}

Let's first look at the for-next loop. Making a for-next loop is all dependent on a variable, starting at a certain value and meeting a certain condition to continue looping. You use for-next loops because you want to repeat some actions but you want to limit the number of times it repeats.

Your for-next loop starts with the variable i, which acts as a counter. You initialize i by setting it equal to 0. As long as i is less than the diffLevel (plus 1 past that value), this loop will continue and all code within the brackets of this loop will be executed that many times. Where the code reads i++, you're giving Macromedia Flash directions as to how you're going to make the value of i change. In this case, you're incrementing i by 1 (adding one to its value).

For every time that Macromedia Flash goes through this loop, it's initializing a new Object as an element, or member, of the at array. An element of an array is like an empty box. If you can picture that, picture the object in that empty box as a command to turn that box into compartments, although you aren't saying what kind of compartments or how big they are. Basically, you're telling the element of the array to be prepared to accept a certain kind of information to hold onto.

In each element of the array, you're calling on your createAsteroid() function. So when I call on at[0], (element #0 in the at array) it's going to refer to an asteroid movie clip. This is how object references work, especially when working with arrays.

Your createAsteroid() function generates the physical asteroid but you have a lot more functionality to build.

If you notice that the first line of the createAsteroid() function has been altered, you see that you now have some information inside the parentheses:

  createAsteroid = function (factor, x, y) { ... }

These items in the parentheses are called parameters, or arguments. They're simply variables passed into the function that will be used inside of the function. The variables x and y will pass an x and y coordinate into the function, telling it where it should create the asteroid.

The x and y variables are used in this code:

	// put the Asteroid at the determined x and y on the stage.
	rock._x = x;
	if (rock._x>20 || rock._x<380) {
		rock._y = mf(mr()*400);
	} else {
		rock._y = y;
	}

You set the asteroid (remember you refer to it in the code here as rock) to an x-position equal to x. If that x-position ends up being greater than "20," or if it ends up being smaller than "380," the y-position is assigned randomly. Otherwise, the y-position will be set to the y passed into the function.

The factor variable will be used to determine if this asteroid has been hit once, twice, or three times. Depending on how many times an asteroid (or a fragment of the parent asteroid) has been hit, the factor is used in determining its fragment's size. It's used in this code, still within the createAsteroid() function:

  // we want a little variety in the appearance of the Asteroids,
  // so we set the x- and y-scale random within a certain range,
  // dependent on the factor.
  rock._xscale = (mf(mr()*50)+50)/factor;
  rock._yscale = (mf(mr()*50)+50)/factor;

That, in a nutshell, is a "rock solid" (pun intended) example of parameters.

You still need to build an engine to handle the movement of every asteroid on the stage. To help with that, assign some random values relative to your specific asteroid: xv (x-velocity), yv (y-velocity), and r (rotation amount):

  // We need to set a velocity value for the Asteroid's
  // x- and y- movements.
  rock.xv = mf(mr()*6)-3;
  rock.yv = mf(mr()*6)-3;
  
  // We also need to set a rate for rotation of the Asteroid,
  // so it looks like it's drifting along in space.
  rock.r = mf(mr()*360)-180;

You're going to use these variables in your movement engine.

If you've entered all the code, you can publish the movie now and see a notable difference. You now have two hexagons (your first asteroids) moving adrift on the stage. If you watch closely enough, you'll see that when the asteroid moves below a certain point, it reappears atop the stage—as if the window wrapped.

In fact that's exactly what's happening onEnterFrame. Take a look over the four different if-statements:

	if (at[i]._x<=_root.xmin+10) {
	at[i]._x += _root.xmax-20;
	}
	if (at[i]._x>=_root.xmax-10) {
		at[i]._x -= _root.xmax-20;
	}
	if (at[i]._y<=_root.ymin+10) {
		at[i]._y += _root.ymax-20;
	}
	if (at[i]._y>=_root.ymax-10) {
		at[i]._y -= _root.ymax-20;
	}

Although your movie is sized at 600 x 400, you don't want to take up this whole space with your game. You need 200 pixels worth of screen real estate for the console, which will hold the scoreboard, your lives, and any system messages and buttons. This means you're going to make your playable space a nice 400 x 400 square.

I like having a 10-pixel border for asteroids, lasers, and the spaceship so that once they cross, they have to wrap around. That way, it doesn't look too weird during the course of play when the screen wraps. Set these variables up in the Game() function:


	// define the bounds of the movie.
	_root.xmax = 390;
	_root.xmin = 10;
	_root.ymax = 390;
	_root.ymin = 10;

Once you set up your boundaries, focus on actually moving each asteroid. Remember that at is an array where each element of the array is an object reference to a unique "Asteroid" movie clip:

	// this code will be executed everytime the frame refreshes.
	this.onEnterFrame = function() {
		for (i in at) {
			at[i]._x += at[i].xv*at[i].level;
			at[i]._y += at[i].yv*at[i].level;
			at[i]._rotation += at[i].r/60;
		}
	};

This updates the x- and y- position on every frame refresh by adding each x-, y- and rotaion-value to themselves. This works well for making objects move in a straight line. The asteroid's location always grows in the same way, which makes it move in a straight line. The only problem is that at a certain point the movie clip's location will grow beyond the viewable area of your movie clip. That's no good; you can't shoot something you can't see. That's why you put in a checking system to move the asteroid to the opposite horizontal and/or vertical border when it passes the minimum or maximum:

 		if (at[i]._x<=_root.xmin+10) {
			at[i]._x += _root.xmax-20;
		}
		if (at[i]._x>=_root.xmax-10) {
			at[i]._x -= _root.xmax-20;
		}
		if (at[i]._y<=_root.ymin+10) {
			at[i]._y += _root.ymax-20;
		}
		if (at[i]._y>=_root.ymax-10) {
			at[i]._y -= _root.ymax-20;
		}

  

 
Previous Contents Next