The following information pertains to creating libraries using QuickBASIC 4.5. Earlier versions of QuickBASIC may also support libraries but no version of QBasic (that freebie interpreter that comes with MS-DOS 5.x to 6.x) does. If you are not using QuickBASIC 4.x, this information may not be very useful.
Okay, first off let's build a simple library using the functions found in FGRAPH.BAS
code file. This file contains the code for the DrawCircle and the
DrawLine procedures that we've went over before. Except with a small
twist to help illustrate a point.
' FGRAPH.BAS -- by Gary Neal, Jr. ' ' Draws Circles and Lines on the graphics screen using floating point math. ' ' Contains the value to increment the Circle's angle with. DIM SHARED angleIncr AS SINGLE ' DrawCircle ' Draws a circle on the graphics screen using floating point math. ' SUB DrawCircle (xOffset%, yOffset%, radius%, C%) DIM xPlot!, yPlot! ' Current pixel being plotted. DIM angle!, angleRad! ' Current angle in degrees & radiens. IF angleIncr < 1! THEN angleIncr = .5 FOR angle! = 0! TO 360! STEP angleIncr ' Convert degrees to radiens. angleRad! = angle! * (3.141592654# / 180!) ' Convert polar to rectangular coordinates. xPlot! = (radius% * COS(angleRad!)) + xOffset% yPlot! = (radius% * SIN(angleRad!)) + yOffset% ' Check boundaries. IF xPlot! < 0 THEN xPlot! = 0 ELSEIF xPlot! > 319 THEN xPlot! = 319 END IF IF yPlot! < 0 THEN yPlot! = 0 ELSEIF yPlot! > 199 THEN yPlot! = 199 END IF ' Plot the pixel on the graphics screen. PSET (xPlot!, yPlot!), C% NEXT angle! END SUB ' Line function ' ' Draws a line on the graphics screen using floating point math. ' SUB DrawLine (X1%, Y1%, X2%, Y2%, C%) DIM currX!, currY! ' Current pixel to be plotted DIM deltaX!, deltaY!, slope! ' 2 deltas and slope deltaX! = X2% - X1% ' Get value for delta X deltaY! = Y2% - Y1% ' Get value for delta Y IF ABS(deltaY!) > ABS(deltaX!) THEN ' |slope| > 1 IF Y2% < Y1% THEN SWAP Y2%, Y1% ' Swap coordinates SWAP X2%, X1% ' Y1 must be < Y2 END IF ' Compute the slope off the vertical axis slope! = deltaX! / deltaY! ' Plot each pixel starting at (X1, X2) currX! = X1% FOR currY! = Y1% TO Y2% PSET (currX!, currY!), C% ' Increment X by slope currX! = currX! + slope! NEXT currY! EXIT SUB ELSEIF deltaX! <> 0! OR deltaY! <> 0! THEN ' |slope| < 1 IF X2% < X1% THEN SWAP X2%, X1% ' Swap coordinates SWAP Y2%, Y1% ' X1 must be < X2 END IF ' Compute the slope off the horizontal axis slope! = deltaY! / deltaX! ' Plot each pixel starting at (X1, X2) currY! = Y1% FOR currX! = X1% TO X2% PSET (currX!, currY!), C% ' Increment X by slope currY! = currY! + slope! NEXT currX! EXIT SUB ELSE ' Set a single pixel because X1 = X2 and Y1 = Y2 PSET (X1%, X2%), C% END IF END SUB ' Returns the angleIncr value for other modules. ' FUNCTION GetAngleIncr! GetAngleIncr! = angleIncr END FUNCTION ' Sets the angleIncr value for other modules. ' SUB SetAngleIncr (newIncr AS SINGLE) IF newIncr > 0 THEN angleIncr = newIncr MOD 360 END IF END SUB
Okay, the first example on how we will reuse the code is to load it into QuickBASIC
as a second module. To do that, we must have some code that we plan to use as
a main module. In other words, our main program. This program, called
RANGRAPH.BAS
will do just the trick.
' RANGRAPH.BAS -- by Gary Neal, Jr. ' ' Generates random graphics using the procedures found in FGRAPH.BAS ' SCREEN 13 ' Random pixels WHILE INKEY$ = "" PSET (RND * 320, RND * 200), RND * 256 WEND ' Clear keyboard WHILE INKEY$ <> "": WEND CLS ' Random lines WHILE INKEY$ = "" DrawLine RND * 320, RND * 200, RND * 320, RND * 200, RND * 256 WEND ' Clear keyboard WHILE INKEY$ <> "": WEND CLS ' The next line is the line of interest ' SetAngleIncr 1! DrawCircle 160, 100, 90, 15 ' Wait for keypress WHILE INKEY$ = "": WEND ' Clear the keyboard WHILE INKEY$ <> "": WEND ' Clean up and exit SCREEN 0, 0, 0 END ' You can use SYSTEM also.
Now, ensure that you load both files in as seperate modules. Then make sure
that you set RANGRAPH.BAS
as the main module. If you are not sure how to do
this, consult your QuickBASIC documentation or online help. Obviously, this
set up will not work in QBasic, eeven though the code itself will. To run this
in QBasic, you must merge the two files RANGRAPH.BAS
and FGRAPH.BAS
into a single
file and load it into QBasic (defeating the purpore of this exercise). If you
are all set, run it and watch it fly.
You notice that this program plots many pixels and draws many lines but only one
circle. This one circle is to illustrate a point. Does the circle
appear "broken up" to you? Well, remove the apostrophe (REM) from the
beginning of the line of interest in the RANGRAPH.BAS
program and run it again.
Ah, the circle should appear even more broken up now. Basically, we increased
the 'angleIncr' variable by setting it to one, now for the million dollar
question that's probably in your mind. Why use a SUB procedure to set the value
of the variable 'angleIncr' and a FUNCTION to retreive it? Why not just
access it directly? Simply put, you can't. At least not from the RANGRAPH
module. Why not? Isn't 'angleIncr' global? It is, after all,
declared using DIM SHARED!
The truth is, no, DIM SHARED does not make a variable GLOBAL. It
does, however, allow the variable to be seen by all procedures within the module that
it's declared in. For example, the variable 'angleIncr' can be seen (and
therefore used) by all functions within the FGRAPH.BAS
code module. But only the
functions and procedures can be seen outside the code module, hence the reason why the
GetAngleIncr function and the SetAngleIncr procedure. Don't beleive
me, try it, modify the lines of interest within the RANGRAPH.BAS
module
and make it look like so:
' The next line is the line of interest. ' SetAngleIncr 1! angleIncr = 1! ' Added line...
Now run it and you'll see that the circle is back to the way it was prior to your removing
the comment from the line of interest. Still not convinced? Okay, add this line
to the RANGRAPH.BAS
program and run it.
' Clean up and exit. SCREEN 0, 0, 0 PRINT angleIncr, GetAngleIncr ' Added line END ' You can use SYSTEM also.
Run it and the following numbers should appear after displaying all the graphics:
1 0.5
As you can see, modifying 'angleIncr' in the RANGRAPH.BAS
module does not affect
the variable of the same name in the FGRAPH.BAS
module. Variables in QuickBASIC
cannot be shared across modules.
Note: If you've used Visual Basic for Windows before you'll notice that BAS file modules allow the use of a GLOBAL keyword to allow a variable to be modified by all modules as well as procedures. QuickBASIC does not support truly GLOBAL variables. Visual Basic versions 4.0 and up suggest using the PUBLIC keyword for global variables since they also work in forms as well as modules.