Note on this tutorial

I wrote this tutorial many years ago (2001-2002). Because of the large number of links pointing to it I've left it up. However, I no longer support it. Please do not contact me asking for help with QBASIC, ASM, or other programming issues. Also, please do not contact me about minor errors in the text: the text of this tutorial is mostly unedited, and only the presentation and markup have been significantly updated (to valid XHTML 1.0 strict). If there are major errors which significantly interfere with readability, though, please feel free to bring them to my attention - Billy Wenge-Murphy
This tutorial is (c) 2001-2007 Billy Wenge-Murphy. All rights reserved. It may not be copied, reproduced, or redistributed in any form without permission. If you wish to share it, please link to it instead of reposting it.

2.1 - Graphics

Let's diverge for a while into a very important topic in programming. If you want to design games, as this tutorial uses what you learn to show you how to do, graphics will be a big part.

There's a whole lot of graphics commands in BASIC. Let's first cover the basic ones. You'll probably toss them out later in favor of sprites, tiles, and other such advanced techniques, but it's a good start.
Here's what we'll cover here:

SCREEN (a different command with different syntax but the same name)
LINE
CIRCLE
PAINT
DRAW
PSET

So far we've only put text on the screen. But you can put graphics on the screen too. However, if you didn't get locate, go back and review - there will be a lot of stuff with coordinates. In fact, graphics are all about coordinates!

You may know already that computer screens (as well as TVs) draw a picture with little dots of color called pixels. If you're just dying to know, pixel is short for PICture ELement, (and i guess somehow that C becomes and X when they're put together).
With the locate statement, we can make pictures like the maze out of text. But if we could make a picture with even more tiny parts to it, it would look better. The amount of pixels a picture has is called its resolution (sometimes people say res or rez for short)
For example, take an impressionist painting made out of single dots. With thousands of little dots close together, it looks like a picture. The more dots we cram into it, the better it looks - and the harder it is to see every little dot.
So, depending on how high a resolution you want, BASIC has different screen modes. Each one has a different amount of dots across and down, therefore, it has a different resolution. Just like with some commands we've already encountered, each screen mode has a code number. We'll use screen #12 - or screen 12. So, how do we tell BASIC to change the screen to this mode? With the screen command. As simple as this:

SCREEN 12

Yes, this is a different command than the SCREEN () you're already familiar with.
Screen 12 is BASIC's highest resolution screen. You have 640 dots across, and 480 down, to draw with. That's about 300,000 dots in total! So, let's look at our first graphics command, LINE.
It's kind of like locate, but it has a different range of coordinates allowed, and needs 2 sets of numbers - of course, since it draws a line; a line must start somewhere, and go somewhere. Also, you give it what color you want the line to be. For example:

LINE (0,0) - (639,0), 1

Will draw a line blue across the top of the screen. Or this:

LINE (0,0)-(0,479), 2

makes a green line down the left side. Line has another special thing about it though. It makes boxes too! If you want a box, write B after the color:

LINE (0,0)-(10,90),5,B

will make a tall purple rectangle in the upper left corner of the screen. However, this is an empty box. If you say BF rather than just B it will make a solid box (in this case, it would be a solid purple rectangle in the upper left corner instead)

That's covered pretty well. Next command:

Circle

Circle needs at least 4 parameters. Where to put it (an x & y), a size (or radius), and a color. Like so:

CIRCLE (320, 240), 10, 4
CIRCLE (320, 240), 50, 3

You should see a little red circle in about the center of the screen, with a much bigger light blue circle around it. Pretty simple, so let's move on. Now for

Paint

Paint can sometimes be tricky to get it to do what you want. What paint does is starts from where you tell it, and paints inside something. But, you have to tell it what color to stop painting at. So, you give it a color, and a border color (the color where it should stop painting). This way you can paint solid inside of figures, like circles you just learned about. Or, inside hollow boxes, if you don't want the inside to be the same color as the border. Take a look at this:

CIRCLE (320,240), 25, 4
PAINT (320,240), 15, 4

Here's a red circle in the middle of the screen again [this time a little bigger], and we'll paint the inside white. Now try changing the 4 in the paint statement only to something else.... It paints the whole screen white! Because it didn't hit whatever color you told it (since it wasn't there) and just kept right on painting.
I don't know what more i can say about this command. Have fun with what you know, experiment around with things.

Now for the last two commands that kind of go together. First let's start with

DRAW

Most programmers despise this command, and think it's a terrible waste to even learn. I sort of agree; about despising it, i mean. It's just something very cumbersome and tedious, but you can have fun messing around with it, and it's an easy way to draw complex graphics from the start. Draw goes like this: You give it a string of different things to to and it draws them. It has little commands of its own in a way. Here's a partial list:

B   move, no line  N   line, no move
Un  Up             Dn  Down            Ln  Left             Rn  Right
En  Up and right   Fn  Down and right  Gn  Down and left    Hn  Up and left

The little n by something means you put a number there. That's how many pixels you want to draw in that direction. Let's see a few examples of how draw works:

DRAW "R50 D50 L50 U50"

You're telling draw to go right for 50 pixels, then go down for 50 pixels, the left 50, then up 50. Congrats! You made a square!. How about this:

DRAW "e10 f10 g10 h10"

You go up and left, then down and right, then down and left, then up and left, 10 pixels each time. You've now made a diamond!
Now let's change slightly what we did earlier:

DRAW "nr50 nd50 nl50 nu50"

perhaps you're saying it will draw a square again. No... - why? Notice N says "Line, no move". That means it will draw something in that direction, then go back to where it was to draw the next thing. Actually, it will draw more of a cross. If you put n in front of each part of the second example, you get an x. Without B and N, the draw statement is much like an Etch-A-Sketch.
B is like the opposite of N - instead of drawing without moving, you move without drawing. So this:

DRAW "r10 br10 r10 br10 r10 br10"

Will give you dashed line. Draw 10, move silently along for 10, draw 10..... and so on.

Our final command for this section helps you out with DRAW

PSET

It's short for "Pointer SET". You'll notice that when you use draw, it's in the upper left corner to start. That's the default position of the imaginary pointer that tells basic where to draw at. You can tell it to go somewhere else on the screen by using PSET. For example, if you want to go to the other corner:

PSET (639, 479)

then maybe you want to go back to the upper left again:

PSET (0,0)

One tiny thing you should notice. PSET makes a dot on the screen at the point you tell it to go to. This will be very handy later.

2.2 - Handling lots of data - Arrays

At this point is gets harder to make an even, flowing progression. So, I'll try to show you important parts of the language, however, they're not necessarily woven interconnectingly.

This section will cover, like it says, how to handle big amounts of data. For example, a variable only holds 1 type of data, and only 1 thing. Now that's about to change as we discuss arrays: they're like a bunch of variables rolled into one. For example, a simple program to find average, without the use of arrays:

PRINT "Enter 4 numbers, I'll find their average"

INPUT a
INPUT b
INPUT c
INPUT d
average = (a+b+c+d) / 4
PRINT "Their average is "; average

( the slash / means to divide)

That's great and all, but it's not very flexible. Say perhaps you wanted the program to be able to find the average of 50 numbers; You'd have to modify the program so that it had 50 variables, add them al together, and divided them by 50. Or even worse, what if you wanted to modify it for up to 50 numbers - you'd have to ask them how many numbers there were putting in, it would have lots of IFs, and be generally of poor quality.
Arrays solve the problem of storing and retrieving lots of numbers with little code and effort. That's because they go hand-in-hand with For...Next loops. To start, here's a program that just gets 50 numbers - it doesn't average them... yet:


DIM numbers(50)

PRINT "Enter 50 numbers. Enter -1 to stop"
FOR a = 1 to 50
INPUT n
IF n <> -1 THEN numbers(a) = n ELSE EXIT FOR
next a

Like always, i threw in a new command, which you probably guess has something to do with arrays. The DIM command makes an array. Unlike variables, which you don't have to "make" before you use them (although you can, and it's a really good habit to do so) you do have to with arrays (the correct term is declare, rather than "make"). You say DIM arrayname() with some number in the parenthesis. This is how high you want your array to go. Your array holds 50 things in this case, and each one is numbered. Then, treat it just like a normal variable. This is perfectly legal:

numbers(1) = 12
numbers(6) = x + y - 5

and so on - anything you could do with normal numeric variables. Since each part of the array is numbered, they work really well with loops as was mentioned.

To break down our program: First, it makes an array, which holds up to 50 things. Then it tells you to enter up to 50 numbers, and type in -1 to stop. It gets the number from you, then checks it to see if you want to stop. If not, it actually puts it into the array. Yes, you COULD do this:

INPUT numbers(a)
IF numbers(a) = -1 THEN EXIT FOR

but then when they do -1 to stop, -1 will get recorded before it breaks out of the loop.

Now let's average them, which isn't too hard. Add this to the end of the program:

FOR b = 1 TO a - 1
sum = sum + numbers(b)
NEXT b

average = sum / (a - 1)
PRINT "The average is: "; average

Just to clarify, why a-1? Since a holds how many times we looped when entering numbers, we use it to determine how many numbers go into the average. But remember they have to enter a number to get out of the loop too - that number doesn't factor in. So, if they entered 2 numbers, then entered -1 to get out, we'd have looped 3 times. So, a-1 tells us how many numbers actually figure into the average.

Now to break down the second part: After all the numbers are entered, we have another loop with a different variable go back an add them all together. Then we find the average by taking the sum and dividing (the slash means divide) by how many numbers there were, then print it out.

In summary, you can see arrays are good for storing a bunch of numbers that are all for the same thing. They also happen to go well with For... Next loops. However, let's take a look at another thing they go well with:

DATA statements

DATA statements are in themselves inert. You just put them in your program, and they hold data. What they hold can't be changed from within the program - you want them changed? you do it by hand! Basically, they're not like arrays and variables, because they don't hold data quite the same and can't be changed by your program. A quick example; be aware of these things involved with DATA statements:

RESTORE
READ
DATA
Line labels

This program tells you what day of the week (The first day, second day, third day, etc) it is, by you giving it the name of the day it is (sunday, monday....):

DIM daynames(7) as string

RESTORE daynameslist
FOR a = 1 TO 7
READ daynames(a)
NEXT a

PRINT "Enter the day, in ALL caps."
PRINT "For example, WEDNESDAY not Wednesday"
INPUT dayname$

FOR a = 1 TO 7
IF daynames(a) = dayname$ THEN PRINT "It is day number "; a ; " today!"
NEXT a

daynameslist:
DATA SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY

See, data records a bunch of stuff within the program and lets us look at it. It doesn't DO anything, in a sense. Notice

daynameslist:

before it, and that there's a line that says

RESTORE daynameslist.

Yes, these two are definitely connected. Suppose you had more than one chunk of data - you're gonna want to look at one at a time obviously. By putting a label (followed with a colon!!!!) you give your data a name. Then with restore, you tell it that name, letting it know you want to look at the data with that name. Read reads the data. Each time you do read, it reads the next piece of data (each piece is separated by a comma, notice) unless you do a restore, where it goes back to the start of the data. When it reads it, it puts it in whatever variable you want it to - here i put it in an array, because if you can put it in a variable, you can put it in an array.

So, to step through this program. At the end, we have our data. Data usually goes at the end. We make an array to hold the daynames so we can look at them easily. Our loop reads them from the data. Now we're ready to do something. We ask the user what day it is - it's gotta be in all caps, because to basic SUNDAY = SUNDAY, but SuNDAY doesn't = SUNDAY. Then we look at all names, which we have in an array. If it sees the right day, it tells you the matching number. Okay, it's not the best example, but it gets the point across.

Why learn this? Mainly, because arrays are very very very important. But also, because arrays are very very very important. And lastly because they make doing complex graphics so much easier.

2.3 - Arrays and graphics: So happy together

SPRITES!

Finally, you have the background knowledge necessary to learn about sprites. What's a sprite you say? If you've ever played old video games, you've seen tons of them. They're the main part of a 2D video game, and are on occasion (with ugly results) used in 3D games. A sprite is any little picture made to be moved around. Here's a couple of sprites from super Nintendo games (bomberman actually)

Bomberman sprite Bomberman sprite

True, bomberman has tons of animations, all which are a separate picture, but bomberman is still considered 1 sprite, as is that little red thing...
As we know, computer graphics are made up of lots of tiny little dots. Rather than draw each of those dots, we can draw with commands like CIRCLE, LINE, etc.
But, as we have the need for more complex graphics, it becomes necessary to do just that - draw every little dot. That's essentially a sprite.
To start, let's jump right in and make a simple sprite. We'll do this by saving a dot-by-dot image in DATA statements. Of course the important piece of information you need to know about a dot is it's color. So we'll of course put the color number of each dot in the data statement.
A simple yellow smiley face. Take a look at this little program:

SCREEN 12
FOR y = 0 TO 15
 FOR x = 0 TO 7
  READ col
  PSET (x, y), col
 NEXT x
NEXT y

DATA 00,14,14,14,14,14,14,00
DATA 14,00,00,00,00,00,00,14
DATA 14,00,00,00,00,00,00,14
DATA 14,00,14,00,00,14,00,14
DATA 14,00,14,00,00,14,00,14
DATA 14,00,14,00,00,14,00,14
DATA 14,00,00,00,00,00,00,14
DATA 14,00,00,00,00,00,00,14
DATA 14,00,00,00,00,00,00,14
DATA 14,00,00,00,00,00,00,14
DATA 14,00,14,00,00,14,00,14
DATA 14,00,00,14,14,00,00,14
DATA 14,00,00,00,00,00,00,14
DATA 14,00,00,00,00,00,00,14
DATA 14,00,00,00,00,00,00,14
DATA 00,14,14,14,14,14,14,00

The data is the bulk of the program. It contains color numbers, either 00 (black), or 14 (yellow). They're arranged in such a way that if you were to take those color numbers and draw them as pixels rather than write them as #'s, they'd form an image of a smiley face.

Then look at the 2 loops. Our picture is made 8 pixels across and 16 down. Notice the inside loop draws 8 pixels. The outside loop makes it loop 16 times. So, this draws 16 lines of 8 pixels, the end result being our smiley face.

How do arrays fit into this as they were mentioned to. The answer - suppose you need to draw that smiley face over and over (to move it around, for example). Doing it this way, you'd need to RESTORE and READ every time you drew it. To make it easier and more efficient, you should just store all the numbers somewhere. As we know, arrays are great for storing a whole lot of numbers which you basically use for the same thing. A modified version of the program:

DIM Smiley(127)
FOR a = 0 to 127
 READ smiley(a)
Next a

SCREEN 12
FOR y = 0 TO 15
 FOR x = 0 TO 7
  PSET (x, y), smiley((8*y)+x)
 NEXT x
NEXT y

( * means 'times' or 'multiply')

You'll just have to take that (8*y)+x formula on faith for now.... An array is essentially 'one-dimensional', but the screen is two-dimensional, so we must convert between the two. This method is very slow, although not too noticeable with such a small sprite.

Let's add in the necessary code so we can move the face around. To clarify it, look back at the pac-man example:

DIM Smiley(127)
SCREEN 12
Smileyx = 0
Smileyy = 0

For a = 0 to 127
 READ smiley(a)
NEXT a

DO

 FOR y = 0 TO 15						'Draw smiley face
  FOR x = 0 TO 7
   PSET (smileyx + x, smileyy + y), smiley((8*y)+x)
  NEXT x
 NEXT y

 Do
  A$ = inkey$
 LOOP UNTIL a$ <> ""	'Wait until they hit a key

 LINE (smileyx, smileyy)-(smileyx+7, smileyy+15),0,bf 'Draw over old smiley before coords change
                                                      'and before new smiley is drawn

 IF a$ = "4" THEN smileyx = smileyx - 8           'Left
 IF A$ = "6" THEN smileyx = smileyx + 8           'Right
 IF a$ = "8" THEN smileyy = smileyy - 8           'Up
 IF a$ = "2" THEN smileyy = smileyy + 8           'Down

LOOP UNTIL a$ = CHR$(27)				'The ASCII code for 'escape' - quit when they hit it

Notice the change in in the PSET command. The coordinates are not simply (x,y). If you drew at x,y every time, the smiley would not move! however, if you add x to the smiley's x position, and y to the smiley's y position, the pic is drawn wherever the smiley's been moved to.
Just like in the pac-man example earlier, we must draw over the old picture before drawing a new one, otherwise there'd be a trail of smilies across the screen. This is what

LINE (smileyx, smileyy)-(smileyx+7, smileyy+15),0,bf

does. The rest of the program is pretty easy to figure out.

2.4 - Get/Put

I mentioned earlier that this method of drawing would be pretty slow with a large spryte. The more commands that have to be done, the longer the program takes.

The loop to draw the smiley loops 128 times total (8 on the inside * 16 on the outside). That not a lot, but it's not exactly efficient. Remember that it loops 128 times every time you hit a key. If your picture was say, 100 * 200, that would take considerably longer - 20,000 pset commands! But nonetheless it's often necessary to draw lots of graphics at once. For this reason, basic has the GET and PUT commands.
GET takes an rectangular area of the screen and copies it so it can be drawn again and again. Then, the PUT command draws what you copied with GET. The advantage is that GET and PUT are very fast (compared to doing a bunch of PSETs, anyway)
For an example, lets go back to our original smiley face program, that just draws the smiley face and add in GET and PUT commands:

SCREEN 12
DIM Smiley(127)
FOR y = 0 TO 15
 FOR x = 0 TO 7
  READ col
  PSET (x, y), col
 NEXT x
NEXT y

GET (0,0)-(7,15), smiley
PUT (320, 240), smiley

(again, i didn't include the DATA statements, in order to save space. Make sure you include them when you run the program for yourself)

Get works like this:

GET (x1, y1) - (x2, y2), arrayname

which means you give it starting coordinates (x1, y1) and ending coordinates (x2, y2), and it GETs an image from that area of the screen. Kind of like line when you made a box (with BF), this gets a rectangular area of the screen. It stores the image it gets in whatever array you specify. As a general rule i just use an array as big as how many pixels the image will have. However, this may be too much depending on what screen mode you use... Don't worry about this right now, it gets more technical than you care to know, i'm sure.

Once we have the image, we use put, which is very similar:

PUT (x, y), arrayname

This takes the image you stored with get from whatever array you tell it and puts it on the screen at coordinates x, y

Maybe you can see where i'm going with this: First we went over how to begin to make a game and started to talk about graphics. Then we digressed into other topics, and now we know how to do graphics even faster, and more efficient methods of storing/using them.
The next logical step is to apply our new knowledge of get and put to our game from before. Let's begin to put a pac-man game together. I choose pac-man because it's pretty simple, but complex enough to give us a lot of material to cover. don't limit yourself - take what you learn here and do what you want with it.

Now that we can use real graphics - not those sucky text.. erm "graphics" from before, let's use real graphics!
Let's make pac-man look like pac-man, and the pac-man maze look like a pac-man maze.

Yep, the tutorial ends abruptly right here. It was never finished and never will be. Sorry!
Mascot: Billy's Weird Cat Thing