to PART 1
2.1 - Graphics
Let's diverege 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 statment, 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 thounsand 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.
This, however is an empty box. If you say BF
ranther 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
chaning 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, PSET, helps out with DRAW. 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 retreiving 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 aforementioned.
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 invloved 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 ususally 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 sooooo 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)
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
esentially 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 peice 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 esentially 'one-dimensional', but the screen is two-dimensional,
so we must convert between the two.
This method is very slow, although not too
noticable 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 smileys 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 copys 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 statments 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 alot 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.
to PART 1