Tutorial: How to write games part 2

Go to page << 1 2 3 4 5 6 7 8 9 10 11 >>

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, bally1
dim ballx2, bally2
dim ballx3, bally3
dim ballxd1, ballyd1
dim ballxd2, ballyd2
dim ballxd3, ballyd3

ballx1 = rnd () % 38 + 1
bally1 = rnd () % 22 + 1
ballxd1 = 1: ballyd1 = 1
ballx2 = rnd () % 38 + 1
bally2 = rnd () % 22 + 1
ballxd2 = 1: ballyd2 = 1
ballx3 = rnd () % 38 + 1
bally3 = rnd () % 22 + 1
ballxd3 = 1: ballyd3 = 1

TextMode (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 + 1
bally(1) = rnd () % 22 + 1
ballxd(1) = 1: ballyd(1) = 1
ballx(2) = rnd () % 38 + 1
bally(2) = rnd () % 22 + 1
ballxd(2) = 1: ballyd(2) = 1
ballx(3) = rnd () % 38 + 1
bally(3) = rnd () % 22 + 1
ballxd(3) = 1: ballyd(3) = 1

TextMode (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 i

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

TextMode (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 = 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"

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 i

for i = 1 to 3
    ballx(i) = rnd () % 38 + 1
    bally(i) = rnd () % 22 + 1
    ballxd(i) = 1: ballyd(i) = 1
next

TextMode (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 = 3

dim ballx(ballCount), bally(ballCount)
dim ballxd(ballCount), ballyd(ballCount)
dim i

for i = 1 to ballCount
    ballx(i) = rnd () % 38 + 1
    bally(i) = rnd () % 22 + 1
    ballxd(i) = 1: ballyd(i) = 1
next

TextMode (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...

Go to page << 1 2 3 4 5 6 7 8 9 10 11 >>