Вы находитесь на странице: 1из 18

How to write games using Basic4GL - Part 2

Right then!
This is the second part of the game programming tutorials series for Basic4GL. It's pretty much going
to carry on from where part 1 left off, so obviously I advise reading part 1 first. It all fits together!
This tutorial will introduce just one concept: "arrays".
It turns out that arrays, and how to use them effectively gives us enough material for an entire tutorial,
so I wont try to squeeze anything else in (it was hard enough to squeeze it down to its current length,
and it's still pretty long.).
Arrays although simple in concept are actually extremely powerful. They can be used to apply the same
lines of code to different data, which we will put to use to show that the same lines of code that move 1
alien can move 50 of them!

Back to the space alien game


The challenge is thus:
Take the simple space alien game from the previous tutorial and extend it to handle multiple space
aliens.
For completeness, we might as well make them shoot back too.
--->
So...
...How would we approach this?
Based on what we've learned so far, we might consider doing this:
• Take the existing code for 1 space alien.
• Copy-and-paste it.
• Change the variable names (alienx2, alieny2 etc)
This would give us a complete working set for a second space alien.
This would work fine. Infact there's nothing wrong with this approach, so long as you have a small
number of space aliens. But if we wanted say 50 aliens, we would have to do a lot of cutting and
pasting and the program would get very long very quickly.
Also if we later wanted to change the alien code (which we will later when we make them shoot back)
we would have to make the same change 50 times!
So we're going to take another approach, which (surprise, surprise) involves introducing our new
concept, called "arrays".

Arrays
An array is a special kind of variable. You remember that a variable is used to store a number or a
string, like in this (fairly meaningless) program:

||
dim count, temperature#dim model$count = 5temperature#
33.44model$
"Plastico 12B"
||

However, instead of just storing 1 number or string, an array can store many numbers or strings.
To illustrate, let's suppose we wanted to store three numbers.
We could simply use 3 different variables:

||
dim n1, n2, n3n1 = 4n2 = 3n3 = n1 + n2
||

But we could also store all three numbers in a single array variable, like this:

||
dim n(3)n(1) = 4n(2) = 3n(3) = n(1) + n(2)
||

This looks pretty similar to the first program. The biggest difference being that there are brackets
around the numbers.
The dim n(3) statement tells the computer that we want an array of 3 elements called n. This is the
array variable name, and follows the same rules as normal variables (for example, we know that the
array stores integers because there is no special symbol after the n. Had we called it n$ as in dim
n$(3), we would have been given an array of three text strings).
So is this better?
Admittedly it's slightly longer and doesn't do anything particularly better. But bear with me, because
there are things we will learn to do with arrays that we can't do with regular variables.
One situation is if we want to store a large number of variables, say 1000. Obviously it would take us a
long time to write out code to "dim" 1000 different variables.

dim n1, n2, n3, n4, n5, n6, n7, n8, n9, n10...!

But with an array we just do this:

dim n(1000)

And there are other advantages which we will see soon.

Using array variables


Each number (or text string) that is stored in an array is called an "array element". Each element
behaves like a regular variable. That is, we can read or write to it, use it in expressions, as function
parameters or whatever.
We tell the computer which element we want to access by putting the number in brackets after the array
variable name. So in the previous examples, n(2) accesses the seond element of the array.
Here's some more examples of using array elements.
||
dim name$(3), numbers(4)name$(1) = "Tom"name$(2) = "Dick"name$(3) = "Harry"numbers(1) =
3numbers(2) = numbers(1)numbers(3) = numbers(1) + numbers(2) * 2numbers(4) = sqrt (numbers (3))
||

As you can see, we are using them just like normal variables.

The Array Index


The number inside the brackets is called the "array index".
This is the number used to 'lookup' the variable in the array. You can think of this like a mailbox
number. It tells the postman where the letter is supposed to go.
So for an instruction like:

numbers(3) = 5

We're delivering the number 5 to mailbox number 3.


We could then look inside mailbox number 3 like this:

print numbers(3)

And we would find the number 5 which we just delivered there.


Of course if we used a different array index like 2:

print numbers(2)

We wouldn't find our number 5! We've looked in the wrong mailbox.


(We would infact find a number 0 there, because that is the default for integer variables if we haven't
changed them to anything else yet.)

Other ways to specify the array index


We put a 3 in the brackets to specify array index 3.
But what if we had used something like 1+1+1 instead?

||
dim numbers(4)numbers(1+1+1) = 5print numbers(3)
||

Would this compile?


Would it have the same effect?
The answer is: yes, it does exactly the same thing. Type it in an run it, and you'll see that it does indeed
print a 5 on the screen.
The reason this works is that the array index doesn't have to be just a single number. It will also accept
any expression that sums up to a single number.
So we could have used 2 + 1 or 7 - 4 or sqrt (9) all to access mailbox number 3.
The computer is quite happy to calculate the result of this sum and go to the appropriate "mailbox".
(Unlike the postal service who turn their nose up at any address that requires long division... Don't
ask...)
Using a variable for the array index
Here's another way to access the 3rd element (mailbox) of the numbers array:

||
dim numbers(4), ii = 3numbers(i) = 5print numbers(3)
||

This is actually a very powerful technique!


What we've done is declared a variable i, and then stored the number 3 in it.
Then we've used i as the array index!
Remember that we can use any expression we want to calculate the array index number, and that
includes other variables like i.
Again the computer calculates the expression, and sees that it comes out as 3. So off to index 3 it goes
and stores in the number 5.

Arrays and loops


Right! Now we can bring it all together and show exactly why arrays are very powerful for dealing
with large amounts of data (like space alien positions :).
The technique involves using a for..next loop, and combining it with the using-a-variable-for-the-array-
index we just saw above.
Now that sentence probably sounded like Mongolian Swahili to you, so we'll illustrate with another
example:
Let's say we have an array of 10 numbers, and we want to set all the elements to the number 7. (Think
of it like delivering a copy of 7 to all the mailboxes in the street).
One way would be to do this:
||
dim numbers(10)numbers(1) = 7numbers(2) = 7numbers(3) = 7numbers(4) = 7numbers(5) =
7numbers(6) = 7numbers(7) = 7numbers(8) = 7numbers(9) = 7numbers(10) = 7
||
That works fine.
Another way would be to do this:
||
dim numbers(10), ii = 1numbers(i) = 7i = 2numbers(i) = 7i = 3numbers(i) = 7i = 4numbers(i) = 7i =
5numbers(i) = 7i = 6numbers(i) = 7i = 7numbers(i) = 7i = 8numbers(i) = 7i = 9numbers(i) = 7i =
10numbers(i) = 7
||
This works fine too. But it's almost twice as long.
But! Here's the trick!
Notice that we are simply running the same instruction ten times:

