9 Lunar Lander
You can't learn programming with Mr. Ward without making a lunar lander! We will make a project in which an image (a real photo of the Apollo 11 lander that first carried humans to the moon) 'flies' realistically, being pulled down by the moon's gravity and pushed up and sideways by rocket thrusters (you can see the finished simulation at the bottom of this page). Ultimately we will extend the program until we can carefully land the lander on a special 'landing pad'. Please do all the steps and don't just jump to the end - you will learn much more if you don't skip anything!
In this part we will import the images we need and write very simple scripts to handle the horizontal motion of the lander. We will deal with the horizontal motion and the vertical motion separately since they are quite different - the vertical motion is affected by gravity and the horizontal motion is not.
Copy this image into your personal folder then import into the stage background (NOT a sprite costume). To import into the stage background click the 'stage' icon in the bottom right corner of Scratch then click 'backgrounds ' a the top of the scripts area then click 'Import'. You can delete the white background since we will not be using it.
This picture is a bit less wide than the stage so you will probably need to open it in the image editor and click the 'Grow' button (not the zoom scale) to make it cover the stage.
Also import the following image (the Apollo 11 lander) as a sprite (copy it to your folder then hit the 'Choose new sprite from file' button and import it. Change the name of the new sprite to 'lander'. Delete the cat sprite (right-click it and choose 'delete').
Now we are ready to make the sprite move. We will use a variable called 'vx' to represent the velocity (speed) in the 'x' (horizontal) direction and later we will add a 'vy' variable for the vertical velocity. For the moment, just create a variable called 'vx'.
As in the previous projects, we will use a 'forever loop' which continuously makes the lander do little 'jumps'. Each jump goes a number of steps equal to the speed variable, so the bigger the variable the bigger the jump. In this case only the x value (the horizontal position of the sprite will be affected, so the lander will only move right (if vx is positive), or left (if vx is negative).
Check out these scripts:
When we press the right arrow key the value of vx is increased by 0.4. When we press the left arrow key the value of vx is decreased by 0.4 (or increased by -0.4, of you prefer). Why 0.4? Because I've tried changing this number and 0.4 seems to work well on my home computer. I'm a bit worried though that the loop might run at different speeds on different computers - I wouldn't really want the lander to accelerate faster just because it's being used on a faster computer. I don't know Scratch well enough yet to know whether this is really a problem. Try changing the numbers if you like.
When the green flag is clicked then a forever loop is launched which simply changes (over and over again) the x value (horizontal position) of the lander sprite by adding vx to it.
If you add the above scripts to the lander sprite (not to the stage, of course) then you should be able to make the lander accelerate left and right as if being pushed by blasts from the side thrusters.
In the next step we will add the vertical motion. That's a bit more complicated because the moon's gravity is present, continually changing the vertical velocity vy. Let's choose to make the upwards direction the positive y direction. Therefore the upward-pushing rocket thruster should make vy bigger (more positive) but the gravity should subtract from vy. The good news about the vertical motion is that we don't need to think about the lander being pushed down by a thruster - no downward-pushing thruster is needed because the downward force of gravity is always present.
So make a new variable 'vy' and then change the scripts of the lander sprite as shown:
The only differences are that
- we are now changing the vertical position 'y' of the lander as well as the horizontal position 'x'
- the 'forever loop' keeps subtracting 0.01 from vy every time a loop is done
- we have a script that increases vy by 1 every time the up arrow key is pressed
- note that we do NOT have a script for the down arrow key, as previously explained
With the new scripts in place, you should be able to fly your lander around in a realistic way, complete with gravity!
Now we will add blocks to detect a landing with the lunar surface.
Three of these five scripts are completely unchanged but we have a new script to handle the 'reset' message and the green flag script on the left has a few extra lines.
Look at the green flag script. The important lines that change x, y and vy are still there but now they are inside an 'if ... else ... ' structure so that x, y and vy are only changed IF the condition in the 'if' block is met. That condition is that the vertical (y) position of the lander must be greater (more positive) than -170. Remember that on the bottom edge of the stage y is equal to -180, so a value of -170 is a little higher than the bottom edge of the stage.
If the 'if' condition is not met (because the lander has gone too close to the bottom of the stage) then the 'change x' and 'change y' blocks no longer run. Instead the 'else' part activates and a message is displayed for 3 seconds, after which a 'reset' message is broadcast to the other scripts.
The 'reset' message is handled by a separate script that simply puts the lander back in the top left corner of the stage and sets the horizontal and vertical velocities back to zero. I put these blocks in a separate script to keep the main (green flag) script as simple and clear as possible. It would also have been possible to put those three lines directly in the green flag script rather than using a broadcast message.
If you carefully set up the scripts as shown then everything should work fine... except for one little detail. You will probably notice that the lander hits the bottom of the stage before the message appears. We want the message to appear when the feet of the lander reach y=-170 but the program assumes so far that the position of lander is the position of the centre of the lander. So we need to tell the program to use the position of the lander's foot, not its centre. To do that, make sure the lander sprite is selected in the bottom right corner of Scratch, then click the 'costumes' tab, then the 'Edit' button. Click the 'Set costume center' button then click at the level of the bottom of the feet of the lander, halfway between the left edge of the lander and its right edge. Once you have made that change the lander should stop a short distance above the bottom edge of the stage.
In this part we will add the landing pad and then check whether the lander has landed correctly on the central part of the pad. Click on 'Paint New Sprite' to create a new sprite in the Paint Editor. Make a red and yellow rectangular shape like that in the animation below. Make sure that the red part of the pad is just slightly wider than the lander itself. By controlling how much wider the red part is than the lander you can control the difficulty of landing successfully. The height of the pad shape doesn't matter much. Place the 'costume center' at the centre of the top surface of the pad.
Let's take a look at the scripts I used (they are all attached to the lander sprite - the other sprite and the stage have no scripts).
Look at the green flag script. First it broadcasts a 'reset' message to the corresponding script which sets the position and both velocities of the lander to their starting values. Then a 'forever' loop continually checks whether the bottom of the lander is higher than the top of the pad (remember how we placed the 'rotation centres' carefully?). If this is the case then the horizontal and vertical positions are adjusted as in part 3 and 0.01 is deducted from the upwards velocity vy, as in part 3.
If the lander is NOT above the pad then we know the lander has landed, but did it land in the right place? This is checked by the second 'If... then... else' structure, which is the most important new addition to this project. For a good landing the lander sprite must be touching the red part of the landing pad but must not be touching the yellow part (ask yourself why the yellow part needs to be so wide).
My image above also shows a 'PostIt' note (comment) that I put in to help people understand my program. It's very important to 'document' your programs in this way because in a professional context it is very likely that someone else will want to modify your program one day and that person will need help to understand how your program works. You can add comments anywhere in the scripts area by right-clicking and choosing 'add comment'.
The simulation below uses a sprite with text on it to launch the game. Text works well enough in Scratch except that you can only have one block of text on each sprite or background and there is no option of centering text (I cheated a bit). Add such a sprite-with-text to your own project.
The main improvement in the simulation below is that it uses a fuel variable. This is initially set to 25 but every time you use a rocket thruster you use up one unit of fuel. When there is no fuel left the thrusters no longer work, just as would be the case in a real lander. Try to add such a fuel variable to your own lander and improve this project in other original ways. If you think this lander simulation is too easy then reduce the fuel allowance. You could offer different levels of difficulty with different levels of fuel, or different gravity. And don't forget to add some sound effects, of course!