In the previous lesson you built a 'lunar flyer' but it
could not be landed because there was no moon to land on (though the moon's
gravity WAS present). Now you will learn how to add the lunar surface and a
landing pad, and how to write code to detect landings, whether good or bad.
Add the lunar
surface by making a label at the bottom of your form, stretching across the full width of
the form, like this (except that your form is much bigger, and it's black!). You
will need to set the label's autosize property to false before the
label can stretch across the form. Also set the label's backcolor
property to a light yellow (everyone knows the moon is made of cheese),
the text property to nothing and the name property to lblMoon.
You can now add the landing pad, another label that
you should place towards the right side of the moon. Call it lblPad, make it just a little wider
than the lander, and make sure its top surface is in line with the lunar
surface, as shown below (this time I will show the form with BackColor = black,
as you should have).

Try
running the program, and you will find that the lander falls straight through
the lunar surface! This should not really come as a surprise, for we have
written no code to detect the actual landing. It's easy for us to see
when the lander has hit the ground, but how can we put this into code so that
the stupid computer can detect what is so obvious to us clever humans? The
lander has landed when the bottom of the picturebox reaches (or goes
lower than) the top of the lunar surface.
We
will use an IF structure to check whether the lander has landed, and if it has
we will show a messagebox message. Change the code inside the tmr1_Tick
subroutine as follows:
If picLander.bottom >= lblMoon.top Then
tmr1.enabled = false
MsgBox ("You have landed")
End
End If
picLander.left = picLander.left + vx
picLander.top = picLander.top + vy
vy = vy + 3
Note that a line has been included to disable the timer as soon
as the landing has been detected, otherwise the messagebox will reappear
constantly. Try running the program.
Our
code can now detect a landing but cannot detect whether the landing occurred in
the right place. This will be rather complex code for we have to check both the
left edge of the picturebox and the right edge. What is the condition for a good
landing?
Perhaps
you can see that the condition for the left edge to be OK is
picLander.left >= lblPad.left
Note the inequality 'greater than or equal to' in the above
line.
The condition for the right edge is similar:
picLander.Right <= lblPad.Right
so the condition for BOTH edges to be right is
(picLander.left >= lblPad.left) AND (picLander.Right <= lblPad.Right)
Note that conditions can be connected with words like AND or OR
just as in English. I've used parentheses to make the above line more legible.
So
now we are ready to modify the timer code. We only need to check the horizontal
landing position if we have already detected a landing, so the new IF structure
should be 'nested' inside the existing one. Note how the indentation of lines
inside each IF structure helps to make the code more legible.
If
picLander.Bottom >= lblMoon.Top Then
tmr1.Enabled = False
If (picLander.Left >= lblPad.Left)
And (picLander.Right <= lblPad.Right)
Then
MsgBox("The
Eagle has landed")
End
Else
MsgBox("You
crashed!")
End
End If
End If
picLander.Left = picLander.Left + vx
picLander.Top = picLander.Top + vy
vy = vy + 0.2
Your lander program should be working fine now - this program is
almost fun! There's just one annoying problem: it doesn't take long to land, and
once you've landed (especially if you crashed) you would probably like the
option of trying again. Our program doesn't give that option... yet... but we
can add it without too much trouble. We will, for the first time, use a
messagebox to ask a question. Look at the following line:
response = MsgBox("You
crashed! Play again?", MsgBoxStyle.YesNo)
The last part of the line, MsgBoxStyle.YesNo, tells the program to display
a 'yes' button and a 'no' button in the message box, instead of the usual 'OK'
button. The user's response has to be stored somewhere, so the line begins with
the name of a variable called response into which the response will be stored.
Since we have just introduced a new variable called response we will have to
declare it. Put this code just under the declarations of vx and vy:
A 'string' variable contains a string of characters, in
other words a block of text. After displaying the message box and putting the response
into a variable called response, the
next step is to add lines to test the response with an IF structure and act accordingly:
If response = MsgBoxResult.Yes Then
Reset
Else
End
End If
This is fine, except that VB does not understand the command
'Reset', so it will do nothing when it reaches that line. Actually it does
do something - it generates a 'reset' event, but since there is no subroutine to
handle this event, nothing happens. We will add a 'reset' subroutine later - for
the time being, just modify the timer code like this:
If picLander.bottom >= lblMoon.top Then
tmr1.Enabled = False
If (picLander.left >= lblPad.left) And (picLander.Right <= lblPad.Right) Then
MsgBox ("The Eagle has landed")
End
Else
response = MsgBox("You crashed! Play again?", MsgBoxStyle.YesNo)
If response = MsgBoxResult.Yes Then
Reset
Else
End
End If
End If
End If
picLander.left = picLander.left + vx
picLander.top = picLander.top + vy
vy = vy + 0.2
Now we will create a subroutine to handle the 'reset' event, so
that the program knows what to do when it reaches that line. What exactly do we
need to do in order to reset our program? We need to
Just above the bottom class wrapper line, End Class, add this line
Press the Enter key when you have finished typing the above line
and and note that
VB automatically gives you the bottom wrapper for this subroutine.
Now
complete the Reset subroutine:
Private Sub Reset()
picLander.left = 30
picLander.top = 30
vx = 0
vy = 0
tmr1.enabled = true
End Sub
Remember that VB uses a very small distance unit called a
pixel,
so 30 pixels is a small distance.
Here is the complete set of code for the lander project:

If you have followed all my instructions
perfectly then
a) you are a genius
b) you should have a lander program that correctly resets if you crash the
lander and then choose to try again
As icing on the cake, it would be nice to hear sound effects when the lander
makes a good landing or a bad one. Look ahead to the Sound project to find
out how to add sound to a VB program, then add appropriate sounds to the
Lander program. You can download some useful sounds by clicking the links
below - make sure you place the downloaded files in the same folder as your
lander project. If left-clicking does not give you a file-save dialog then
try right-clicking. To work with VB the sounds must be in the WAV
format, as all the following sounds are.