numbers(i) = 7

Only we're putting an i = 1 infront of the first one then an i = 2 in front of the next one, then an i = 3,
and so on...
If you remember back to the for..next loop, you may realise that this is exactly the same as saying:

for i = 1 to 10 numbers (i) = 7next


(Or here's the full program:)
||
dim numbers(10), ifor i = 1 to 10 numbers(i) = 7next
||
Now this does everything we needed it to do, and it's quite a bit shorter than the first program.
And it has other advantages.
Say you wanted to store an 8 in each array element (mailbox), it would be very easy to change the
program to do this.
Or, if you decided you wanted to have 100 array elements (or 1000), it's still very easy to update the
program to do this.

Putting it together
That was quite a bit of theory, and not much about space aliens. It must be about time to put it to use on
something practical.
But before going back to the space alien game though, we're going to start with a simple bouncing ball
program.
This is because we want to demonstrate the inbetween steps for converting a one-object program into a
many-object program, and the space alien game has become rather large. We want something smaller
so we can show each little step without making the tutorial longer than it already is!

1 bouncing ball
Okay, so firstup we need a bouncing ball program with one ball.
Because we're still using text mode, we will simply draw a letter 'o' for the ball. The ball will simply
move diagonally around the screen. Whenever it reaches the edge of the screen it will bounce away.
As before, we need to decide what data the computer needs to store to remember where the ball is, and
keep it moving.
We need to store the ball's current position on the screen. So we will use ballx and bally as the current
column and row.
Now at any one time, the ball will be moving in a direction, so we need to store that too.
We will use two variables called ballxd and ballyd, and will store the horizontal (left and right) and
vertical (up and down) directions of the ball, which we will store as a number. Each time around the
main loop we will update the ball's position like this:

ballx = ballx + ballxdbally = bally + ballyd

So when ballx is 1, it will be the same as doing a ballx = ballx + 1 and the ball will move to the right.
And when ballx is -1, it will be doing the same as ballx = ballx + -1 (in other words ballx = ballx - 1)
and the ball will move to the left.
Likewise with ballyd. 1 will make the ball move down, and -1 will make it move up.
Here's the first version with 1 ball.
||
dim ballx, ballydim ballxd, ballydballx = rnd () % 38 + 1bally = rnd () % 23 + 1ballxd = 1: ballyd =
1TextMode (TEXT_BUFFERED)SetTextScroll (false)while true ballx = ballx + ballxd bally = bally +
ballyd if ballx <= 0 or ballx >= 39 then ballxd = -ballxd endif if bally <= 0 or bally >= 24 then ballyd =
-ballyd endif cls locate ballx, bally: print "o" DrawText () Sleep (75)wend
||
Most of this should look familiar from the space aliens game. We have declared our variables with dim.
Then we've stored some initial data in them, using the rnd () function and the remainder operator (%)
to generate numbers from 1-38 and 1-23 for the column and row screen position. This makes the ball
start from a random position.
In the main loop, we move the ball as we said we would.
The only tricky bit is the if..then instructions:

if ballx <= 0 or ballx >= 39 then

detects when the ball has reached the left hand side of the screen (column 0) or the right hand side
(column 39).
If so we reverse the left-right direction with:

ballxd = -ballxd

So if ballxd was 1 (ball moving right), it will be changed to -1 (ball moving left).
And if ballxd was -1 (ball moving left), it will be changed to 1 (ball moving right).
And the ball's up-down direction is handled in the same way.
The rest of the code simply draws the ball on the screen, and delays for 0.075 seconds, to regulate the
speed.

3 bouncing balls
So now we're going to change the program to handle 3 bouncing balls.
As we said before, we're going to do this in stages, so we're not going to jump to the final solution
straight away.
For now we're going to ignore arrays and simply use more variables.
So instead of ballx, we're going to have ballx1, ballx2 and ballx3. And likewise for bally, ballxd and
ballyd all the other variables.
And we're simply going to copy the code that we wrote to move and draw the first ball over to the
second and third.
The code for this one is a little bit repeditive and easy to make mistakes, so you might just want to cut
and paste it rather than type it all in.
||
dim ballx1, bally1dim ballx2, bally2dim ballx3, bally3dim ballxd1, ballyd1dim ballxd2, ballyd2dim
ballxd3, ballyd3ballx1

rnd () % 38 + 1bally1
rnd () % 22 + 1ballxd1

1: ballyd1
1ballx2 = rnd () % 38 + 1bally2 = rnd () % 22 + 1ballxd2 = 1: ballyd2 = 1ballx3 = rnd () % 38 +
1bally3 = rnd () % 22 + 1ballxd3 = 1: ballyd3 = 1TextMode (TEXT_BUFFERED)while true ballx1
ballx1 + ballxd1 bally1
bally1 + ballyd1 if ballx1 <= 0 or ballx1 >= 39 then ballxd1

-ballxd1 endif if bally1 <


0 or bally1 >= 23 then ballyd1

-ballyd1 endif ballx2


ballx2 + ballxd2 bally2 = bally2 + ballyd2 if ballx2 <= 0 or ballx2 >= 39 then ballxd2 = -ballxd2
endif if bally2 <= 0 or bally2 >= 23 then ballyd2 = -ballyd2 endif ballx3 = ballx3 + ballxd3 bally3
= bally3 + ballyd3 if ballx3 <= 0 or ballx3 >= 39 then ballxd3 = -ballxd3 endif if bally3 <= 0 or
bally3 >= 23 then ballyd3 = -ballyd3 endif cls locate ballx1, bally1: print "o" locate ballx2, bally2:
print "o" locate ballx3, bally3: print "o" DrawText () Sleep (75)wend
||
As before I've used bold red to highlight the new bits.
So the program is almost 3 times as long now, but as you can see when you run it, it does work fine.
There are 3 balls bouncing around the screen like they were told.
Okay, from now on, each version is going to do the same thing, just in slightly different ways each
time!
So please try not to be discouraged when you don't see any improvement. You will see in the end that it
was worth it, especially when we see how easy it is to change the final version to bounce 50 balls
around the screen.
So let's soldier on and replace these variables with arrays.
Still gradual steps remember!
||
dim ballx(3), bally(3)dim ballxd(3), ballyd(3)ballx(1)

rnd () % 38 + 1bally(1)
rnd () % 22 + 1ballxd(1)

1: ballyd(1)
1ballx(2)

rnd () % 38 + 1bally(2)
rnd () % 22 + 1ballxd(2)

1: ballyd(2)
1ballx(3)
rnd () % 38 + 1bally(3)
rnd () % 22 + 1ballxd(3)

1: ballyd(3)
1TextMode (TEXT_BUFFERED)while true ballx(1)

ballx(1) + ballxd(1) bally(1)


bally(1) + ballyd(1) if ballx(1) <= 0 or ballx(1) >= 39 then ballxd(1)

-ballxd(1) endif if bally(1) <


0 or bally(1) >= 23 then ballyd(1)

-ballyd(1) endif ballx(2)


ballx(2) + ballxd(2) bally(2)

bally(2) + ballyd(2) if ballx(2) <


0 or ballx(2) >= 39 then ballxd(2)

-ballxd(2) endif if bally(2) <


0 or bally(2) >= 23 then ballyd(2)

-ballyd(2) endif ballx(3)


ballx(3) + ballxd(3) bally(3)

bally(3) + ballyd(3) if ballx(3) <


0 or ballx(3) >= 39 then ballxd(3)

-ballxd(3) endif if bally(3) <


0 or bally(3) >= 23 then ballyd(3) = -ballyd(3) endif cls locate ballx(1), bally(1): print "o" locate
ballx(2), bally(2): print "o" locate ballx(3), bally(3): print "o" DrawText () Sleep (75)wend
||
So the program hasn't improved a great amount, but we are using arrays. And we still get 3 bouncing
balls when we run it.
This still isn't the best way to use arrays though.
In the next step we are going to replace code like:

ballx(1) = ballx(1) + ballxd(1)

With code like this:

i=1
ballx(i) = ballx(i) + ballxd(i)

Where i is a new variable that we are using for the "array index".
Here's the new code:
||
dim ballx(3), bally(3)dim ballxd(3), ballyd(3)dim ii = 1ballx(i)

rnd () % 38 + 1bally(i)
rnd () % 22 + 1ballxd(i)

1: ballyd(i)
1i = 2ballx(i)

rnd () % 38 + 1bally(i)
rnd () % 22 + 1ballxd(i)

1: ballyd(i)
1i = 3ballx(i)

rnd () % 38 + 1bally(i)
rnd () % 22 + 1ballxd(i)

1: ballyd(i)
1TextMode (TEXT_BUFFERED)while true i = 1 ballx(i)

ballx(i) + ballxd(i) bally(i)


bally(i) + ballyd(i) if ballx(i) <= 0 or ballx(i) >= 39 then ballxd(i)
-ballxd(i) endif if bally(i) <
0 or bally(i) >= 23 then ballyd(i)

-ballyd(i) endif i
2 ballx(i)

ballx(i) + ballxd(i) bally(i)


bally(i) + ballyd(i) if ballx(i) <= 0 or ballx(i) >= 39 then ballxd(i)

-ballxd(i) endif if bally(i) <


0 or bally(i) >= 23 then ballyd(i)

-ballyd(i) endif i
3 ballx(i)

ballx(i) + ballxd(i) bally(i)


bally(i) + ballyd(i) if ballx(i) <= 0 or ballx(i) >= 39 then ballxd(i)

-ballxd(i) endif if bally(i) <


0 or bally(i) >= 23 then ballyd(i)

-ballyd(i) endif cls i


1 locate ballx(i), bally(i): print "o" i = 2 locate ballx(i), bally(i): print "o" i = 3 locate ballx(i), bally(i):
print "o" DrawText () Sleep (75)wend
||
Now again the program still produces 3 bouncing balls. And it hasn't become any simpler or shorter.
Infact all these i = ... statements have made it longer still.
But there is one very important feature here that you may have noticed!
The positioning code is exactly the same for each ball.
The movement code is exactly the same for each ball.
The drawing code is exactly the same for each ball.
All that differs is the i = 1, i = 2, or i = 3 that is infront.
So we can use our for..next trick (from before) so that the same instructions can be used on all the
balls!
So instead of:
i = 1locate ballx(i), bally(i): print "o"i = 2locate ballx(i), bally(i): print "o"i = 3locate ballx(i), bally(i):
print "o"

we can write:

for i = 1 to 3 locate ballx(i), bally(i): print "o"next

So let's do it! Here's the new program:


||
dim ballx(3), bally(3)dim ballxd(3), ballyd(3)dim ifor i = 1 to 3 ballx(i) = rnd () % 38 + 1 bally(i) = rnd
() % 22 + 1 ballxd(i) = 1: ballyd(i) = 1nextTextMode (TEXT_BUFFERED)while true for i = 1 to 3
ballx(i) = ballx(i) + ballxd(i) bally(i) = bally(i) + ballyd(i) if ballx(i) <= 0 or ballx(i) >= 39 then
ballxd(i) = -ballxd(i) endif if bally(i) <= 0 or bally(i) >= 23 then ballyd(i) = -ballyd(i) endif next cls for
i = 1 to 3 locate ballx(i), bally(i): print "o" next DrawText () Sleep (75)wend
||
Now there's an improvement! It's only a little bit longer than the code to bounce one ball around the
screen!
But let's take this a little bit further.
We keep on writing for i = 1 to 3. This is obviously because there are 3 balls on the screen. But instead
of saying 3 everytime, let's use a constant instead!
Why would we do this? We'll see in a minute :-)
We will call the constant ballCount and give it the value 3 at the start of the program like this:

const ballCount = 3

Then everytime we want to refer to the number of balls (i.e 3) we will use ballCount instead.
So instead of saying for i =1 to 3, we are instead going to say for i = 1 to ballCount.
Let's see the changed program.
||
const ballCount = 3dim ballx(ballCount), bally(ballCount)dim ballxd(ballCount),
ballyd(ballCount)dim ifor i = 1 to ballCount ballx(i) = rnd () % 38 + 1 bally(i) = rnd () % 22 + 1
ballxd(i) = 1: ballyd(i) = 1nextTextMode (TEXT_BUFFERED)while true for i = 1 to ballCount
ballx(i) = ballx(i) + ballxd(i) bally(i) = bally(i) + ballyd(i) if ballx(i) <= 0 or ballx(i) >= 39 then
ballxd(i) = -ballxd(i) endif if bally(i) <= 0 or bally(i) >= 23 then ballyd(i) = -ballyd(i) endif next cls for
i = 1 to ballCount locate ballx(i), bally(i): print "o" next DrawText () Sleep (75)wend
||
Again, the program works exactly the same way as before. 3 bouncing balls.
So why is this better?
Well consider this.. How difficult would it be to change this program to have 50 balls bouncing around
the screen.
How many lines of code do you think we would have to change?
The answer - believe it or not - is just one line of code!
Try it! Change the top line from:

const ballCount = 3

to read:
const ballCount = 50

And re-run the program.


That's right! Changing just one line of the program can make it into a 50 ball program. And you can
just as easily change it to 1, 10, 100 or 1000 balls, or any other number for that matter (although when
the number gets really big the computer will start to slow down. If it gets too big the computer will say
it doesn't have enough memory to store all these balls and won't be able to run the program.)
So that is - in a nutshell - the power of using arrays that I've been harping on about all this time...

Back to the space aliens!


Now I promised that we were going to have multiple space aliens, and now we have the tools to do it.
So load up the space alien game from the first tutorial (or cut and paste it from the tutorial if
necessary).

More of 'em
We're going to use the same techniques from above to create multiple space aliens.
But first we have to think a little bit about how this will affect the game rules. Because the game rules
for the 1 alien version aren't quite suited for a multiple space alien version.
In the current version, whenever we shoot the alien it reappears on the left side of the screen. But now
we would really prefer them to dissapear and stay gone, so that the player can clear the screen of all
aliens and win the game (or move on to the next level etc).
So the computer also needs to remember which aliens are still on screen, and which aren't, so it knows
which ones to move around and draw.
We'll start by changing the variables declared to arrays. That is we will replace (at the top of the
program):

