Sei sulla pagina 1di 25

How to write games in Basic4GL...

15-May-2004
-Tom Mulgrew

Intro
This is a tutorial on how to write games in Basic4GL, which is a free programming language for
Windows computers.
It's aimed at the complete beginner, and takes you from the very basics of writing simple programs,
right through to writing scrolling 2D sprite based games.
So if you've never programmed a line of code before, I recommend you start at the beginning.
Otherwise you may want to skip a few sections and jump in at the level that suits you.
This is part 1 of the tutorial, which introduces the basics of programming by using them to write a
simple text based space invaders like game. Later parts will build onto what is taught here, introducing
2D sprite based animation and finally a full parallax scrolling 2D shooter.

Why start with Basic4GL?


Once upon a time if you bought a computer, it came with a free programming language called BASIC,
which stands for "Beginner's All Purpose Symbolic Instruction Code" and was invented to make
programming easier to learn for beginners.
Traditionally it wasn't the most powerful language for writing complex applications, but it did make it
easy to write interesting programs - often with graphics and/or sound effects - without having to write
pages of program code just to get started.
Basic4GL aims to continue in this spirit, as a free, beginner friendly language, based on today's
technology like OpenGL 3D graphics. It's specifically designed to make the fun stuff easily accessible,
like games and animations.
And while you're doing this, you're also learning basic programming concepts and skills that you can
use if you decide to move on to more powerful languages that professional programmers use.
So, in that spirit, this tutorial will teach you to program using animations, games, and basically
anything that I think looks interesting or cool. We will start with text based animation (because it's
easiest to start with), move into sprite based 2D animation and work our way up to a full 2D parallax
scrolling platform shooter.

Getting started
First you need a computer. It will need to be:
• A PC. About 350 Mhz or faster is recommended.
• It must be running one of the following versions of Windows:
• Windows 98, or
• Windows ME, or
• Windows 2000, or
• Windows XP
• A graphics card with OpenGL support (any recent computer should be fine).
Next you need the Basic4GL compiler and development environment.
Fortunately this is available for free from the Basic4GL website: www.basic4gl.net.
You will need to download and install it.

My first program!
Okay! Let's assume you've installed Basic4GL and are ready to go. (If you haven't, there's not much
that this tutorial can do for you :)
We're going to write our first program. It will be very simple.
First, run Basic4GL as follows:
Click the windows "Start" menu, then "Programs", then "Basic4GL", then "Basic4GL".
You should see the Basic4GL programming window.
This window looks fairly innocent. Infact it looks a bit like the Windows notepad.
It has an area where you can type into, and and a few buttons on the top.
This however is the Basic4GL editor and is all you need to create and test your own programs. You
type them into the text area at the bottom, and run them by clicking the "Go" button on the toolbar.
Here's the first program.
print "Hello world!"
Type this in, then click the "Go" button on the toolbar:
Now one of two things will happen!
If it works, the screen will go black and you will see this:
In the top left hand corner.
Yes, it's the infamous Hello World program. Press a key to finish the program and switch back to the
regular screen.
If it doesn't work, you will likely see something like this:
This means there is a syntax error in the program.
If this happens to you, do not panic! Syntax errors occur all the time. They are the programming
equivalent of a typo. The computer is simply saying it does not understand what you are trying to do,
so you just need to fix it up and try again.
The computer has positioned the cursor at the position of the problem, and has displayed a description
of the problem on the status bar (the gray bar at the bottom). In the example, it reads "Unknown
variable: prit. Must be declared with DIM."
Sometimes these 'error messages' can be helpful in figuring out the cause of the problem.
In this example, it isn't all that useful, so we need to have a close look ourselves and figure out what is
wrong.
Here we have written: prit instead of print
All we need to do is correct the problem, then click the Go button again, and we should get the results
we need.

Examining the "Hello World" program


Lets have a look at how "Hello World" worked. It's quite a simple program.
It has just one instruction, consisting of the command print and a parameter "Hello world!".
The print command as you might have guessed prints text on the screen.
You may have noticed that Basic4GL changed its colour to red as you typed it. This is Basic4GL's way
of telling you that it has recognised the word "print" as one of its commands.
The "Hello world!" part is what's known as a quoted string. This is how we supply text to the
program, so we can tell the print command what we want to print to the screen. The double quotes tell
Basic4GL that anything between the quotes are to be treated as text data, so it doesn't try to read it as
program code. Basic4GL displays quoted strings in green.
If we remove the quotes from the program and try to run it, it won't work! Because now it treats Hello
World! as program instructions. There is no command called "Hello", so Basic4GL will stop and
complain.

Saving your program


Once you have a working program that you want to keep, you can save it to disk.
It is also a good idea to save your changes as you go, so that your work isn't lost if something
unexpected happens.
Basic4GL saves programs the same way as a text editor would.
You can click "Program|Save", press Control+S on your keyboard, or click the save button

