Newsletter Subscribers: Are you looking for Creating a Visual Basic 6 Add-In?
After last week’s somewhat one dimensional flight of fantasy into Visual Basic Space Travel, it is time to add another dimension to game programming. This week, we will be adding horizontal movement and sound capabilites to our blockbuster game. So without further ado, let’s get going.
The horizontal movement of our spaceship will be implemented in a similar way to the vertical movement. Each time the timer event is raised, we will use the API to check whether the left of right arrows have been pressed, and if they have, apply the neccessary acceleration to the horizontal speed.
To trap the left and right key presses, we will need these constants:
Private Const VK_LEFT = &H25 Private Const VK_RIGHT = &H27
We will also need these variables to store the speed and position of the craft. Paste these also into the declarations section:
' The x coordinate of the craft Private LandX As Double ' Horizontal speed of the craft Private hSpeed As Double
Since our pilot is going to want to know how fast he is moving, draw a text box called txthspeed and an accompanying label. The default values for the horizontal speed should be set in the form’s load event:
hSpeed = 0 LandX = 150 ' Update text boxes txthspeed.Text = Format(hSpeed, "0.0")
That’s the easiest bits out of the way now, but the rest is not that hard really. The first modifications to be made to the timer will be to change the default X coordinate of 150 to the variable value, LandX. Therefore, go through each BitBlt API call (there are four in total), changing the second parameter from 150 to LandX. For example, the first call should read:
BitBlt picEarth.hdc, LandX, LandY, _ piclander.ScaleWidth, piclander.ScaleHeight, _ piclander.hdc, 0, 0, vbSrcInvert
Now that we have the basic framework for controling the horizontal movement, it is almost a matter of copy and pasting the code for monitoring the down arrow key to extend it to watch the left and right arrow keys:
' Apply left and right movement If GetAsyncKeyState(VK_RIGHT) <> 0 Then If Fuel > 0 Then dothrust = True ' Apply thrust: 15 is the acceleration produced hSpeed = hSpeed - ((timediff / 1000) * 15) Fuel = Fuel - ((timediff / 1000) * 150) ' Check that fuel does not go below 0 If Fuel < 0 Then Fuel = 0 Else Beep End If End If If GetAsyncKeyState(VK_LEFT) <> 0 Then If Fuel > 0 Then dothrust = True ' Apply thrust: 15 is the acceleration produced hSpeed = hSpeed + ((timediff / 1000) * 15) Fuel = Fuel - ((timediff / 1000) * 150) ' Check that fuel does not go below 0 If Fuel < 0 Then Fuel = 0 Else Beep End If End If
LandX = LandX + hSpeed
And there you have it! Just think, you have double the number of dimensions in your game with just a few easy steps! Before we move on, we mustn’t forget to tell the user how fast they are going. Add this with the other statements that update the text box:
txthspeed.Text = Format(hSpeed, "0.0")
And now for some sound!
Since VB has no functions to play WAV files, we must again look to the API to satify our needs. We will be using the sndPlaySound API. Here are the declarations:
Private Declare Function sndPlaySound _ Lib "winmm.dll" Alias "sndPlaySoundA" _ (ByVal lpszSoundName As String, _ ByVal uFlags As Long) As Long Private Const SND_ASYNC = &H1
As you can see, this function takes two parameters. The first is the name of the sound file to play, and the second can be used to specify certain options for the playing of the sound. We will be using the SND_ASYNC flag, which allows us to call the function, and it will return straight away, letting us get on while the sound is playing. This is know as playing “asynchronously”, as opposed to “synchronously”, which plays the entire sound before returning.
Since we are going to be calling the sound file when any of the thrusters are applied, either left, right, or up, and we don’t want to repeat all the code, we will be using a variable to specify whether the sound should be played. At the end of the timer event, we should check to see if the sound is currently playing, and if it is not, play it.
At the begginging of the timer event, we need two new variables:
Dim dothrust As Boolean Static lastplayed As Long
dothrust will be set to true if one of the arrows is pressed, thus telling the program to play sound. lastplayed stores the value from GetTickCount when the sound was last played. This will be used to check whether the sound is currently playing.
The first change is to go through and add
dothrust = True
everywhere the thrust can be applied. I recommend adding it after this line:
If Fuel < 0 Then Fuel = 0 ' Add: dothrust = True
Then at the end of the timer function, add this code to play the sound:
If dothrust = True Then ' if one of the thrusters has been pressed... If timenow - lastplayed > 805 Then ' and it is more than 805ms since the sound last played ' ( the length of the sound is 805ms ) ... ' then play the sound again! sndPlaySound "thrust.wav", SND_ASYNC lastplayed = timenow End If End If
The thrust sound that I used was about 805ms long, hence the 805 in the code. If you decide to use a different one, you may want to change that value accordingly. Also, the file shoud be in the same directory as the project, unless you specify the full path.
Just one more feature this week to make our game fiendishly difficult!
To add another level of difficulty to our game, we are going to make a landing area, which the pilot must land on, otherwise they will drown in the gooey bogs of the planet Zogg, where this game happens to take place. And we don't want that to happen to our poor defenceless intergalactic space travelers do we?
The platform will be draw with the land, so that is where the major modifications will occur. The platform will appear at a random place each time, so the Randomize Timer call should be moved to just after the if statement. Then we need to add a a little code to draw the platform. The code will finally look like this:
If curtime = 0 Then Randomize Timer
' Draw the earth picEarth.Line (0, picEarth.ScaleHeight _ - 30)-(picEarth.ScaleWidth, picEarth.ScaleHeight), _ vbWhite, BF ' Draw landing area randnum = CLng(Rnd * (picEarth.ScaleWidth - _ (picEarth.ScaleWidth / 5))) picEarth.Line (randnum, picEarth.ScaleHeight _ - 30)-(randnum + (picEarth.ScaleWidth / 5), _ picEarth.ScaleHeight - 28), vbRed, BF safeleft = randnum saferight = randnum + (picEarth.ScaleWidth / 5) ' Draw stars..etc
You have probably also spotted the safeleft and saferight variables. These should be both declared in the General Declarations section as Long:
'The left and right points of the landing area Private safeleft As Long Private saferight As Long
Now that we have these two variables, we must also check that the craft has landed within the allowed area. This is done by modifying the line that checks that the craft is not moving too fast:
' Previously: If vSpeed > -2 Then ' Change to: If vSpeed > -2 And hSpeed > -2 And LandX > safeleft _ And (LandX + piclander.ScaleWidth) < saferight Then
The now checks that you are not moving to fast in the horizontal and vertical dimensions, and also checks that you are within the allowed bounds of the platform.
You can download a demo to accompany this article. The game is now quite tricky, and it should keep you amused for many more hours. If you have any questions or comments about the article, you can post feedback in the form below, or on the Q and A forum.
Have fun playing!