dim score, lives, turretx, alienx, alieny

With :

const alienCount = 10dim score, lives, turretxdim alienx (alienCount), alieny (alienCount),
alienOnScreen (alienCount)dim bulletx, bullety, bulletOnScreen, i

This will stop the program from working for now, but that doesn't matter (we still have some more
changes to make before it is ready).
Notice that we've used a constant for the number of aliens, instead of simply writing 10 everywhere.
This will make it easy to change the number of aliens later (e.g. if we want to make the game easier or
harder.)
We've added the alienOnScreen array to store whether or not each alien is still on the screen.
Next we have to change the code that puts the aliens in their starting position. Now that we have more
than one, we can't have them both start from the same position, so we will use random numbers to set
their starting position.
Replace the lines (near the top):

alienx = 0alieny = 12
With:

for i = 1 to alienCount alienx(i) = rnd () % 37 alieny(i) = rnd () % 22 + 1 alienOnScreen(i) = truenext

This should put the aliens in random start positions (rnd () % 37 makes a random number between 0
and 36, and rnd () % 22 + 1 makes a random number between 1 and 22). We obviously couldn't set
them all to column 0, row 12, as otherwise they would all be drawn over the top of each other, and it
would look like there is only one alien!
We still have a couple of changes to make before the program will compile and run though.
Next we will change the alien movement code.
Find the section of the program that reads:

alienx = alienx + 1 if alienx > 37 then alienx = 0 alieny = rnd () % 22 + 1 endif

And replace it with:

for i = 1 to alienCount if alienOnScreen (i) then alienx (i) = alienx (i) + 1 if alienx (i) > 37 then alienx
(i) = 0 alieny (i) = rnd () % 22 + 1 endif endif next

Notice that we've used our for..next loop to make sure the instructions get repeated multiple times -
once to move each alien. We've also used an if..then..endif statement to tell the computer to only run
the instructions between then and endif if the alien is on the screen. (There's no reason to move the
alien if it isn't.)
We're almost there. Next we're going to update the code that draws the alien on the screen.
Find this line in the program

locate alienx, alieny: print ">O<"

And replace it with this:

for i = 1 to alienCount if alienOnScreen (i) then locate alienx (i), alieny (i): print ">O<" endif next

Again we tell the computer to run the same lines of code once for each alien.
And again we tell the computer only to draw the alien if it's still on the screen.
We've made quite a few changes, and the program still won't run. It's normally a good idea to try and
keep the program working as we make the changes. This means that we can test each of the steps as we
go along, and keeps us from getting disheartened.
So what we're going to do now is completely remove the collision detection code so that we can test the
program! (Don't worry, we will add it back in again very soon.)
So find the section of the program that reads:

if bulletOnScreen and bullety = alieny and bulletx >= alienx and bulletx <= alienx + 2 then color (255,
255, 100) for i = 1 to 10 locate alienx, alieny: print "/" DrawText () Sleep (50) locate alienx, alieny:
print "\\\" DrawText () Sleep (50) next bulletOnScreen = false alienx = 0 alieny = rnd () % 22 + 1
score = score + 100 Sleep (1000) endif

And delete it!


Now run the program, and you should see a whole screenful of space aliens flying up above the turret.
If it doesn't work, then you will need to check over the program for mistakes.
To make it easier, here's the complete program at this point, with the changes in red as usual.
||
const alienCount = 10dim score, lives, turretxdim alienx (alienCount), alieny (alienCount),
alienOnScreen (alienCount)dim bulletx, bullety, bulletOnScreen, ilives = 3turretx = 19for i = 1 to
alienCount alienx(i) = rnd () % 37 alieny(i) = rnd () % 22 + 1 alienOnScreen(i) =
truenextbulletOnScreen = falseTextMode (TEXT_BUFFERED)while true if ScanKeyDown
(VK_LEFT) and turretx > 0 then turretx = turretx - 1 endif if ScanKeyDown (VK_RIGHT) and turretx
< 37 then turretx = turretx + 1 endif for i = 1 to alienCount if alienOnScreen (i) then alienx (i)

alienx (i) + 1 if alienx (i) > 37 then alienx (i)


0 alieny (i)

rnd () % 22 + 1 endif endif next if


bulletOnScreen then bullety
bullety - 1 if bullety < 1 then bulletOnScreen = false endif else if ScanKeyDown (VK_SPACE) then
bulletOnScreen = true bullety = 22 bulletx = turretx + 1 endif endif cls color (255, 255, 255) locate 0,
0: print "Score=" + score locate 30, 0: print "Lives=" + lives color (255, 50, 50) for i = 1 to
alienCount if alienOnScreen (i) then locate alienx (i), alieny (i): print ">O<" endif next color (150,
150, 150) locate turretx, 23: print "<!>" if bulletOnScreen then color (255, 255, 50) locate bulletx,
bullety: print "!" endif DrawText () Sleep (75)wend
||

Shooting the space aliens


So we can see that the game indeed runs, and that there are many aliens.
This looks a bit more exciting! But if you're like me, you'll be wanting get that collision code back in so
we can start blasting aliens! (It's a male thing...)
So we'll simplify what happens when the alien gets hit a little bit and just do the following:
1. Remove the alien from the screen.
2. Remove the bullet from the screen.
3. Increase the score by 100
Because there are 10 aliens, we need to tell the computer to check whether the bullet has hit each one
individually. So we will need another for..next loop, to check the bullet's position against all of the
aliens.
Here's the updated code:
||
const alienCount = 10dim score, lives, turretxdim alienx (alienCount), alieny (alienCount),
alienOnScreen (alienCount)dim bulletx, bullety, bulletOnScreen, ilives = 3turretx = 19for i = 1 to
alienCount alienx(i) = rnd () % 37 alieny(i) = rnd () % 22 + 1 alienOnScreen(i) =
truenextbulletOnScreen = falseTextMode (TEXT_BUFFERED)while true if ScanKeyDown (VK_LEFT)
and turretx > 0 then turretx = turretx - 1 endif if ScanKeyDown (VK_RIGHT) and turretx < 37 then
turretx = turretx + 1 endif for i = 1 to alienCount if alienOnScreen (i) then alienx (i) = alienx (i) + 1 if
alienx (i) > 37 then alienx (i) = 0 alieny (i) = rnd () % 22 + 1 endif endif next if bulletOnScreen then
bullety = bullety - 1 if bullety < 1 then bulletOnScreen = false endif else if ScanKeyDown (VK_SPACE)
then bulletOnScreen = true bullety = 22 bulletx = turretx + 1 endif endif cls color (255, 255, 255)
locate 0, 0: print "Score=" + score locate 30, 0: print "Lives=" + lives color (255, 50, 50) for i = 1 to
alienCount if alienOnScreen (i) then locate alienx (i), alieny (i): print ">O<" endif next color (150,
150, 150) locate turretx, 23: print "<!>" if bulletOnScreen then color (255, 255, 50) locate bulletx,
bullety: print "!" endif if bulletOnScreen then for i = 1 to alienCount if alienOnScreen (i) then if
bullety = alieny (i) and bulletx >= alienx (i) and bulletx <= alienx (i) + 2 then alienOnScreen (i) =
false bulletOnScreen = false score = score + 100 endif endif next endif DrawText () Sleep (75)wend
||
Now this is probably more if..thens and for..nexts than we've used in combination before, but we
should be ready to cope with it now :) It's the same as what we've seen before, just in a few more
layers.
First we tell the computer that if the bullet is not on the screen then don't worry about checking any of
the aliens:

if bulletOnScreen then

Next we tell it to repeat the instructions multiple times, once for each alien.

for i = 1 to alienCount

Then we say to only to check the alien if it's on the screen.

if alienOnScreen (i) then

And then we have the actual check to see if the alien and the bullet are at the same position on the
screen.

if bullety = alieny (i) and bulletx >= alienx (i) and bulletx <= alienx (i) + 2 then

And finally, if it finds an alien at the same position as the bullet, it runs the code to remove the alien
and the bullet from the screen and update the score.

alienOnScreen (i) = false


bulletOnScreen = false
score = score + 100

And that's about all there is too it.

Shooting back
There's still a few things missing from our game, and the most obvious is that the aliens don't shoot
back So let's make them.
As usual we first need to stop and think about how the aliens are going to shoot back, and how that can
be made into specific rules that we can enter into the computer.
The rules will be quite simple.
• The aliens will shoot randomly. Specifically we will give them a one in ten chance of shooting
each time they move.
• There will be up to 10 alien bullets on the screen at one time.
• The bullets will fall down the screen until they reach the bottom, then dissapear.
From this we can see that we will need arrays (because we will have multiple bullets).
We need to store the position of each bullet (we will use x and y array variables) on the screen.
The bullets won't always all be on the screen at once, so we also need to store which ones are on screen
and which aren't.
So we will probably store them something like this:

const bombCount = 10dim bombx (bombCount), bomby (bombCount), bombOnScreen (bombCount)

(I've called them "bombs" because they will fall down the screen, and because I can't be bothered
typing "alienBullet" each time!)
Next we need to make the aliens drop bombs randomly each time they move.
We've said they will have a 1 in 10 chance each time. We can make this work by making picking a
random number from 1 to 10 each time and then checking if it equals 1. If it does we drop the bomb.
In order to drop a bomb, we need to find one that isn't already on the screen. So we need to search
through all the bombs for the first one where bombOnScreen (bombCount) is false. When we find
one, we will place it on the screen where the alien is.
We need something like this (in the move alien loop):

if rnd () % 10 + 1 = 1 then for j = 1 to bombCount if not bombOnScreen (j) then bombOnScreen (j) =
true bombx (j) = alienx (i) + 1 bomby (j) = alieny (i) j = bombCount endif nextendif

We need the new variable j because we are already using i as the alien array index.
You may be wondering about the j = bombCount line at the end, after we have put a bomb on the
screen. This simply tells the computer that we don't want to repeat the instructions in the for..next
anymore (because we've already found our bomb and put it on the screen). Otherwise the computer
would keep on looping through the remaining bombs and putting them all underneath the current alien!
That's not what we want!
The next thing we need is some code to draw the bombs on the screen.
We will put this just after the code that draws the player bullet:

color (175, 175, 175)for i = 1 to bombCount if bombOnScreen (i) then locate bombx (i), bomby (i):
print "O" endifnext

Here's what the program currently looks like:


||
const alienCount = 10const bombCount = 10dim score, lives, turretxdim alienx (alienCount), alieny
(alienCount), alienOnScreen (alienCount)dim bulletx, bullety, bulletOnScreen, i, jdim bombx
(bombCount), bomby (bombCount), bombOnScreen (bombCount)lives = 3turretx = 19for i = 1 to
alienCount alienx(i) = rnd () % 37 alieny(i) = rnd () % 22 + 1 alienOnScreen(i) =
truenextbulletOnScreen = falseTextMode (TEXT_BUFFERED)while true if ScanKeyDown (VK_LEFT)
and turretx > 0 then turretx = turretx - 1 endif if ScanKeyDown (VK_RIGHT) and turretx < 37 then
turretx = turretx + 1 endif for i = 1 to alienCount if alienOnScreen (i) then alienx (i) = alienx (i) + 1 if
alienx (i) > 37 then alienx (i) = 0 alieny (i) = rnd () % 22 + 1 endif if rnd () % 10 + 1 = 1 then for j =
1 to bombCount if not bombOnScreen (j) then bombOnScreen (j) = true bombx (j) = alienx (i) +
1 bomby (j) = alieny (i) j = bombCount endif next endif endif next if bulletOnScreen then bullety =
bullety - 1 if bullety < 1 then bulletOnScreen = false endif else if ScanKeyDown (VK_SPACE) then
bulletOnScreen = true bullety = 22 bulletx = turretx + 1 endif endif cls color (255, 255, 255) locate 0,
0: print "Score=" + score locate 30, 0: print "Lives=" + lives color (255, 50, 50) for i = 1 to
alienCount if alienOnScreen (i) then locate alienx (i), alieny (i): print ">O<" endif next color (150,
150, 150) locate turretx, 23: print "<!>" if bulletOnScreen then color (255, 255, 50) locate bulletx,
bullety: print "!" endif color (175, 175, 175) for i = 1 to bombCount if bombOnScreen (i) then
locate bombx (i), bomby (i): print "O" endif next if bulletOnScreen then for i = 1 to alienCount if
alienOnScreen (i) then if bullety = alieny (i) and bulletx >= alienx (i) and bulletx <= alienx (i) + 2
then alienOnScreen (i) = false bulletOnScreen = false score = score + 100 endif endif next endif
DrawText () Sleep (75)wend
||
(Don't forget to add the j to the dim instruction at the top!)
You can see that the program actually runs, and that the aliens do make bombs.
We just need to make them fall down the screen, like this:

for i = 1 to bombCount if bombOnScreen (i) then bomby (i) = bomby (i) + 1 if bomby (i) > 23 then
bombOnScreen (i) = false endif endifnext

So the bomby (i) = bomby (i) is there to move the bombs down the screen.
The if bomby (i) > 23 then will check if the bomb has fallen off the bottom of the screen, and if so the
bombOnScreen (i) = false will take it off the screen (so it's ready to be dropped again by another
alien).
We can place this code after the code that moves the aliens. Like this:
||
const alienCount = 10const bombCount = 10dim score, lives, turretxdim alienx (alienCount), alieny
(alienCount), alienOnScreen (alienCount)dim bulletx, bullety, bulletOnScreen, i, jdim bombx
(bombCount), bomby (bombCount), bombOnScreen (bombCount)lives = 3turretx = 19for i = 1 to
alienCount alienx(i) = rnd () % 37 alieny(i) = rnd () % 22 + 1 alienOnScreen(i) =
truenextbulletOnScreen = falseTextMode (TEXT_BUFFERED)while true if ScanKeyDown (VK_LEFT)
and turretx > 0 then turretx = turretx - 1 endif if ScanKeyDown (VK_RIGHT) and turretx < 37 then
turretx = turretx + 1 endif for i = 1 to alienCount if alienOnScreen (i) then alienx (i) = alienx (i) + 1 if
alienx (i) > 37 then alienx (i) = 0 alieny (i) = rnd () % 22 + 1 endif if rnd () % 10 + 1 = 1 then for j =
1 to bombCount if not bombOnScreen (j) then bombOnScreen (j) = true bombx (j) = alienx (i) + 1
bomby (j) = alieny (i) j = bombCount endif next endif endif next for i = 1 to bombCount if
bombOnScreen (i) then bomby (i) = bomby (i) + 1 if bomby (i) > 23 then bombOnScreen (i) =
false endif endif next if bulletOnScreen then bullety = bullety - 1 if bullety < 1 then bulletOnScreen =
false endif else if ScanKeyDown (VK_SPACE) then bulletOnScreen = true bullety = 22 bulletx =
turretx + 1 endif endif cls color (255, 255, 255) locate 0, 0: print "Score=" + score locate 30, 0: print
"Lives=" + lives color (255, 50, 50) for i = 1 to alienCount if alienOnScreen (i) then locate alienx (i),
alieny (i): print ">O<" endif next color (150, 150, 150) locate turretx, 23: print "<!>" if
bulletOnScreen then color (255, 255, 50) locate bulletx, bullety: print "!" endif color (175, 175, 175)
for i = 1 to bombCount if bombOnScreen (i) then locate bombx (i), bomby (i): print "O" endif next if
bulletOnScreen then for i = 1 to alienCount if alienOnScreen (i) then if bullety = alieny (i) and bulletx
>= alienx (i) and bulletx <= alienx (i) + 2 then alienOnScreen (i) = false bulletOnScreen = false score
= score + 100 endif endif next endif DrawText () Sleep (75)wend
||
And the last step is to tell the computer how to check whether a bomb has hit the turret, and what to do
if it has.
We want to:
• Display a "turret hit" animation
• Put the turret back in the middle of the screen
• Subtract one from the lives
• If the lives reach zero the game is over, so
• Show the "Game Over" message, and
• End the game.
We also want to remove all the bombs from the screen. This gives the player a chance to react when the
game starts again.
We want to put this after we've drawn the rest of the screen.
So here's the final version.
||
const alienCount = 10const bombCount = 10dim score, lives, turretxdim alienx (alienCount), alieny
(alienCount), alienOnScreen (alienCount)dim bulletx, bullety, bulletOnScreen, i, jdim bombx
(bombCount), bomby (bombCount), bombOnScreen (bombCount)lives = 3turretx = 19for i = 1 to
alienCount alienx(i) = rnd () % 37 alieny(i) = rnd () % 22 + 1 alienOnScreen(i) =
truenextbulletOnScreen = falseTextMode (TEXT_BUFFERED)while true if ScanKeyDown (VK_LEFT)
and turretx > 0 then turretx = turretx - 1 endif if ScanKeyDown (VK_RIGHT) and turretx < 37 then
turretx = turretx + 1 endif for i = 1 to alienCount if alienOnScreen (i) then alienx (i) = alienx (i) + 1 if
alienx (i) > 37 then alienx (i) = 0 alieny (i) = rnd () % 22 + 1 endif if rnd () % 10 + 1 = 1 then for j =
1 to bombCount if not bombOnScreen (j) then bombOnScreen (j) = true bombx (j) = alienx (i) + 1
bomby (j) = alieny (i) j = bombCount endif next endif endif next for i = 1 to bombCount if
bombOnScreen (i) then bomby (i) = bomby (i) + 1 if bomby (i) > 23 then bombOnScreen (i) = false
endif endif next if bulletOnScreen then bullety = bullety - 1 if bullety < 1 then bulletOnScreen = false
endif else if ScanKeyDown (VK_SPACE) then bulletOnScreen = true bullety = 22 bulletx = turretx + 1
endif endif cls color (255, 255, 255) locate 0, 0: print "Score=" + score locate 30, 0: print "Lives=" +
lives color (255, 50, 50) for i = 1 to alienCount if alienOnScreen (i) then locate alienx (i), alieny (i):
print ">O<" endif next color (150, 150, 150) locate turretx, 23: print "<!>" if bulletOnScreen then
color (255, 255, 50) locate bulletx, bullety: print "!" endif color (175, 175, 175) for i = 1 to bombCount
if bombOnScreen (i) then locate bombx (i), bomby (i): print "O" endif next if bulletOnScreen then for i
= 1 to alienCount if alienOnScreen (i) then if bullety = alieny (i) and bulletx >= alienx (i) and bulletx
<= alienx (i) + 2 then alienOnScreen (i) = false bulletOnScreen = false score = score + 100 endif
endif next endif for i = 1 to bombCount if bombOnScreen (i) and bomby (i) = 23 and bombx (i) >=
turretx and bombx (i) <= turretx + 2 then color (255, 255, 0) for j = 1 to 10 locate turretx, 23:
print "\\\" DrawText () Sleep (75) locate turretx, 23: print "/" DrawText () Sleep (75) next turretx
= 19 lives = lives - 1 if lives = 0 then color (255, 255, 255) locate 15, 12: print "Game Over!"
DrawText () end endif for j = 1 to bombCount bombOnScreen (j) = false next endif next DrawText
() Sleep (75)wend