Basic4GL as a calculator
Here's our second program.
Before typing it in, click the new program button on the toolbar , to tell Basic4GL we are working on a
new and different program.
print "4 + 5 = "print 4 + 5
Again, click on the "Go" button to run the program.
So now we can use Basic4GL as a calculator!
Infact we've just written our first expression!
You've just written your first expression: 4 + 5
And the computer has calculated the result and displayed it (with print).
Again let's break it down.
This program has two instructions. Each on a different line.
print "4 + 5 = "
This is just like the Hello World program. We have used the print command, and supplied it with the
text "4 + 5 = " as a quoted string. We know that this means write the text "4 + 5 =" to the screen.
print 4 + 5
This looks much like the first line, except the 4 + 5 is not a quoted string anymore. We are using the
print command again, but this time using 4 + 5 as the parameter.
So what does the computer do? It evaluates 4 + 5 first. It calculates that 4 + 5 equals 9, and then sends
9 through to print as the parameter.
So the second line prints out a 9 on the screen.
Try modifying the program to calculate other equations. Here are some examples:
4+5+6
7*8 * means multiplication
14.2 - .5
3/2 / means division
1+2*3
(1 + 2) * 3
sqrt (2)
(1 + sqrt (2)) * 2
"Cat" + "fish"
"Five" + 5
"1" + "3"
"4 x 5 = " + 4 * 5
Some notes to be aware of:
• Some arithmetic operations are performed before others. E.g. multiplication (*) is always
performed before addition and subtraction (+)
• You can force the order of evaluation by using brackets
• sqrt is a function (calculates the square root).
You can use functions anywhere that you can use a regular number.
• You can use plus (+) to join two quoted strings together.

Variables
So now we can calculate mathematical equations and print the results on the screen.
Useful... But we are still some distance away from writing a parallax side scroller! Don't worry, we will
get there! But first we need to introduce a few more concepts.
We will start with variables.
A variable is somewhere that you can store some data.
In Basic4GL, this data can be one of the following:
• A real number.
This corresponds to a regular number, like 5, -12, 4.332 or 3.14159265
These numbers can be positive or negative, or have fractions.
(Another name for these sorts of numbers is "floating point" numbers. But we will just call them "real"
numbers in this tutorial.)
• An integer number.
These are just like real numbers, but can only store whole numbers, not fractions.
Like -4, 1000, 32.
(But not 0.3333 or -12.9)
• A text "string".
This stores some text, such as "Hello World!" or "The price of fish is $4.77 today" or "Press any key to
continue"
Almost all programs use variables. Even games use them to keep track of all sorts of things. They
might store how many aliens there currently are, or how many bullets the player has, or what the score
is, or what the players names are on the high score chart, or how long since each one fired a bullet, or
any number of things.
So let's have an example.
Clear out the old program (save it first if you want to), and type in the following.
dim a, ba = 5b = 3printr "a stores " + aprintr "b stores " + b
Then run the program (with the Go button, as usual).
It should tell us that a is storing 5, and b is storing 3.
a and b are variables.
We told the computer that we wanted to create two variables with line at the top:
dim a, b
dim is the command that creates variables. After it we list the names that we want to give to those
variables, with commas in between (if there are more than one). In this case, we have two variables
called a and b.
Next we tell the computer to assign values to them with:
a=5
b=3
This tells the computer to store the value 5 in the variable named a, and the value 3 in the variable
named b.
Finally we print the results to screen:
printr "a stores " + a
printr "b stores " + b
This time we're using the Basic4GL printr command. This is exactly like the print command except
that it returns the cursor to the start of the next line after it has finished.
Variables can be used anywhere that you would normally put a number - in expressions or as
parameters for commands. For example, consider the following program.
dim a, b, c
a=5
b=3+4
c=a+b
printr "a = " + a
printr "b = " + b
printr "c = " + c
printr "b + c = " + (b + c)
(Type it in and run it if you want.)
This program uses an expression 3 + 4 to calculate the value to store in b:
b=3+4
It uses a + b to calculate the value to store in c:
c=a+b
It uses b + c to calculate a value to use in a parameter to printr:
printr "b + c = " + (b + c)

Choosing variable names


So far we have used a, b and c as variable names, but we don't have to stick with single letters if we
don't want. In our program, the variables didn't really have any purpose, but in most programs they do,
so it is a good idea to try to give them names that match what it is they are for. This makes the program
easier to understand when you come back to it.
If we are storing the number of lives the player has and his/her score, we could write this:
dim a, b
a=3
b = 1020
this works fine, but if we instead wrote:
dim lives, score
lives = 3
score = 1020
it makes it a lot easier to understand what the program is trying to do.
There are a few rules you have to follow when choosing the names for your variables, otherwise the
compiler won't compile and run your program:
• Variable names cannot contain spaces.
• Variable names can only contain letters (a..z) and numbers (0..9) and the underscore character
(_).
• Variable names cannot start with a number.
• You cannot use words that have already been reserved for Basic4GL, such as commands (like
print).
• You cannot have two variables with the same name.
Some examples of acceptable variable names:
cat, a1, my_shoe_size, MaximumHealth, counter
Some examples of unacceptable variable names:
cat fish, 2many, health&armour

