Lunar Lander

As for the calculator movie, we’ll only use one frame in our lander movie.

Make a new movie and use the properties inspector to resize it to 550 x 400 pixels. Use the properties inspector also to set the background colour to black and check that the frame rate is set to 12 frames per second. Make sure you can see the whole of the frame by choosing ‘show frame’ from the pull-down list in the top right hand corner of the frame window.

As we are concentrating on learning Flash scripting skills, we won’t bother initially with using a realistic photo of the lander. We’ll just use a red square instead – you can change the fill of the square later into a bitmap photo of a lander if you like. Before we draw our shapes it's a good idea to turn on the 'snap-to-grid' option (View>Snapping>Snap to Grid). Turning on this option helps to make neat symmetrical shapes, at the expense of no longer being able to have precise control over the shapes. Select the rectangle tool in the toolbox, and set the fill colour to red. Think also about the stroke colour - we don't need Flash to draw four strokes (lines) around our rectangle so let's keep it simple by setting the stroke colour to 'none' .

As it stands, our red square cannot be given a name and therefore cannot be referred to by code. Click the red square to select it then convert it to a symbol by pressing F8. Give the name ‘lander’ and choose the ‘movie clip’ for the behaviour – this is the usual choice for any symbol that is not intended to act as a button. Also note that the 'registration point' of the movie clip is in the top left corner. Choose the bottom left corner instead so that we can more easily detect when the bottom of the lander hits the top of the pad. The registration point is the point to which the _x and _y coordinates refer. In other words, when you get the position of an object on the stage you are getting the position of that object's registration point, which may have been placed in the top left corner or in the centre or in other places. You will notice that the symbol you have just created has been added to the library (press Ctrl-L if you can't see the library).

The red square on the form is now an instance of the lander symbol – use the properties inspector to change the instance name of the red square to ‘lander1’. This does not imply that there will be other lander instances, but it is a good reminder that an instance is not the same as a symbol and that we could make other instances of the same symbol if we wanted to.

We’ll build our program step by step, testing as we go, so let’s first see whether we can make our lander fall as if pulled down by the moon’s gravity. We did this in VB by using the timer control to run a block of code at frequent intervals (once every 100 milliseconds or 10 times every second). We had variables vxand vy which represented the horizontal velocity (to the right) and the and vertical (downward) velocity, respectively. 10 times every second, the downward velocity vy was increased by a constant amount, just as would be the case for a real lander. Since speed is just the distance moved in each unit of time, we had code that moved the lander horizontally and vertically by distances equal to vx and vy (we were assuming therefore that vx and vy were the velocities in ‘pixels per decisecond’).

Since Flash has nothing like VB's timer control we will use a different technique to animate the lander. You need to understand that:

  • our movie is only one frame long
  • when the movie gets to the end it starts again at the beginning - it loops
  • each time the movie starts again we enter the first and only frame in our movie

Flash has an onEnterFrame event handler and code that is attached to this will run repeatedly at the frame rate of the movie since our movie keeps starting again from the beginning after playing the one and only frame. The frame rate of our movie is set to 12 frames per second and code that runs this often to move the lander will give smooth-looking animation, as we wish.

Make a new layer for this code then, as you did in the calculator movie, and name the new layer ‘Actions’. Right-click the empty keyframe in frame 1 of the Actions layer, open the Actions panel and paste a copy of the code below:

vy = 0;
_root.onEnterFrame = function() {
            vy = vy + 0.1;
            _root.lander1._y = _root.lander1._y+vy;
};

Study the above code carefully – it first creates a variable called vy and gives it the value zero - this variable will be used to store the vertical velocity of the lander. Please note that Flash is (unfortunately) case sensitive so vy is not the same as Vy, for example, and lander1 is not the same as Lander1. You can avoid case problems if you use lower case for everything. Next, the code defines the function ‘_root.onEnterFrame’. In the second line above, Flash needs to know where the frames are located, since a Flash movie can contain many ‘movie clips’ each with a different timeline. In this case we are referring to the main timeline, which is said to be at the ‘root level’ of the movie.

In the third line, we add a constant number to vy, so that the downward velocity will increase steadily as the movie runs.

In the fourth line, we add the value of vy to the ‘_y’ property of the lander (not forgetting to indicate that the lander is in the main or ‘root’ movie). As you have guessed, the ‘_y’ property is the equivalent of the ‘top’ property in VB – it gives the vertical position of a movie clip, measured from the top of the frame.

Test your movie (Ctrl-Enter) and if all goes well you will see the lander accelerate downwards and disappear off the frame. Well done! Note that it is also possible to test your movie by pressing Ctrl-F12 - this takes a little longer but shows you exactly what your movie will look like inside your browser.

