![]() |
ISSUE #15 - June 1999
Edited By David Groulx |
Tutorials | Modular Programming |
Structured Programming | |
Your Programs | Text Line |
Text Stars | |
QBasic Sprite Editor v0.21 | |
Misc & Credits | 2000 Website Awards |
Credits | |
Contact Info |
Contents:
2.0 The basics of modular
programming
2.1 Subs
2.2 Functions
2.3 Where to use SUBs and
FUNCTIONs
3.0 Going into the details
of subs
3.1 Getting data into modules
3.2 Global Variables
3.3 Module Interface
3.4 Commands you can't
use in a sub
4.0 Going into the details
of Functions
4.1 Using functions for
calculations
1.0 Introduction
When writing large programs in QBasic,
it is vital for the debugging process that the flow of the program can
be understood easily. If GOTO and GOSUB is used a lot, the program acquires
a spaghettilike structure, making it extremely hard to track down and remove
bugs in the source. This is why modular programming is such a good idea.
This particular method of programming lets you divide your program into
smaller tasks that can be solved individually, creating an easy-to-read
source code, that also takes less time to debug.
2.0 The basics of
modular programming
First of all, a module is a chunk of code
within a program that performs a specific task, and typically has a name
that describes that task. A module that collects input from the user should
therefore be called "GetInput" or something along those lines, but all
valid variablenames can be used. Giving the module a descriptive name does
however make it easier for yourself and other people to understand the
source. There are two types of modules: SUBs and FUNCTIONs. These two terms
will be used throughout the tutorial, so here's a brief description of
them:
2.1 Subs
SUB is short for 'Subroutine'. A SUB may
contain most QBasic statements, although some statements may be used only
in the main code. SUBs are useful when you need several lines of code to
complete a single task, for example when printing help-screens for the
user, or creating windows. All variables used in a SUB are local, which
means they start at 0 or null every time the SUB is called, unless they
are dimensioned as global variables in the main code (more on this later).
You can also pass variables from the main code to the SUB, or define the
SUB as STATIC, which means the variables are not reset when control is
passed back to the main code. Don't worry if you don't understand the above
at this point, everything will be explained in detail later.
2.2 Functions
Functions are just that. They are used
in the same manner as 'built-in' QBasic functions such as RND (random number),
SQR (square root) or LEN (length of a string). In general, if you can type
Variable = FunctionName(arguments) and get away with it, it's a function.
This is where FUNCTIONs are different from SUBs, a sub is called like a
normal QBasic statement, and functions are either assigned a variable (a%
= FunctionName) or used to determine the outcome of a true/false expression
(IF YesNo$ = "N" THEN...)
2.3 Where to use SUBs
and FUNCTIONs
Subs and functions may appear alike, but
their uses are completely different. The following paragraph should give
you some idea of when to use subs and when to use functions. A sub is best
suited for a routine that requires little interaction with the main code,
meaning that the outcome of any calculation in the sub shouldn't bear any
significance to the main module. Functions on the other hand often provide
a new value to a variable in the main code, and are therefore best suited
for long or complicated calculations. In short, use subs for long routines
and functions for long calculations.
3.0 Going into the
details of SUBs
A new sub is created by typing 'SUB SubName'
whereafter you get a blank screen with the words 'SUB SubName' and 'END
SUB'. The statements in your module go between these two lines of code.
It is considered good programming practice to add a few comment lines to
the top of the sub describing what it does and what variables from the
main code are used and/or changed.
3.1 Getting data into
modules
As mentioned before, all variables used
in subs and functions are local to the module, which means they are reset
when command is passed back to the main code, unless the sub is defined
as STATIC. If you want to use variables/strings from your main code in
the module, you have two options: Global variables or the module interface.
3.2 Global Variables
If a variable or string is defined as
global, it can be used and changed in all levels of the program (in all
modules). This kind of variable is essential for large programs that use
many variables for controlling the programflow. A global variable is defined
in the main code with the following statement:
DIM SHARED Varible, Variable1..... AS TypeA, Variable2 AS TypeB
Where Type is the type of variable you are currently defining, e.g. Integer, String, Single-precision etc. (See the QBasic help for more info on variable types). When using global variables you are also forced to plan your program ahead before typing the actual code. This often makes the result of your efforts much better, as your code will be efficient and easily readable if you have planned it properly. Constants defined with the CONST ConstName = Value% statement are also global and may be used in all subs and functions without any bother.
3.3 Module Interface
An alternative to global variables is
using the module interface. This has advantages over global variables in
some cases, but naturally it is also inferior on some points. If you are
writing a sub that performs a task based on the data passed to it from
the main code, a box drawing routine for example, you would use the module
interface for data-interchange. This way you could get away with typing
something like 'DrawBox (1, 1, 20, 20)' instead of having to give four
global variables a new value and then calling the sub. The module interface
is created by adding a set of paranthesis () to the 'SUB SubName' statement:
SUB SubName (Variable%, String$)
It is now possible to pass two variables to the module (an integer and a string), by typing
SubName a%, s$
In the sub, the variables a% and s$ will be known as Variable% and String$ as stated in the SUB SubName statement. You can have any amount of variables of any kind passed to a module. This does mean however, that every time the module is called, the correct number of arguments must be passed to it. This is partly where this method is inferior to global variables. When calling a sub with arguments, you must make sure that you type the arguments in the correct order, according to the declaration of the sub, and that the arguments passed are of the right datatype (integer, string etc).
3.4 Commands you can't
use in a sub
There are certain commands and statements
that won't work within a module. This doesn't mean that there are some
tasks that can't be solved with modules, just that you need to add a little
extra code to your main program. The most commonly used statements that
aren't allowed in modules are as follows:
CONST
- For defining global constants
DIM SHARED
- For defining global variables
DECLARE SUB / FUNCTION - For initiating a module in
a program
DATA
- Data statements can only be put in the main code
You might very well encounter other statements and commands that are illegal in modules, just try moving them into the main code.
4.0 Going into the
details of Functions
A function is created in the same manner
as a sub, by typing the following statement: FUNCTION FunctionName (ArgumentList%)
Same as before, you now have a blank screen with the name of the function
and the END FUNCTION statement. There are two main uses for functions.
The first is calculating a new value based on the arguments passed to the
function in the arguments list, the second is reading or calculating a
new value based on input from the user or gathered from an input device.
4.1 Using functions
for calculations
This is really practical if you need a
fixed number of operations done on a variable from the main code. You could
have a function that converted a string input from the user to all uppercase,
no commas and no left/right spaces. This could be useful in a text-adventure
for example. You would do this by typing the formatting code into your
function module, using the name of the module as your stringname:
FUNCTION ConvString$(Text$)
ConvString$ = UCASE$(ConvString$)
' Convert to uppercase
ConvString$ = LTRIM$(RTRIM$(ConvString$))
' Remove left/right spaces
.....
END FUNCTION
In the main code you would put something like
INPUT Text$
Text$ = ConvString$(Text$)
Whereafter your string Text$ will be changed to whatever your sub does to it. It saves a lot of space in the main module, and makes it easier to read.
4.2 Using functions
for getting new values
A function may also be used to create
a new variable. This means that the function collects input from the keyboard
or another input device, and gives it to the variable in question. For
example, if we wanted to create a function that waited for a single keypress
from the user, printed it on the screen, and passed control back to the
main program, we would have something like this:
FUNCTION GetChar$
DO
' Start reading-loop
Temp$ = INKEY$
' Read the keyboard
LOOP UNTIL Temp$ <> ""
' Loop until key pressed
PRINT Temp$
' Print the character on screen
GetChar$ = Temp$
' Pass the value to the main program
END FUNCTION
And in the main code:
KeyPress$ = GetChar$
Again, this drastically shortens our code and makes it easier to get a single character from the user. (Strictly, the above example is obselete as it could be substituted with the INPUT$ function) It is vital that you include the line 'FunctionName = Value' at some point in the function, otherwise the main program will recieve the value 0 or null from the function. In the example we have put GetChar$ = Temp$ to pass the value of Temp$ to the main program.
5.0 Summary
We have (hopefully) learnt that modular
programming has many advantages over normal programming, the biggest being
the improved readability of the source code. In reality, all there is to
modular programming is deviding your program into tasks and figuring out
the best way to interchange data between the modules. Modules are written
in the same manner as normal QBasic programs, although some statements
are illegal in modules (you'll know when you try to use them).
6.0 Closing words
I hope this tutorial has given you some
ideas for structuring your programs in a functional way, modular programming
really is the most important aspect of structured programming. I encourage
you to use modules in your programs, as you will probably be able to use
some of them again in later projects. Eventually you will have built up
your own set of QBasic commands to be used over and over again, saving
you precious time and letting you concentrate on the important parts of
your program. Thank you for reading this tutorial.
Suggested reading: Structured Programming
1.0 Introduction
There is more to good programming than
learning the keywords and commands of a language like QBasic, there is
also a more abstract aspect known as Structured Programming. If you want
to write long and complicated code that does more than print "Hello World!"
on the screen, the spaghettistructure of old fashioned BASIC just won't
cut it anymore. People who have been mucking about with GWBASIC and BASICA
will know what I mean, but the days of line numbering are over, say hello
to Structured Programming!
QBasic is the prime version of BASIC and gives us quite a few advantages over previous releases. For example, the source editor now consists of a user- friendly text editor with many functions, a great modular level interface and extensive on-line help. So why not use all this great stuff to it's full extent? This tutorial will help you take advantage of the many features QBasic offers to programmers today, so read on...
1.1 the project
During this tutorial a simple address
database program will be constructed step by step. With each step the necessary
keywords and statements will be introduced and explained, hopefully giving
you a better picture of just how everything works in reality. Thanks to
Larry (nonnypa@gte.net) for suggesting
This approach.
2.0 The backbone of structured programming
One of the major elements of structured
programming is planning your program before you actually write it, e.g.
you know in advance roughly what your program will do, which variables
and datastructures it will use, and what the outcome will be. Starting
to write a program without having at least considered how it will work
will often result in disasterous code.
Let's take a brief look at what our database program will contain:
'{ Initialize Datatype }
'{ Allocate memory for records }
'{ Open random access file for read/write }
'
' Option 'Browse Records/Enter new record'
'
' Procedure 'Browse Records'
' { Get records from file }
' { Display records }
' end procedure
'
' Procedure 'Enter new record'
' { Get input for new record }
' { Append record to file }
' end procedure
'
'{ End program }
Make any sense? It should do, it's just a plain English version of the QBasic program still to be written. We will use the above code in the example source code (SPEX10.BAS) for the address database. Concluding this short chapter, pseudo code can and should be used to create the framework of your program before you indulge in the code writing process. It lets you maintain a constant overview of your program, helps you target your concentration on one task and gives you something to stick to when everything goes wrong (and it will). In short, use it!
3.0 Creating userdefined datatypes
What is a datatype? Datatypes are things
like Integers (16-bit numbers), Long Integers (32-bit numbers), Single
Precision digits etc, in general just types of data. If you are working
with arrays (stacks) of conventional data, you will only be able to manipulate
one array at a time, for example:
A%(2) = A%(1)
B%(2) = B%(1)
C%(2) = C%(1)
etc...
A bit unhandy if you have more than 2 or 3 arrays to manipulate. The is where userdefined datatypes enters the scene. These datatypes can contain several different kinds of datatypes all in one element, letting you easily handle stacks of data:
TYPE variables
A AS INTEGER
B AS INTEGER
C AS INTEGER
END TYPE
DIM TestArray AS variables
TestArray(2) = TestArray(1)
The last line of code performed the exact same action as the 3 lines of code in the previous example, pretty slick huh? This can save you a LOT of time and bother and will even make your code look much neater. Building a usertype like this involves three steps: finding out what kind of data you need, making a type for it and allocating memory for that type. Pretty simple. The TYPE statement that defines the usertype works like this:
TYPE TypeName
Element1 AS Type
Element2 AS Type
.....
END TYPE
TYPE is the actual QBasic statement, followed
by the name of the datatype you're creating. Next comes a list of all the
elements in your datatype, these elements can be:
INTEGER | A 16-bit signed integer variable |
LONG | A 32-bit signed integer variable. |
SINGLE | A single-precision 32-bit floating-point variable. |
DOUBLE | A double-precision 64-bit floating-point variable. |
STRING | n% A fixed-length string variable n% bytes long. |
And yes, you can have different types of data in your type, all types of data will fit together in one type, great eh? This feature of QBasic can be handy in a lot of situations that require moving and rearranging large amounts of data, like in our database program. So guess what? We're going to create a usertype for our database right now. As it's an adress database we will of course want to store a persons name, addresse, city/state and an optional phone number. Our datatype:
TYPE RecordType
Names AS STRING * 25
Address AS STRING * 25
City AS STRING * 25
PhoneNr AS STRING * 10
END TYPE
We could also have added other elements such as Integers for peoples ages, but since most of your friends probably won't tell you how old they are we'll leave this one out. So now we have a usertype for all our addresses. Next step is to allocate data for the usertype. It's not a variable until we take this step. We use the DIM statement for this (most people think DIM is only for arrays, don't listen to them):
DIM Record AS RecordType
And voila! We now have a fully functional variable called Record to use in our program, but the smart-alec reader will have noticed that we have four elements in a variable with only one name. Correct, to get around this we add a period (.) after Record followed by the name of the field we want to access, and we have a regular variable: Record.Names is the name of the first field, Record.Address is the second etc. That's all there is to know about usertypes. You will notice when reading the source code of the example program (SPEX10.BAS) that a whole record holding a persons name, address, city and phone number can be written to a random access file with one statement, beats using conventional arrays doesn't it?
4.0 Using loops
Loops stick the routines of your source
together to a working program. It is important to learn how to handle these
loops in an efficient manner, as well-structured loops make your program
work better. There are several kinds of loops available to us in QBasic,
most of which you probably know about already, but following this I will
try to explain the in's and out's of all the looping techniques you need
in your programs.
4.1 DO .... LOOP
This looping method wasn't possible in
early versions of BASIC that required line numbers, so it is a fairly new
addition to the language. This kind of loop lets you handle conditional
jumps in a very efficient manner, as you can either add your condition
to the DO or the LOOP statement. This first example checks the status of
the keyboard string before it even starts the loop, so the loop may not
even be executed once if a key has been pressed prior to the routine:
DO UNTIL INKEY$ <> ""
PRINT "No key pressed"
LOOP
On the other hand, if you need your loop executed at least once you can add the condition to the LOOP statement:
DO
PRINT "No key pressed"
LOOP UNTIL INKEY$ <> ""
Get the general picture? This is however not the only way of using the DO...LOOP method, you can also use boolean (true/false) operators to control your condition. Inserting AND between conditions will only interfere with the loop if all the conditions are true (non-zero), using OR will react when either one of your conditions is true:
DO UNTIL INKEY$ <> "" AND A% > 0
- This will exit the loop only when
both
conditions after the UNTIL
keyword are
true (non-zero)
DO UNTIL INKEY$ <> "" OR A% > 0
- This will exit the loop when either
one
of the statements are true.
There is another keyword you can add to your condition, which is NOT. This word reverses the meaning of the following boolean statement... confused? I know I am, but let's try with an example:
DO UNTIL NOT INKEY$ <> ""
This breaks the loop when a key IS NOT pressed, e.g. when the conditional statement is false rather than true. You can use several NOTs in your condition:
DO UNTIL NOT INKEY$ <> "" AND NOT A% > 0
This will break the loop if no key is pressed and the variable a% is less than or equal to zero. Alternatively, you can completely leave out the condition at the front or end of the loop, and use EXIT DO within the loop to terminate the routine:
DO
IF INKEY$ <> "" THEN EXIT DO
PRINT "No key pressed"
LOOP
I know all this must sound confusing, but then again you're not supposed to learn everything from this tutorial. Once you have tried using the different loops and conditions it will all make perfect sense to you, I promise.
4.2 FOR ... NEXT
Most people starting off in QBasic have
made that great program that prints your name all over the screen 100 times,
haven't you? If you did you probably used a FOR ... NEXT loop, which is
what we'll discuss here. This kind of loop is what you use when you need
a routine executed a fixed amount of times (e.g. printing your name all
over the screen). The syntax is very simple:
FOR Variable% = LowerBound TO UpperBound [STEP Difference]
....
NEXT Variable%
Variable% is the variable that will be increased or decreased every time the interpreter reaches the NEXT statement. Simple eh? For the names program it works like this:
FOR a% = 1 TO 100
PRINT "Your Name Here"
NEXT a%
This example doesn't actually use the variable a% in it's operation, so it's not necessary to do anything fancy like STEPping. The routine will just loop one hundred times and pass control to the next statement. If, on the other hand, you want to use this loop for something constructive, you might need to use the STEP keyword. This let's you increase the variable by more than one at every loop, or even make the counting go backwards. Let's say we want to print a dot at every fifth position on the screen:
FOR Dot% = 1 TO 80 STEP 5
LOCATE 1, Dot%
PRINT "."
NEXT Dot%
That example is of course completely useless, but illustrates how to use the STEP keyword. If you want to decrease your variable on every count, STEP must be followed by a negative number and the low bound must be greater than the high bound, for example...
FOR Dot% = 80 TO 1 STEP -5
LOCATE 1, Dot%
PRINT "."
NEXT Dot%
Another useless example that just prints the same dots on the screen starting from the right instead of the left. But what if you want to fill the whole screen with dots? Unlikely, but let's say you do. Writing 25 statements, one for each row, would take some time to accomplish, which is why we can do nested loops:
FOR Row% = 1 TO 25
FOR Col% = 1 TO 80
LOCATE Row%, Col%
PRINT "."
NEXT Col%
Next Row%
This would execute the inner loop 25 times, one time for each row on the screen. Beats copying and pasting the loop 25 times eh? You can nest as many loops as you like, but keep in mind that QBasic can be rather slow in it's calculations. The two loops in the example alone cause the interpreter to loop a total of 25*80 = 2000 times, nesting an additional loop of 15 would make a total of 30.000 loops, and quite frankly that just wouldn't work. This is also a part of structured programming, avoiding unnecessary loops and moving time-critical operations outside of loops, but this will all come clear to you when you try to calculate a sine value 2000 times in a loop. (Ok, so we could have used the STRING$ statement instead of looping an additional 80 times, but it's just an example, right? :)
You may also have noticed that the examples have extra blank spaces on the left every time a new loop is started, this is not necessary but really makes your code much easier to read, and not doing this will generally cause programmers to frown at you, so make it a habbit!
5.0 Conditions and branching
Without conditions your program would
output the exact same data every time it was run, pretty boring, but fortunately
we have two methods of branching off to subroutines in our programs, making
them a little more fun to work with. Both methods have their advantages
and disadvantages, so consider which one you'll use in your program, it's
a part of structured programming!
5.1 IF .... THEN logic
You may have worked with this kind of
condiditional branching previously, it is quite simple and effective. Basically,
using IF THEN logic will cause your program to branch off to a subroutine
when a condition is met, and another if the condition is not met. This
is IF THEN in it's simplest form, and works like this:
IF Condition THEN .......
The condition works the same way as in DO LOOP loops (chapter 4.1). If the condition is met, the statement after the THEN keyword is executed. Simple. But what if it is not met? We could add a subsequent IF THEN statement with the opposite condition, telling the program what to do in that case. Or even better we can add the ELSE keyword to the existing statement:
IF Condition THEN ......... ELSE ......
The statement after the ELSE keyword will be executed if the condition is not met. Now only one problem remains, what if we want to branch off to an entire subroutine instead of just one statement? For this we have block IF THEN's:
IF Condition1 THEN
......
ELSEIF Condition2
......
ELSE
......
END IF
These work basically the same way as the basic IF THEN statement, except you can type several lines of code for each condition. The ELSEIF keyword lets you specify multiple conditions in the same IF THEN block, handy for things like menuhandling:
IF Choice% = 1 THEN
{ Subroutine for #1 here }
ELSEIF Choice% = 2 THEN
{ Subroutine for #2 here }
ELSEIF .......
ELSE
{ Subroutine for invalid choice here }
END IF
This brings us on to the next conditional jump method, CASE....
5.2 SELECT CASE
This is the modern and trendy version
of IF THEN statements. This method offers some advantages over IF THEN
as you will discover in a short while. The syntax for SELECT CASE is:
SELECT CASE Variable%
CASE Comparison1%
.......
.......
CASE Comparison2%
.......
.......
CASE ELSE
.......
.......
END SELECT
Variable% is of course the variable you will be handling in your conditions. After each CASE keyword, a string or variable is placed that is compared to the Variable%. If these two match, the routine after the CASE keyword is executed. You can even specify several matches for the same routine, for example you could make "A" and "a" do the same thing, which would also be pretty handy for a letter-operated menusystem. This is done by seperating the comparison variables with commas:
CASE "A", "a"
.......
Pretty simple too when you get the hang of it. Again, additional spaces have been added to the left of the CASE keywords to make the code easy to read and understand. SELECT CASE is typically used when there are several possible subroutines that can be branched off to, it's simply more convenient than a huge block of IF THEN's. And convenience is what we're looking for.
6.0 Your comments please
Everybody knows what they are, but nobody
uses them when they should. The use of comments in your source can really
speed up the understanding of the code. At a glance you can see what all
your routines do without having to understand all the calculations and
variables used within, pretty slick eh? But then again we don't want to
overdo it, placing a comment after a PRINT statement saying 'This prints
the text blablabla to the screen' is just a waste of time. On the other
hand, the following statement might need some explaining:
a = (SIN(A1) * c) / SIN(C1)
When confronted with a statement like this you'd have to look back in the program to find out what the variables represent, and then take a look at the calculation itself to find out what the program is doing to them. Adding a few comments, however, might ease the pain a little...
' Following routine calculates the side A of a triangle ABC, using
' the side c and the angles A1 and C1. Angles A1 and C1 are 124
and 10
' respectively, side c is 13...
a = (SIN(A1) * c) / SIN(C1) ' Calculate size of side a
The example wouldn't have been too hard to figure out without comments, but routines consisting of several pages of code tend to get a bit harder, so use comments when something needs explaining, other programmers will respect you for it.
7.0 Name your Variables
This is a very short but important chapter.
As you might have guessed, it's all about naming your variables in a way
that makes your code easier to understand to yourself and others. We get
to use as many characters as we like (almost) in our variable names, but
too much of anything isn't good for the baby, the variable MainLoopIterationCounter
is a legal variable, but it takes time to type and is prone to misspelling.
You get the idea. Something like MainLoop would be sufficient and understandable.
You can also add little signs to the end
of your variables indicating what type of variables they are. As mentioned
earlier, there are five types of variables, and five corresponding signs:
Integers | % |
Long Integers | & |
Single Precision | ! |
Double Precision | # |
Strings | $ |
So, the variable a% is an integer, a! a long integer etc. etc. Using these signs saves memory and can make program execution faster, so by all means get used to it, it's a good programming habit.
8.0 Closing words
Naturally you won't be a perfect programmer
after reading this, it takes days and weeks and months to learn how to
structure your programs in the most convenient manner, but throughout the
document you've been introduced to several important techniques and methods
that could make programming easier and a lot more fun in the future. I
hope you enjoyed reading this as much as I enjoyed typing it, please feel
free to contact me if you have any questions regarding anything with QBasic
on dtordrup@mail1.stofanet.dk.
Thanks to Larry (nonnypa@gte.net)
for helping out with the testing of this tutorial, without his advice and
constructive criticism it would be even more confusing than it is now ;)
Suggested reading: Modular Programming
Getting help
Pressing F1 at any time will bring up
context sensitive help!
Changing colors
Pressing F2 will let you change the color
you are currently using. Use the arrow keys to highlight the desired color,
and press ENTER to activate it. When you return to the editor all tools
will output the new color.
Selecting tools
Use the arrow keys to move the cursor
in the editing window, and press SPACE or ENTER to activate the drawing
tool currently selected. The available tools are displayed in a column
to the right of the editing window, with the active tool highlighted. To
change tools press F3, and select your new tool with the Up/Down arrow
keys followed by ENTER.
Naming your file
Your sprite will be saved under the DOS
filename stated above the editing window. The default name is 'NONAME00.GFX'.
This can be changed by pressing F4 and typing in the new filename. The
extension does not have to be GFX, any valid filename will do.
Saving the sprite to disk
Once you have finished drawing your sprite,
you can save it by pressing F5. The sprite is saved under the filename
stated above the editing window. Any files with the same name as your sprite
will be overwritten! All sprites will be placed in the same directory as
the editor itself.
Loading a sprite from disk
To continue work on a previously created
sprite, press F6 and type in the filename for the sprite. The sprite will
be placed in the centre of the editing window. Sprites over 115 x 100 pixels
in size can not be loaded into the editor.
DIM Array%(Size_goes_here) ' Dimension an array for the sprite
DEF SEG = VARSEG(Array%(0)) ' Start loading data at Array%(0)
BLOAD "FILENAME.EXT", 0 ' Load file at offset 0
PUT (1, 1), Array%
' Put the sprite on the screen
' to show that it works (leave out)
Use the above routine for all the sprites you need to load, just remember to use individual names for the arrays. If you want to have multiple sprites in one array, remember to change the index of the array in the DEF SEG statement before you BLOAD again.
Suggested reading: "GETting and PUTting in QBasic" in Issue 14 of The Basix Fanzine
Nominated your favourite BASIC site
You can vote for your favourite webpage or nominated on on the Basix Fanzine homepage.
David Tordrup | http://www.cybernet.dk/users/dtordrup/qbzone/ |
Buzz | http://huizen.ddsw.nl/bewoners/buzz/ |
ARTICLES | Basix_Fanzine@yahoo.com |
OTHER INQUIRIES ETC | Basix_Fanzine@yahoo.com |
WWW ADDRESS | http://www.come.to/basixfanzine |
To join send an email to "Basix Fanzine" <ListProcessor@mindspring.com> with the subject "SUBSCRIBE".
To unsubscribe send an email to "Basix Fanzine" <ListProcessor@mindspring.com> with the subject "UNSUBSCRIBE".
As always I am always looking for articles, tutorials, comments, newsgroup articles, etc to put in the Basix Fanzine. Please send them in.