Variable types
All the variables we have seen so far are integer variables.
We can't use them to store text strings.
dim a
a = "my house"
Would not work.
We can't use them to store real numbers with fractions.
dim a
a = 3.443
would compile and run, however it would round 3.443 to 3 before storing it in a.
So how do we tell the computer we want to store a text string instead of an integer?
To store a text string, we have tell the computer to allocate a text string variable.
We do this by appending a dollar sign ($) to the variable name when we declare it.
Here's another example to try.
dim school$, schoolMotto$school$ = "Scott Base elementary"schoolMotto$ = "If it moves, don't eat
it"printr "Welcome to " + school$printr "Our motto is"printr schoolMotto$
We've created two text string variables:

dim school$, schoolMotto$

Because they end in a dollar sign, the computer knows that we want to store text string data inside
them.
We've stored some text inside them:

school$ = "Scott Base elementary"


schoolMotto$ = "If it moves, don't eat it"

And we've used them in expressions and as parameters to printr

printr "Welcome to " + school$


printr "Our motto is"
printr schoolMotto$

So that's how we store text in variables.


If we want to tell the computer to store a real number in a variable, we have to append a hash sign (#)
to the variable name..
For example:
dim l#, w#, diameter#
l#=10
w#=14
diameter# = sqrt (l# * l# + w# * w#)
printr "A " + w# + " by " + l# + " inch screen"
printr "Is " + diameter# + " inches in diameter"

Drawing text on the screen


We've covered a fair bit of theory so far, and you may now be scratching your head and wondering how
you're going to hold it all in. Again, don't worry! The best way to pick these things up is from
examples, and we'll have plenty of those.
For now, let's move on to something a little more visual, where we can see what's going on.
We're going to draw a scene from a space invaders like game.
Just be a single snapshot for now as we will need to learn a few more things before we can turn it into
something playable.
Here's the program:
color (255, 255, 255)
locate 0, 0: print "Score=1040"
locate 30, 0: print "Lives=3"
color (255, 50, 50)
locate 11, 12: print ">O<"
color (150, 150, 150)
locate 17, 23: print "<!>"
color (255, 255, 50)
locate 15, 17: print "!"
When you run this, you should see something that looks a bit like a scene from a space invaders type of
game.
It has the score and lives displayed at the top, some sort of red space invader thing in the middle, the
player's gun turret down the bottom in gray, and a yellow bullet presumably halfway through flying up
the screen.
Okay, it's all just coloured text characters for now, but it will serve until we learn about sprites and
other forms of animation.
We have used three different commands:
• "color" sets the colour of the text cursor. We supply three numbers to specify the three colour
components: red, blue and green respectively. Each number can range from 0 (no brightness) to
255 (full brightness).
Any text drawn after this will be in the specified colour.
• "locate" positions the cursor. The first number is the column and the second is the row.
The text screen has 40 columns and 25 rows.
• "print" as we know prints text on the screen, at the current cursor position, in the current colour.
You can see that we've used the colon (:) to separate the locate command from the print command.
We must use a colon if we want to place more than one command on one line, so that Basic4GL knows
where the first one stops, and the second one begins.

Adding animation
Believe it or not, we are going to turn the previous program into a full working game. So don't forget to
save it before moving on.
First though, we are going to learn how animate.
The basic principles of computer animation are the same as those of cartoon animation. It can be
broken down into steps:
1. You display a picture.
2. Leave it on the screen for a short amount of time
3. Then replace it with another picture which has changed slightly from the first.
4. Go back to step 2
The brain interprets the continually changing still images as movement, and we have animation.
Let's illustrate with an example:
Sleep (2000)
cls:locate 10, 12: print "->": Sleep (200)
cls:locate 11, 12: print "->": Sleep (200)
cls:locate 12, 12: print "->": Sleep (200)
cls:locate 13, 12: print "->": Sleep (200)
cls:locate 14, 12: print "->": Sleep (200)
This is a very short animation. It simply moves "->" along the screen a few times and stops.
The new commands are:
• "cls" which clears all the text from the screen.
• "Sleep" which makes Basic4GL pause before it continues executing the instructions. The
number is the length of the pause in milliseconds. So 1000 corresponds to a one second pause.
As you can see, we display a picture (the "->") on the screen, leave it for a short amout of time, then
replace it with another picture (the "->" slightly to the right of where it was). We do this five times,
each time changing the position of the "->" by changing the column number in the locate command.
This gives us our very simple animation.
Note: I put the "Sleep (2000)" line at the top to add a 2 second delay to the program before it started.
This gives the monitor time to switch resolutions and get setup before the animation starts.

Improving the animation


The biggest problem with that animation is that we had to write a line of code for each "frame" of the
animation.
In this case, it wasn't so bad, as we only had 5 frames, and each frame is very simple. But if you
consider that even a simple 2D computer game can display several thousand frames, with dozens of
objects moving around in each, then it becomes clear that we need a better way of doing things than
writing one line of code for each frame!
One better approach is to use an "animation loop".
We will demonstrate this by extending the animation to move the "->" all the way from the left hand
side of the screen to the right hand side.
Here's the program:
Sleep (2000)
dim x
for x = 0 to 38
cls
locate x, 12
print "->"
Sleep (75)
next
As you can see, this program is a lot shorter than 39 lines, but it still displays 39 frames of animation!
Let's examine what it's doing:
We've introduced a variable x, which we are using to store the column of the "->"s position. Notice that
we are now positioning the cursor with "locate x, 12". That is we are calling the locate command, and
passing x as the first parameter (the column number) and 12 as the second (the row number).
Next, we've created a for..next "loop".
A "loop" is a set of commands that get run more than once. In our case, this is all the commands
between the for line and the next line.
The for..next loop is a particular type of loop. It has a loop variable, which counts from one number to
another number:

for x = 0 to 38

In this case, the loop variable is x. It will count from 0 to 38 (inclusive). And for each time, it will run
the contents of the loop.
So the first time it is effectively running:

x=0
cls
locate x, 12
print "->"
Sleep (75)

And the second time:

x=1
cls
locate x, 12
print "->"
Sleep (75)

And so on, up until the last time, where it runs:

x = 38
cls
locate x, 12
print "->"
Sleep (75)

And then it's finished.


So each time it runs the locate command, the cursor will end up one to the right of where it was last
time, and the arrow will be drawn in a slightly different place.
As you can see, the for..next loop is very useful, and makes what would otherwise have been a long
repeditive program very small and compact.
Here's some more for..next examples:
dim i
for i = 1 to 10
printr i
next

dim i
for i = 0 to 9
printr 10 - i
Sleep (1000)
next
print "Blastoff!"

dim i
printr "12 times table"
for i = 1 to 12
printr i + " x 12 = " + (i * 12)
next

Back to space invaders


So let's take what we've learned and extend the space invaders program. We will be adding to the
program bit by bit, so each example will show the new pieces in red.
First, we will start by storing the score and lives in some variables:
dim score, lives
lives = 3
color (255, 255, 255)
locate 0, 0: print "Score=" + score
locate 30, 0: print "Lives=" +lives

color (255, 50, 50)


locate 11, 12: print ">O<"
color (150, 150, 150)
locate 17, 23: print "<!>"
color (255, 255, 50)
locate 15, 17: print "!"
Notice that we set "lives" to it's initial value at the start of the program. The initial value for "score" is
0, so we don't have to change it.
Next we will take all the drawing code, and put it into an animation loop. The program will keep on
drawing new animation frames until the user quits it by pressing escape. So remember to press escape
when you want to get out of the program!
dim score, lives
lives = 3
while true
cls
color (255, 255, 255)
locate 0, 0: print "Score=" + score
locate 30, 0: print "Lives=" + lives
color (255, 50, 50)
locate 11, 12: print ">O<"
color (150, 150, 150)
locate 17, 23: print "<!>"
color (255, 255, 50)
locate 15, 17: print "!"
Sleep (75)
wend
This time we've used a while..wend loop, which is another sort of loop. Like the for..next loop, the
instructions inside the loop are run multiple times. In this case the computer will keep on running
the instructions forever, until the user quits the program by pressing escape.
(Not all while..wend loops run forever, there are many different ways to use them. The
while..wend loop will be explained in more detail later.)
You may have noticed a couple of things:
• The screen flickers a lot
• Nothing actually moves!
We will fix the flickering later. For now we need to concentrate on making things move, and the
obvious place to start is the player's turret, which will slide along the bottom of the screen.
To make the player's turret move, the computer needs to store information about the turret in
variables. We need to decide exactly what information it needs to remember so that it can draw
the turret on the screen and move it around when the player pressed the right keys.
We will make the turret moves as follows:
• We will store the turret's position in a variable: turretx. This will store the column number
of the turret.
• Because the turret always stays on the same row, we don't need to store the row number.
• We will also add some lines to move the turret left and right when the player presses the
left and right arrow keys.
But first, we need to take another detour to introduce some more new concepts.

Constants, functions, keyboard input, and conditional


statements
Before we can continue with the space invaders game we need to take a detour to learn a few new
techniques. Don't forget to save the space invaders program away to disk first.

Constants
A constant is much like a variable.
It has a name (like true, TEXT_BUFFERED, VK_LEFT). It also has a value, which can be either a
number or a string.
Unlike variables, the value of a constant never changes.
Basic4GL has a number of pre-defined "constants". These are constants that Basic4GL already
knows about, without you having to tell it first.
Here are some pre-defined constants:
printr "m_pi = " + m_pi
printr "TEXT_BUFFERED = " + TEXT_BUFFERED
printr "VK_LEFT = " + VK_LEFT
Sometimes constants are used as an easy way to remember a commonly used number, such as Pi
(stored in the constant m_pi).
Sometimes constants are used to associate a more meaningful name with a number. For example
VK_LEFT stores the scan code of the left arrow key, which happens to be 37.
The computer knows that 37 means the left arrow key, but I'm less likely to remember that. But
if I use the VK_LEFT constant in a program, I can easily see the program is trying to do.
We will be using the following constants to find out which keys are being pressed, so we can move
the gun turret accordingly:
• VK_LEFT
• VK_RIGHT
• VK_SPACE

Functions
A function is like a command. It has a name which Basic4GL recognises, and sometimes has one
or more parameters.
The main difference is that a function evaluates to a number or a string. We call this the "return
value". We can use this value anywhere we would normally use a value, e.g. in an expression, as a
parameter to another command or function. We can also assign it to a variable.
Some examples of functions:
printr "Half the square root of 2 is " + sqrt (2) / 2
printr "A random number: " + rnd ()
dim a$, helloLength
a$ = "Hello"
helloLength = len (a$)
print a$ + " has " + helloLength + " letters"
sqrt, rnd, and len are all functions.
As you can see, they all evaluate to a number or string that can be used like any other value.
Basic4GL has a large number of functions that calculate a number of different things.

Keyboard input
Right! Now we've had a very quick crash course on functions and constants, we can introduce the
ScanKeyDown function.
We are going to use this function to find out whether keys are being pressed or not. The function
takes a single parameter which is the "scan code" of the key that we are interested in. Because I
don't know all the keyboard scan key codes off the top of my head, we're going to use special
predefined constants: VK_LEFT, VK_RIGHT and VK_SPACE.
Here's how it all fits together:
while true
cls
print ScanKeyDown (VK_SPACE)
wend
(Tap the spacebar while the program is running to see it in effect.)
ScanKeyDown (VK_SPACE) evaluates to -1 when the spacebar is being pressed, and 0 when it
isn't.
(-1 and 0 are actually special "boolean" values true and false. But we will worry about boolean
values later.)
Here's another example:
while true
cls
if ScanKeyDown (VK_UP) then
locate 19, 4: print "Up"
endif
if ScanKeyDown (VK_DOWN) then
locate 18, 19: print "Down"
endif
if ScanKeyDown (VK_LEFT) then
locate 8, 12: print "Left"
endif
if ScanKeyDown (VK_RIGHT) then
locate 28, 12: print "Right"
endif
wend
(In this one, you need to press the arrow keys while it's running to see what it does.)
This example uses the if..then..endif statement, which will be explained very soon.

Space invaders with keyboard input


Okay, load up the space invaders program, and modify it to look like the following (new bits are
in red.)
dim score, lives, turretx
lives = 3
turretx = 19
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

cls
color (255, 255, 255)
locate 0, 0: print "Score=" + score
locate 30, 0: print "Lives=" + lives
color (255, 50, 50)
locate 11, 12: print ">O<"
color (150, 150, 150)
locate turretx, 23: print "<!>"
color (255, 255, 50)
locate 15, 17: print "!"
Sleep (75)
wend
(Don't forget to update the locate command where it draws the turret!)
Okay, so now we can move the turret left and right by pressing the left and right arrow keys. This
is our first interactive program! We're well on our way!
But first we have to understand this new if..then..endif statement.
This is called a conditional statement, because the computer sometimes runs the instructions
between then and endif and sometimes doesn't. This all depends on the part between if and then,
i.e. the "condition".
Let's examine the first one:

if ScanKeyDown (VK_LEFT) and turretx > 0 then

The "condition" here is: "ScanKeyDown (VK_LEFT) and turretx > 0"
This is like an expression (e.g. 1+2/3), except it evaluates to either true or false.
Conditional statements often read a lot like english. In english you might say "If it is raining then
take your umbrella to work".
In this one we are telling the computer "if the player is pressing the left arrow key and the turret
hasn't already moved as far as it will go, then move it slightly to the left".
Of course the computer doesn't speak english, so we need to put it in computer terms. So "the
player is pressing the left arrow key" becomes "ScanKeyDown (VK_LEFT)", and "the turret
hasn't already moved as far as it will go" becomes "turretx > 0".
When the computer runs this instruction and sees that the condition is true (i.e. the player is
pressing the key and the turret can move further), then it will run the instructions between then
and endif:

turretx = turretx - 1

Which will move our turret one column to the left (by subtracting one from it's column number).
Of course if the computer runs the if ... then instruction and the player is not pressing the left
arrow key (or the turret has already reached the edge of the screen) then the computer will see
that the condition is false, and it will not run the instructions between then and endif. Instead it
will skip to just after the endif and keep running the program from there.
The second if..then..endif line is used to move the turret right. It works much the same way as
moving left so I'll leave you to examine it and see how it works.

Buffered text output


It's time to deal with the flickering, as it is quite painful to watch!
The reason for the flickering is that the screen is updated every time we:
• Clear it (with cls)
• Draw something (with print)
So each time a frame is drawn, everything dissapears, and then is drawn back in, one object at a
time. So the ugly flicker is due to everything constantly dissapearing and re-appearing.
What we want is a way to prevent the user seeing our drawing until we have everything setup
and ready to display. So the user never has to see a half drawn frame.
We can do this with the TextMode and DrawText commands.
dim score, lives, turretx
lives = 3
turretx = 19
TextMode (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
cls
color (255, 255, 255)
locate 0, 0: print "Score=" + score
locate 30, 0: print "Lives=" + lives
color (255, 50, 50)
locate 11, 12: print ">O<"
color (150, 150, 150)
locate turretx, 23: print "<!>"
color (255, 255, 50)
locate 15, 17: print "!"
DrawText ()
Sleep (75)
wend
Flicker problem solved!
TextMode (TEXT_BUFFERED) switches the text drawing mode to buffered mode. This means
that any changes to text on the screen will not be shown until we say so. And we tell the computer
we're ready to display the changes with the DrawText () command.
Sorted!

Moving the alien


Next we'll add some code to move the space alien.
It will move from left to right. When it reaches the right hand side of the screen, we will start it
again from the left.
dim score, lives, turretx, alienx

lives = 3
turretx = 19
alienx = 0
TextMode (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

alienx = alienx + 1

if alienx > 37 then


alienx = 0
endif

cls
color (255, 255, 255)
locate 0, 0: print "Score=" + score
locate 30, 0: print "Lives=" + lives
color (255, 50, 50)
locate alienx, 12: print ">O<"
color (150, 150, 150)
locate turretx, 23: print "<!>"
color (255, 255, 50)
locate 15, 17: print "!"
DrawText ()
Sleep (75)
wend
(Again, don't forget to update the locate line where we draw the alien.)
It should be getting easier to see how this works.
We've created a new variable to store the alien's position, called alienx. Like with the turret, this
stores the column that the alien is currently positioned at.
We set it to zero at the start. We didn't really have to (as zero is the default anyway), but it
doesn't hurt to be specific.
We move the alien one column to the right by adding one to it's column position.

alienx = alienx + 1.

Then we check whether the alien has reached the right hand side of the screen:

if alienx > 37 then

And if it has, we move it back to the left hand side:

alienx = 0
And that's all there is to it.

Moving the bullet


The object of the game is to shoot the alien, so we need to have a moving bullet.
This is a little bit more complicated than the other moving objects because it isn't fixed at a single
height. Also, sometimes the bullet isn't on the screen at all.
Again, we need to decide what the computer needs to store in order to handle the bullet.
We will store the bullet in three variables:
• bulletx will store the column position of the bullet.
• bullety will store the row position of the bullet.
• bulletOnScreen will be set to true if the bullet is on the screen, and false if the bullet is
waiting to be fired (i.e. not on the screen yet).
So when the user presses space, we want to "fire" the bullet, by placing it on the screen just
above the turret.
While the bullet is on the screen, it will fly up until it reaches the top, then it will be taken off the
screen ready to be fired again.
When it comes time to draw the bullet, we only draw it if it's on the screen.
The modified program looks like this.
dim score, lives, turretx, alienx
dim bulletx, bullety, bulletOnScreen
lives = 3
turretx = 19
alienx = 0
bulletOnScreen = false
TextMode (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
alienx = alienx + 1

if alienx > 37 then


alienx = 0
endif

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)
locate alienx, 12: print ">O<"
color (150, 150, 150)
locate turretx, 23: print "<!>"
if bulletOnScreen then
color (255, 255, 50)
locate bulletx, bullety: print "!"
endif
DrawText ()
Sleep (75)
wend
(You may notice that while we can now shoot at the alien, we can't actually hit it! The bullet passes
straight through. This is because we haven't told the computer to do anything when the bullet hits the
alien.)
We're getting very close to a complete game now! A very simple one, but a complete one all the same.
The new code should be starting to make sense now, but you may be wondering what true and false
mean.
You may remember we learnt earlier that conditional expressions evaluate to true or false. And
that if..then..endif uses the condition between if and then to determine whether to run the
instructions between then and endif.
Well we can actually store a condition result in a variable. So we set bulletOnScreen to true to say
that the bullet is on the screen, and false to say that it isn't. We can then use it as the condition
part of our if..then..endif statement.
We've used some if..then..endif statements inside other if..then..endif statements.
This is okay. The second if..then..endif simply become and instruction inside the first one.
We've also used an if..then..else..endif statement. So you may be wondering how this new else bit
works.
It's actually just a simple extension of the standard if..then..endif statement. If the condition
(between if and then) evaluates to true, the computer runs the instructions between then and else,
otherwise it runs the instructions between else and endif instead.
To look at what it actually does:
If the bullet is on the screen "if bulletOnScreen then", we move it up the screen by subtracting one
from the row position "bullety = bullety - 1". We also check whether the bullet has reached the
top of the screen"if bullety < 1 then", and if so take it off the screen. "bulletOnScreen = false".
Inside the else..endif section we say what to do if the bullet is not on the screen. In this case the
player can shoot it by pressing the spacebar, so we check whether the user is pressing space "if
ScanKeyDown (VK_SPACE) then" and if so, place the bullet on the screen and position it above
the gun turret:

bulletOnScreen = true
bullety = 22
bulletx = turretx + 1

Shooting the alien


To complete the game we need to make the bullet hit the alien.
So we have to tell the computer how to check when the bullet has hit the alien, and what to do
when it happens.
We're going to keep it simple, and do the following:
• Display a simple alien hit animation
• Delay for a couple of seconds
• Take the bullet off the screen
• Reset the alien back to the left hand side
• Add 100 points to the score
So let's do it:
dim score, lives, turretx, alienx
dim bulletx, bullety, bulletOnScreen, i
lives = 3
turretx = 19
alienx = 0
bulletOnScreen = false
TextMode (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
alienx = alienx + 1
if alienx > 37 then
alienx = 0
endif
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)
locate alienx, 12: print ">O<"
color (150, 150, 150)
locate turretx, 23: print "<!>"

if bulletOnScreen then
color (255, 255, 50)
locate bulletx, bullety: print "!"
endif

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

DrawText ()
Sleep (75)
wend
To hit the alien, the bullet has to be on the screen, at the same row as the alien, and on a column
between alienx and alienx + 2 (because the alien is 3 columns wide).

We animate the exploding alien by repeatedly drawing diagonal lines over the top, using a
for..next loop to repeat the process 10 times, and a Sleep (50) delay for timing.
We placed all this code after the regular drawing code, so that everything is already on the screen
when we perform our animation.
After our animation, we remove the bullet from the screen, reset the alien to the left side, add 100
hundred points and pause for 1 second.

Program complete (well, sortof!)


And that's it. That's our text based space alien game.
Currently it has a lot of restrictions, such as there's only one alien, and it doesn't shoot back (so
there's not much point in having 3 lives...). But it's a playable game all the same.
Along the way we've learnt a number of programming concepts and techniques, including:
• how to store data in variables
• how to loop the program so that it runs the same instructions over and over (while..wend
and for..next)
• how to write conditional instructions that are run only in certain situations (if..then..endif).
• how to animate by drawing gradually changing frames and displaying them to the user
• how to represent an object's position on the screen with variables
• how to respond to keyboard input.
Notice how we built up the program in stages.
At each stage we had a working program that we could run and examine the results of. This
allowed us to check each stage, and make sure that the code was doing what we expected before
moving on. It also kept things interesting (I hope!), as we were able to see the difference that each
of our changes made.
As a final touch we will add a little variety and make the alien fly past at different heights.
We can use the rnd() function, which returns a random number between 0 and about 32,000. A bit
like throwing a 32,000 sided dice I guess.
With a bit of maths we can turn this into a number between 1 and 22 like so:

alieny = rnd () % 22 + 1

Here's the final version:


dim score, lives, turretx, alienx, alieny
dim bulletx, bullety, bulletOnScreen, i
lives = 3
turretx = 19
alienx = 0
alieny = 12
bulletOnScreen = false
TextMode (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
alienx = alienx + 1
if alienx > 37 then
alienx = 0
alieny = rnd () % 22 + 1
endif
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)
locate alienx, , alieny: print ">O<"
color (150, 150, 150)
locate turretx, 23: print "<!>"

if bulletOnScreen then
color (255, 255, 50)
locate bulletx, bullety: print "!"
endif

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

DrawText ()
Sleep (75)
wend

Where to now?
Don't worry too much if this all seems like a lot to take in in one setting. It's not important to absorb it
all the first time through. The best way to learn is by example and experimentation, so don't be afraid to
play around with the examples or try and invent some of your own. You won't break anything!
You may want to try skimming through the Programmer's guide (choose "Programmer's guide" from
the "Help" menu in Basic4GL), which lists a number of functions and commands used in Basic4GL for
things like joystick and mouse input, resizing the text area or changing the font.
You may also want to play with the demo programs that are distributed with Basic4GL (click "Open..."
from the "Program" menu in Basic4GL). Just keep in mind that some of the demo programs use
programming features that we haven't learnt yet, and many of them use OpenGL which is a huge topic
in it's own right.)
We will finish off this first part of the tutorial with some more example programs/games to try out and
experiment with. See if you can figure out how they work, or modify/extend them into your own
customised versions.

Bricks
dim score, ballsdim ballx#, bally#, ballxd#, ballyd#dim paddlexdim col, line, a$paddlex = 18ballx#

20bally#

10ballxd#

0ballyd#

1score = 0balls = 3color (255, 255, 255)locate 0, 0: print "Score: 0"locate 30, 0: print "Balls: 3"locate
0, 2color (255, 100, 100)for line = 1 to 7 for col = 1 to 20 print "[]" nextnextTextMode
(TEXT_BUFFERED)while true color (255, 255, 255) locate 0, 0: print "Score: " + score locate 30, 0:
print "Balls: " + balls locate paddlex, 23: print" " if ScanKeyDown (VK_LEFT) and paddlex > 0 then
paddlex = paddlex - 1 endif if ScanKeyDown (VK_RIGHT) and paddlex < 35 then paddlex = paddlex
+ 1 endif Color (200, 200, 200) locate paddlex, 23: print"-----" Color (255, 255, 255) locate ballx#,
bally#: print " " a$ = CharAt$ (ballx# + ballxd#, bally# + ballyd#) if a$ = "-" then ballyd#

-ballyd# ballxd#

(int (ballx#) - paddlex - 2) / 2.0 a$ = " " endif ballx#


ballx# + ballxd# bally#

bally# + ballyd# if ballx# <= 0 or ballx# > 39 then ballxd#

-ballxd# endif if bally# <

0 then ballyd#

-ballyd# endif if bally# > 23 then DrawText ()


Sleep (1000) balls

balls - 1 if balls > 0 then locate paddlex, 23: print" " paddlex = 18 ballx#

20 bally#

10 ballxd#

0 ballyd#

1 else Color (255, 255, 255) locate 15, 12: print "Game Over!" DrawText () end endif endif locate
ballx#, bally#: print "o" if a$ = "[" or a$ = "]" then ballyd#

-ballyd# score
Road
dim roadx, carx, scoredim delay#dim iroadx = 13carx = 20delay#

100Color (200, 200, 200)for i

1 to 23 locate roadx, i: print " "nextTextMode (TEXT_BUFFERED)while true roadx = roadx +


rnd () % 3 - 1 if roadx < 0 then roadx = 0 endif if roadx > 40 - 14 then roadx = 40 - 14 endif Color
(200, 200, 200) locate 0, 24: printr locate roadx, 23: print " **" score = score + 1 Color (255, 255,
0) locate 0, 0: print "Score = " + score if ScanKeyDown (VK_LEFT) then carx = carx - 1 endif if
ScanKeyDown (VK_RIGHT) then carx = carx + 1 endif if CharAt$ (carx, 12) <> " " then Color (255,
100, 10) locate carx - 1, 11: print "X X" locate carx - 1, 12: print " X " locate carx - 1, 13: print "X X"
Color (255, 255, 255) locate 15, 12: print "Game Over!" DrawText () end endif Color (255, 255, 255)
locate carx, 12: print "O" DrawText () Sleep (delay#) delay# = delay# - 0.25wend

Guess a number
dim guesses, number, guessnumber = rnd () % 100 + 1Color (255, 255, 255)printr "I've chosen a
number between 1 and 100"printr "See if you can guess it in 10 guesses"printr "To make a guess, type
in the number and"printr "press Enter"printrfor guesses = 1 to 10 print "Guess " + guesses + ": " guess
= val (Input$ ()) if guess = number then printr printr "Correct!" end endif if number > guess then printr
"The number is greater than " + guess else printr "The number is less than " + guess
endifnextprintrprintr "Out of guesses!"printr "The number was " + number

Worm
dim x, y, xd, yd, key, scorex = 20: y = 12xd = 0: yd = -1Color (0, 255, 0)while true key = InScanKey ()
if key = VK_LEFT and xd <> 1 then xd = -1: yd = 0 endif if key = VK_RIGHT and xd <> -1 then xd =
1: yd = 0 endif if key = VK_UP and yd <> 1 then xd = 0: yd = -1 endif if key = VK_DOWN and yd <>
-1 then xd = 0: yd = 1 endif x = x + xd y = y + yd score = score + 1 if CharAt$ (x, y) <> " " then Color
(255, 255, 255) locate 15, 11: print "Game Over!" locate 15, 13: print "You scored " + score end endif
locate x, y: print "X" Sleep (75)wend

Potrebbero piacerti anche