Saturday, January 10, 2009

Making a module - Lesson 6

Many times it can be useful to break a program up into pieces. For example the part of our hypotenuse calculator that draws a right triangle might be useful in more than one program about triangles. Why reimplement it in each one?

Run BASIC permits a program to use one or more others. Let's take the code that draws the right triangle and make a program that can be used as a module (or object) by the hypotenuse calculator program. Here's what that looks like:

'This program is a module for drawing
'right triangles.
wait

function drawRightTriangle(a, b, c)
cls
graphic #rightTri, 240, 180
#rightTri place(210, 160)
#rightTri north()
#rightTri go(150)
#rightTri turn(-127)
#rightTri go(250)
#rightTri turn(-143)
#rightTri go(200)
#rightTri box(180, 130)
#rightTri place(215, 80)
#rightTri "\"; a
#rightTri place(100, 170)
#rightTri "\"; b
#rightTri place(90, 80)
#rightTri "\"; c
render #rightTri
end function
The idea here is that our hypotenuse calculator program will run this one which will just stop and wait to be called. That's why the first thing in the program is a WAIT statement. Notice also that we convert the SUB into a FUNCTION. This is the format that Run BASIC expects when one program calls another to do some work.

Here is how the hypotenuse calculator looks once we modify it to use the new right triangle drawing module:

'hypotenuse calculator with module
global a, b, c, #sideA, #sideB
run "rightTriangle", #drawing
call displayAll
wait

sub displayAll
cls
print "Hypotenuse Calculator"
print
print "Length of side A: ";
textbox #sideA, a
print
print "Length of side B: ";
textbox #sideB, b
print
button #go, "Go!", computeSideC
print
if c > 0 then
print "Length of side C: "; c
#drawing drawRightTriangle(a, b, c)
render #drawing
end if
end sub

sub computeSideC key$
a = #sideA value()
b = #sideB value()
c = sqr(a^2+b^2)
call displayAll
end sub

See how at the beginning of the program we use a RUN statement to start up a copy of the rightTriangle program? Then we assign it to an object variable named #drawing.

Inside our displayAll subroutine we no longer use CALL to access the drawRightTriangle subroutine because it doesn't exist in our program anymore.  Instead we invoke the drawRightTriangle() function on the #drawing object using the form:
#drawing drawRightTriangle(a, b, c)
Then once the drawRightTriangle() function is finished we render the #drawing object like so:
render #drawing
Wait a minute... you say. We already have a RENDER statement in the rightTriangle program. Why do we need another? Good question. Any time you RUN a program from within another and you want the newly RUN program to appear you must render it. So in this case you're not rendering the GRAPHIC object but the whole rightTriangle program is being rendered as part of the page. The RENDER statement in the rightTriangle program just renders the GRAPHIC. So both RENDER statements are needed.

Whew! That was a mouthful.

No comments: