The BASIX Fanzine


ISSUE #15 - June 1999

Edited By David Groulx


Contents


 
Tutorials Modular Programming
Structured Programming
Your Programs Text Line
Text Stars
QBasic Sprite Editor v0.21
Misc & Credits 2000 Website Awards
Credits
Contact Info


Tutorials


Modular Programming
 By David Tordrup


 

Contents:

1.0 Introduction

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

5.0 Summary

6.0 Closing words

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


Structured Programming
By David Tordrup

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:

As you can see, an overview of the final program makes everything look very simple and easily done. That's because it is, when you have a general plan of your program worked out offhand, the rest is just a matter of applying the correct QBasic commands and statements. To make this task even easier we use pseudo code. This is basically a detailed version of the above overview that let's us plan the structure of each individual routine in the program before we get down and dirty with the QBasic commands. Some programmers use a certain structure and layout for their pseudo code, the official pseudo code, but this is not at all necessary as long as you know what is going on in your preview. Consider the following code:

'{ 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


Your Programs



TEXT Programs
By Buzz

Text Line
Text Stars


QBasic Sprite Editor v0.21
By David Tordrup



From: qbse021.zip


Introduction

The QBasic Sprite Editor was written to aid programmers in easily creating and incorporating graphics into their programs. The editor is written in and for screen mode 7 (EGA), thus the graphics files ouput by the editor will only display correctly in this mode. Future editions may include options for other screen modes.


Using the editor

The editor is operated with the arrow keys and a number of function (F-xx) keys. A self-explanatory menu is displayed to the right of the editing window, describing the actions of the function keys.

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.


Handling output files

Once you've drawn your sprite and saved it to disk, you might want to know how to get it into your QBasic program. To do this, make a note of the size of the sprite (the window below the menu), dimension an array of
integers in your program in that size, and use BLOAD to load the sprite:

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.


Afterword


You are free to create whatever you wish with this program, but please give credit where credit is due. For more information on material by the QBasic Team, visit the website or send e-mail to dtordrup@mail1.stofanet.dk

Suggested reading: "GETting and PUTting in QBasic" in Issue 14 of The Basix Fanzine


Miscellaneous & Credits


2000 BASIC Website Award


I have yet to receive some submissions. Please send them in. Please note that sites with pirated software posted on there webpage are not eligible.

Nominated your favourite BASIC site

You can vote for your favourite webpage or nominated on on the Basix Fanzine homepage.


Credits


Thank you to those people who took time to send in articles for this issue. Those people who contributed are:
 
David Tordrup http://www.cybernet.dk/users/dtordrup/qbzone/
Buzz http://huizen.ddsw.nl/bewoners/buzz/


Contact Info


 
ARTICLES Basix_Fanzine@yahoo.com
OTHER INQUIRIES ETC Basix_Fanzine@yahoo.com
WWW ADDRESS http://www.come.to/basixfanzine


Mailing List


Currently there are around 165 people on the list. Please note that I assume no responsibility for any message that you receive or don't receive from being on the list.

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".


Next Issue

As always I am always looking for articles, tutorials, comments, newsgroup articles, etc to put in the Basix Fanzine. Please send them in.



Edited By David Groulx
Copyright © 1999 The Basix Fanzine