IntroductionIn the last tutorial we started adding some graphics primitives to our screen object, namely a point object. If you haven't done so, you should look over the graphics tutorial #3 to get a recap of the point object. In this tutorial we will add a new primitive, the line object.
Using Objects to Create Other ObjectsOne of the reasons that OOP has become so wide spread is that you don't always have to reinvent the wheel each time you want to add some new functionality to your program. If you have a class that draws a point on the screen, then you can use that class to create a class to draw a line, inheriting the code from the point class. Since you inherent the point class code, you don't need to rewrite the point code in your line class..
FreeBasic doesn't support inheritance, but we can use our point object as a base for our line object using the concept of containment. A line (for our purposes here) is made up of two point objects, so to create a line object, we will need to have two point objects defined in our line object; that is, our line object will contain two point objects. Unlike inheritance, which would automatically make available the point object methods inside the line object, we will need to manually expose the point object methods. It is a little more work, but the end result will be the same.
You should be quite familiar with the coding format by now, so I will only go over the major concepts of the object to see how all this works together.
Implementing the Containment ModelOur line object starts with two point objects, so we need to include these in our object.
Private:
_p1 As pntobj2D 'End points of line.
_p2 As pntobj2D
If you look at the code you will see that this is the only private data we have in our line object. We don't need any other data because the point objects hold all the information we need for a particular line.
Almost all the public methods of the object just expose the properties and methods of the two point objects. Most of the methods are labeled either 1 or 2, corresponding to point 1 or point 2. The designations are arbitrary since a line is symmetrical; that is you can draw a line from point 1 to 2 or from 2 to 1. It really doesn't matter as the line will come out the same either way.
Let's look at the PointX property to see how to implement the containment model.
'Sets the x coord of point 1.
Property lineobj2D.PointX1 (x As Integer)
If x < 0 Then x = 0
_p1.PointX = x
End Property
'Returns the x coord of point 1.
Property lineobj2D.PointX1 () As Integer
Return _p1.PointX
End Property
As you can see the code is quite simple. We are simply calling the Point method of the point object to set and return the X value. The other methods are implemented in the same fashion.
The line MidPoint function is really the only calculated function in the object, and it too relies on the point properties.
'Returns the midpoint of the line.
Function lineobj2D.MidPoint() As pntobj2D
Dim p As pntobj2D
p.PointX = (_p1.PointX + _p2.PointX) / 2
p.PointY = (_p1.PointY + _p2.PointY) / 2
Return p
End Function
Here we create a temporary point object, p, and set the values of the X and Y parameters based on the line points using the standard midpoint equation.
You can see the real power of object-based programming when you look at the line Rotate function. To refresh your memory here is the rotate method in the point object.
'Rotates a point around rotpoint.
Sub pntobj2D.Rotate (rotpnt As pntobj2D, angle As Double)
Dim As Double rad = angle * (_pi / 180)
Dim As Double cosphi = Cos(rad), sinphi = Sin(rad)
Dim As Integer rx = _pntx - rotpnt.PointX, ry = _pnty - rotpnt.PointY
_pntx = rotpnt.PointX + rx * cosphi - ry * sinphi
_pnty = rotpnt.PointY + rx * sinphi + ry * cosphi
End Sub
Here we are using the standard rotation equation to rotate a point around a fixed coordinate. Now take a look at the line Rotate method.
'Rotates line around rotpoint.
Sub lineobj2D.Rotate (rotpnt As pntobj2D, angle As Double)
_p1.Rotate rotpnt.PointX, rotpnt.PointY, angle
_p2.Rotate rotpnt.PointX, rotpnt.PointY, angle
End Sub
To rotate the line we simply call the Rotate method of each point and the line will rotate. It couldn't be easier.
Drawing a LineA line is more than points of course. We need to display the line on the screen. We do that in the screen object.
'Draws a line to the buffer using color object.
Sub screenobject.DrawLine (ln As lineobj2D, clr As clrobj)
Dim As Integer x = ln.PointX1, y = ln.PointY1, d = 0, dx = ln.PointX2 - ln.PointX1, dy = ln.PointY2 -ln.PointY1, c, m, xinc = 1, yinc = 1
If dx < 0 Then
xinc = -1
dx = -dx
EndIf
If dy < 0 Then
yinc = -1
dy = -dy
EndIf
If dy < dx Then
c = 2 * dx
m = 2 * dy
Do While x <> ln.PointX2
If clr.ChannelAlpha < 255 Then
PokeAlpha x, y, clr
Else
PokeBuffer x, y, clr
EndIf
x += xinc
d += m
If d > dx Then
y += yinc
d -= c
EndIf
Loop
Else
c = 2 * dy
m = 2 * dx
Do While y <> ln.PointY2
If clr.ChannelAlpha < 255 Then
PokeAlpha x, y, clr
Else
PokeBuffer x, y, clr
EndIf
y += yinc
d += m
If d > dy Then
x += xinc
d -= c
EndIf
Loop
EndIf
PokeBuffer x, y, clr
End Sub
In this version of the DrawLine method, a line object is passed to the subroutine along with a color object, and the line is drawn using Bresenham's line algorithm. Notice that we can draw both opaque and alpha lines based on the alpha value of the color object. Remember that we are using a buffer in the screen object, so the drawing is actually taking place in the buffer using the PokeBuffer or PokeAlpha methods of the screen object.
If you look at the revised screen object code you see several implementations of the line method. This is to make the object easier to use and more flexible.
SummaryI hope you can now see that all the work we did in the initial screen object, color object and point object are starting to pay off big. This is the power of object oriented and object-based programming. While we had to manually expose the point and color object methods in the line object, the actual amount of original coding was minimal. We were able to build upon the foundation we had already built to create the first in a set of graphic primitives that will further extend the power and usability of our screen object.
You can grab the modified screen object code and demo program
here. Look for ScreenObject4.0.zip.