Now let’s add a button to control the thruster rocket that pushes the lander upwards. Choose the line tool in the toolbox then use it to make a sharp upward-pointing triangle in the lower left corner of the frame(don't draw black lines for you won't see them against the black background). Now choose the paint bucket tool, make sure the fill colour is set to blue, and fill the triangle with blue colour. Delete the 3 strokes around the triangle and convert the triangle into a symbol with the name ‘thruster’ and with button behaviour (we usually use 'movie clip' behaviour' but 'button behaviour' allows us to use the simple 'on release' code below).

Make sure the blue triangle (now an unnamed instance of the ‘thruster’ symbol) is selected, then open the Actions panel and paste or type the following code:

on (release) {
            vy = vy - 2;
}

It should be obvious what this code does – when the mouse button is pressed down and then released over this button, 2 will be subtracted from the downwards velocity (vy) of the lander. Test your movie and make sure you can now control the vertical velocity of the lander.

Let’s add the other two buttons to control the horizontal thrusters. Make sure the movie’s library panel is visible (choose Window > Library otherwise) then drag a second instance of the thruster symbol from the library onto the frame, placing it to the left of the existing thruster button. Choose the free transform tool in the toolbox and use it to rotate the new instance until it points to the left. Add a third instance and make it point to the right. Add the code for the two new buttons – the one on the left should subtract 2 from vx each time it is clicked and the one on the right should add 2.

Note that we've been a bit naughty by attaching code to each of the three buttons because the idea of the Actions layer was that we would put all the code there so that it would all be in one place and therefore easy to find. But the code that makes the buttons work is shorter and easier to understand if we attach it directly to each button, so that's what we did.

The 2 new buttons won’t affect the lander’s motion until we modify the ‘onEnterFrame’ function definition to take into account the vx variable. The code below also contains a line which creates and initializes the variable vx.

vy = 0;
vx = 0;
_root.onEnterFrame = function() {
            vy = vy + 0.1;
            _root.lander1._y = _root.lander1._y + vy;
            _root.lander1._x = _root.lander1._x + vx;
};

Test your movie and check that you can control the horizontal as well as the vertical velocity of the lander.

Now you can add a landing pad – just a green rectangle, to the lower right corner of the frame. Remove the 4 strokes around it then convert it to a movie clip symbol called ‘pad’, at the same time setting the registration point to be at the top left corner of the pad (for reasons that will be explained later). Name the instance of the pad symbol now on the frame ‘pad1’ so that we can refer to it in the code. Your frame should now look something like this (but not yet including the text box in the top right corner):

Now we need to modify the ‘onEnterFrame’ function definition to test whether the lander has fallen far enough to be touching the pad. We have set the registration point of the lander to be on its bottom edge and the registration point of the pad to be on its top edge. The ‘_y’ property gives the position of each registration point so it will be easy to compare the positions of the two registration points to see whether the lander is above the pad or not.

If you previously did the Visual Basic version of the lander then you know that in VB it was more difficult to get the position of the bottom of the lander since in VB there is no property called ‘bottom’ that represents the location of the bottom edge of an object. We had to add ‘top’ and ‘height’ to get the position of the bottom of the lander.

Let's add a line or two to our code so that the lander only moves around if it is above the level of the pad. Change the onEnterFrame code like this:

vy = 0;
vx = 0;
_root.onEnterFrame = function() {
            if (_root.lander1._y <_root.pad1._y) {
                        vy = vy + 0.1;
                        _root.lander1._y = _root.lander1._y + vy;
                        _root.lander1._x = _root.lander1._x + vx;
            }
};

The new line checks whether the registration point of the lander is less far down the frame than the registration point of the pad, and if so then the lander is moved as previously. If the test gives a false result then the following lines are not executed so the lander stops moving. Try it - test your movie...

Now let's make a message appear when you land. In our VB lander program a message box appeared at the moment of the landing and announced ‘You have landed’. There is no messagebox statement in Flash but a similar effect can be achieved by changing the contents of a dynamic text box which is initially empty.

Use the text tool to make a text box in the top right corner. Set the text type to dynamic text, the ‘show border around text’ option to off, and the text colour to bright yellow. Set also the var property of the text box to ‘message’. Now the following modification to the code will make the message appear when you land:

vy = 0;
vx = 0;
_root.onEnterFrame = function() {
            if (_root.lander1._y <_root.pad1._y) {
                        vy = vy + 0.1;
                        _root.lander1._y = _root.lander1._y + vy;
                        _root.lander1._x = _root.lander1._x + vx;
            } else {
                        message = "You have landed"
            }
};

Test your movie – you should see the message appear whenever the lander reaches the level of the pad, WHETHER OR NOT THE LANDER IS ACTUALLY 'ON' THE PAD.

Note that there are other ways of making a message appear, e.g. a previously-hidden text box could be made visible (Flash movie clips have a ‘_visible’ property which corresponds to the ‘visible’ property of VB controls), or the alpha value (opacity) of the text box could have been set to 0 initially (using the properties inspector) and then (using code) to 100% when the lander landed. (A transparent text box is not the same as an invisible text box, for the transparent box is still enabled – it can still be clicked).

Clearly the program is not yet finished – I’ll leave you the rather difficult challenge of adding the code to check whether the lander actually lands correctly, entirely within the width of the pad. If you need help with that, call me. As in VB, you will need to do this with a ‘nested’ if structure, and you will probably need to use the ‘_width’ property of the lander and the pad. Note that you should use && in place of AND in Flash - I warned you that Flash is not intuitive! The result could look something like this (refresh the page by pressing F5 to restart the movie)...

GOOD LUCK TO YOU!