diff options
Diffstat (limited to 'vectorgfx.mod')
-rw-r--r-- | vectorgfx.mod/vectorgfx.bmx | 1365 |
1 files changed, 682 insertions, 683 deletions
diff --git a/vectorgfx.mod/vectorgfx.bmx b/vectorgfx.mod/vectorgfx.bmx index 06018a8..a44635f 100644 --- a/vectorgfx.mod/vectorgfx.bmx +++ b/vectorgfx.mod/vectorgfx.bmx @@ -1,683 +1,682 @@ -' Copyright (c) 2006 Ian Cowburn -' -' Permission is hereby granted, free of charge, to any person obtaining a copy of -' this software and associated documentation files (the "Software"), to deal in -' the Software without restriction, including without limitation the rights to -' use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -' of the Software, and to permit persons to whom the Software is furnished to do -' so, subject to the following conditions: -' -' The above copyright notice and this permission notice shall be included in all -' copies or substantial portions of the Software. -' -' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -' IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -' AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -' LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -' OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -' SOFTWARE. -' -' $Id$ -' -Rem -bbdoc: noddybox.vectorgfx -EndRem -Module noddybox.vectorgfx - -ModuleInfo "Framework: 2D Vector Graphics classes" -ModuleInfo "Copyright: Ian Cowburn -- released under the MIT License" -ModuleInfo "Author: Ian Cowburn" -ModuleInfo "Version: $Revision$" - -Strict -Import brl.linkedlist -Import brl.math -Import brl.endianstream -Import brl.max2d -Import noddybox.vector -Import noddybox.algorithm - -Rem -bbdoc: Wibble -about: Wobble -EndRem - -Rem -bbdoc: Defines a method for drawing vector lines -about: For an example of creating a line drawing routine view the LineSolid type in the private section of this module. -EndRem -Type TVectorGfxLineStyle Abstract - Rem - bbdoc: Draws a vector line using IDs and @TVectorGfxCollisionMap method. - returns: The or'ed mask of all collision IDs overwritten in @colmap by this line, or zero if @colmap is null. - about: This routine must draw a line from @x1, @y1 to @x2, @y2 using the colour @r,@g,@b. - about: @id, @obj and @line must be written into the collision map @colmap if @colmap is not null and @actor is false. - about: If @colmap is set and @actor true, then collisions must be returned but no points written into the collision map. - about: If @colmap is set, @actor is true and @list is not null then any collisions should be recorded into this list - about: (no requirement for duplicate checking). - EndRem - Method LineToCollisionMap:Int(x1:Int, y1:Int, x2:Int, y2:Int, r:Int, g:Int, b:Int, id:Int, obj:TVectorGfxObject, line:Int, colmap:TVectorGfxCollisionMap, actor:Int, list:TList) Abstract - - Rem - bbdoc: Draws a vector line using the point list method. - about: This routine must draw a line from @x1, @y1 to @x2, @y2 using the colour @r,@g,@b. - about: If list is not null, then the points drawn must be stored in the list as @TVectorGfxPoint objects. - about: For an example of creating a line drawing routine view the LineSolid type in the private section of this module. - EndRem - Method LineToPointList:Int(x1:Int, y1:Int, x2:Int, y2:Int, r:Int, g:Int, b:Int, list:TList) Abstract -End Type - -Rem -bbdoc: Set to use solid lines for drawing. -about: This mode draws vector lines as solid colour lines using the current alpha, and is the default mode. -EndRem -Function VectorGfxSetSolid() - Static.linedraw=New LineSolid -End Function - -Rem -bbdoc: Set to use a custom drawing method. -EndRem -Function VectorGfxSetCustom(linedraw:TVectorGfxLineStyle) - Static.linedraw=linedraw -End Function - -Rem -bbdoc: Defines a point in the vector graphics collision map. -EndRem -Type TVectorGfxCollision - Rem - bbdoc: The X co-ordinate of this collision (in the object co-ordinate space). - EndRem - Field x:Int - - Rem - bbdoc: The Y co-ordinate of this collision (in the object co-ordinate space). - EndRem - Field y:Int - - Rem - bbdoc: The collision masks at this point. - EndRem - Field mask:Int - - Rem - bbdoc: The last vector object that wrote at this point. - EndRem - Field obj:TVectorGfxObject - - Rem - bbdoc: The index of the line in the last vector object that wrote at this point. - EndRem - Field line:Int - - Function Create:TVectorGfxCollision(x:Int, y:Int, mask:Int, obj:TVectorGfxObject, line:Int) - Local o:TVectorGfxCollision=New TVectorGfxCollision - o.x=x - o.y=y - o.mask=mask - o.obj=obj - o.line=line - Return o - End Function -End Type - - -Rem -bbdoc: Defines a vector graphics collision map. -about: Collisions using this method in the library are defined using a bitmask (allowing 32 collision masks). -EndRem -Type TVectorGfxCollisionMap - - Field width:Int - Field height:Int - Field xoff:Int - Field yoff:Int - Field data:TVectorGfxCollision[,] - - Rem - bbdoc: Create a collision map. - returns: The created collision map. - about: @width and @height are the size of the collision map. - EndRem - Function Create:TVectorGfxCollisionMap(width:Int, height:Int) - Local o:TVectorGfxCollisionMap=New TVectorGfxCollisionMap - - o.width=width - o.height=height - o.xoff=0 - o.yoff=0 - o.Clear() - Return o - End Function - - Rem - bbdoc: Set the offset of the collision map. - about: @x and @y are the offsets into the co-ordinate space where the collision map lives. - EndRem - Method SetOffset(x:Int, y:Int) - xoff=x - yoff=y - End Method - - Rem - bbdoc: Get a collision point. - returns: The collision point, or null if nothing drawn there. - about: @x and @y are the co-ordinates (in the objects co-ordinate space, not the collision map space) - EndRem - Method GetCollision:TVectorGfxCollision(x:Int, y:Int) - If x<xoff Or x>=xoff+width Or y<yoff Or y>=yoff+height - Return Null - Else - Return data[x-xoff,y-yoff] - EndIf - End Method - - Rem - bbdoc: Set a collision point. - returns: The current collision mask for that point, or zero if the point is out of the map's range. - about: @x and @y are the co-ordinates (in the objects co-ordinate space, not the collision map space) - EndRem - Method SetCollision:Int(x:Int, y:Int, id:Int, obj:TVectorGfxObject, line:Int) - If x<xoff Or x>=xoff+width Or y<yoff Or y>=yoff+height - Return 0 - EndIf - - Local ax:Int=x-xoff - Local ay:Int=y-yoff - - Local cur:TVectorGfxCollision=data[ax,ay] - - If Not cur - cur=TVectorGfxCollision.Create(x,y,id,obj,line) - data[ax,ay]=cur - Else - cur.mask:|id - cur.obj=obj - cur.line=line - EndIf - - Return cur.mask - End Method - - Rem - bbdoc: Clear the collision map - EndRem - Method Clear() - data=New TVectorGfxCollision[width,height] - End Method -End Type - - -Rem -bbdoc: Defines a 2D vector graphics object -EndRem -Type TVectorGfxObject - Rem - bbdoc: The points making up this object - EndRem - Field points:TVectorGfxPoint[] - Rem - bbdoc: The lines making up this object - EndRem - Field lines:TVectorGfxLine[] - Rem - bbdoc: The X co-ordinate of the object - EndRem - Field x:Int - Rem - bbdoc: The Y co-ordinate of the object - EndRem - Field y:Int - Rem - bbdoc: The minimum X co-ordinate of the object. Only valid after a call to SetPoints(). - EndRem - Field min_x:Int - Rem - bbdoc: The maximum X co-ordinate of the object. Only valid after a call to SetPoints(). - EndRem - Field max_x:Int - Rem - bbdoc: The minimum Y co-ordinate of the object. Only valid after a call to SetPoints(). - EndRem - Field min_y:Int - Rem - bbdoc: The maximum Y co-ordinate of the object. Only valid after a call to SetPoints(). - EndRem - Field max_y:Int - Rem - bbdoc: The width of the object. Only valid after a call to SetPoints(). - EndRem - Field width:Int - Rem - bbdoc: The height of the object. Only valid after a call to SetPoints(). - EndRem - Field height:Int - Rem - bbdoc: The angle of the object, as degrees*10. Must be within the range 0-3599 inclusive. - EndRem - Field ang:Int - Rem - bbdoc: The scale of the object. - EndRem - Field scale:Double - - Field rotated:TVectorGfxPoint[] - - Rem - bbdoc: Creates a new empty object - returns: The created object. - EndRem - Method New() - points=Null - lines=Null - rotated=Null - x=0 - y=0 - min_x=9999999 - min_y=9999999 - max_x=-9999999 - max_y=-9999999 - width=0 - height=0 - ang=0 - scale=1 - End Method - - Rem - bbdoc: Clones this object - about: Returns a copy of this object, with its own copy of the line and points. - EndRem - Method Clone:TVectorGfxObject() - Local o:TVectorGfxObject=New TVectorGfxObject - o.x=x - o.y=y - o.min_x=min_x - o.min_y=min_y - o.max_x=max_x - o.max_y=max_y - o.width=width - o.height=height - o.ang=ang - o.scale=scale - o.SetPoints(points) - o.SetLines(lines) - Return o - End Method - - Rem - bbdoc: Sets the points for this object - about: @pa is an array of points for this object. - EndRem - Method SetPoints(pa:Object[]) - points=New TVectorGfxPoint[pa.length] - For Local f:Int=0 Until pa.length - points[f]=TVectorGfxPoint(pa[f]) - min_x=Min(min_x,points[f].x) - min_y=Min(min_y,points[f].y) - max_x=Max(max_x,points[f].x) - max_y=Max(max_y,points[f].y) - Next - width=max_x-min_x - height=max_y-min_y - End Method - - Rem - bbdoc: Sets the lines for this object. - about: @la is the array of lines for this object. - EndRem - Method SetLines(la:Object[]) - lines=New TVectorGfxLine[la.length] - For Local f:Int=0 Until la.length - lines[f]=TVectorGfxLine(la[f]) - Next - End Method - - Rem - bbdoc: Whether a point is inside the object - returns: True if the point lies inside the object. The object is assumed to be a closed polygon for this test. - about: @cx, @cy is the point to test. - about: This routine is based on code from comp.graphics.algorithms FAQ 2.03 - EndRem - Method IsInside:Int(cx:Int, cy:Int) - If rotated=Null - Return False - EndIf - - Local cross:Int=False - - For Local l:TVectorGfxLine=EachIn lines - Local x1:Int=x+rotated[l.i1].x - Local y1:Int=y+rotated[l.i1].y - Local x2:Int=x+rotated[l.i2].x - Local y2:Int=y+rotated[l.i2].y - - If ((((y1<=cy) And (cy<y2)) Or ((y2<=cy) And (cy<y1))) And (cx < (x2 - x1) * (cy - y1) / (y2 - y1) + x1)) - cross=Not cross - EndIf - Next - - Return cross - End Method - - Rem - bbdoc: A line's adjusted co-ordinates. - returns: The rotated and scaled points (in object co-ordinates) of the line. - about: @i is the index of the line to return the points for. - about: Calling it before drawing the object will return null. - EndRem - Method AdjustedCoords:TVectorGfxPoint[](i:Int) - If rotated=Null - Return Null - EndIf - - Local p:TVectorGfxPoint[]=New TVectorGfxPoint[2] - Local l:TVectorGfxLine=lines[i] - p[0]=rotated[l.i1] - p[1]=rotated[l.i2] - Return p - End Method - - Rem - bbdoc: A line's normal. - returns: The normal of the selected line. - about: @i is the index of the line to return the normal of. This will return the normal due to the rotation of the object after the object is drawn. - about: Calling it before drawing the object will return null. - EndRem - Method Normal:TVector(i:Int) - If rotated=Null - Return Null - EndIf - - Local l:TVectorGfxLine=lines[i] - Local v:TVector=TVector.Create(rotated[l.i2].y-rotated[l.i1].y,rotated[l.i1].x-rotated[l.i2].x) - v.Normalise() - Return v - End Method - - Rem - bbdoc: Loads the object from the supplied @filename. - returns: The loaded object, or null if the file could not be opened. - EndRem - Function Load:TVectorGfxObject(filename:String) - Local s:TStream=ReadStream(filename) - - If Not s - Return Null - EndIf - - s=LittleEndianStream(s) - Local o:TVectorGfxObject=New TVectorGfxObject - - o.x=s.ReadInt() - o.y=s.ReadInt() - o.ang=s.ReadInt() - - Local l:TList=CreateList() - Local i:Int=s.ReadInt() - - For Local f=0 Until i - l.AddLast(TVectorGfxPoint.Load(s)) - Next - - o.SetPoints(l.ToArray()) - - l.Clear() - - i=s.ReadInt() - - For Local f=0 Until i - l.AddLast(TVectorGfxLine.Load(s)) - Next - - o.SetLines(l.ToArray()) - - s.Close() - - Return o - End Function - - Rem - bbdoc: Saves the object to the supplied @filename. - EndRem - Method Save(filename:String) - Local s:TStream=WriteStream(filename) - - If Not s - Return Null - EndIf - - s=LittleEndianStream(s) - - s.WriteInt(x) - s.WriteInt(y) - s.WriteInt(ang) - - s.WriteInt(points.length) - For Local p:TVectorGfxPoint=EachIn points - p.Save(s) - Next - - s.WriteInt(lines.length) - For Local l:TVectorGfxLine=EachIn lines - l.Save(s) - Next - - s.Close() - End Method - - Rem - bbdoc: Draw the object, not bothering about collisions. - EndRem - Method Draw() - rotated=New TVectorGfxPoint[points.length] - - For Local f:Int=0 Until points.length - Local p:TAlgoPointD=DoRotateD(points[f].x*scale,points[f].y*scale,ang) - rotated[f]=TVectorGfxPoint.Create(p.x,p.y) - Next - - For Local l:TVectorGfxLine=EachIn lines - Static.linedraw.LineToCollisionMap(x+rotated[l.i1].x,y+rotated[l.i1].y,x+rotated[l.i2].x,y+rotated[l.i2].y,l.r,l.g,l.b,0,Self,0,Null,True,Null) - Next - End Method - - Rem - bbdoc: Draw the object, using the collision map routines. - returns: A bitmask of collisions. - about: Draws the object. If @colmap is null then no collision processing takes place. - about: If @actor is true then collision processing takes place, but the object will - about: not write into the collision map. - about: If @list is not null then any collisions will be written into this list. This only applies if @colmap is set and @actor true. - EndRem - Method DrawToCollisionMap:Int(colmap:TVectorGfxCollisionMap=Null, actor:Int=False, list:TList=Null) - Local col:Int=0 - - rotated=New TVectorGfxPoint[points.length] - - For Local f:Int=0 Until points.length - Local p:TAlgoPointD=DoRotateD(points[f].x*scale,points[f].y*scale,ang) - rotated[f]=TVectorGfxPoint.Create(p.x,p.y) - Next - - Local i:Int=0 - - For Local l:TVectorGfxLine=EachIn lines - col:|Static.linedraw.LineToCollisionMap(x+rotated[l.i1].x,y+rotated[l.i1].y,x+rotated[l.i2].x,y+rotated[l.i2].y,l.r,l.g,l.b,l.id,Self,i,colmap,actor,list) - i:+1 - Next - - Return col - End Method - - Rem - bbdoc: Draw the object, using returning a point list. - returns: The list of points plotted as @TVectorGfxPoint objects. - EndRem - Method DrawToPointList:TList() - Local list:TList=CreateList() - Local col:Int=0 - - rotated=New TVectorGfxPoint[points.length] - - For Local f:Int=0 Until points.length - Local p:TAlgoPointD=DoRotateD(points[f].x*scale,points[f].y*scale,ang) - rotated[f]=TVectorGfxPoint.Create(p.x,p.y) - Next - - Local i:Int=0 - - For Local l:TVectorGfxLine=EachIn lines - col:|Static.linedraw.LineToPointList(x+rotated[l.i1].x,y+rotated[l.i1].y,x+rotated[l.i2].x,y+rotated[l.i2].y,l.r,l.g,l.b,list) - i:+1 - Next - - Return list - End Method -End Type - -Rem -bbdoc: Defines a point -EndRem -Type TVectorGfxPoint - Rem - bbdoc: The X co-ordinate of the point - EndRem - Field x:Int - Rem - bbdoc: The Y co-ordinate of the point - EndRem - Field y:Int - - Rem - bbdoc: Create a point. - returns: The created point. - about: @x and @y are the co-ordinates of the point. - EndRem - Function Create:TVectorGfxPoint(x:Int, y:Int) - Local o:TVectorGfxPoint=New TVectorGfxPoint - o.x=x - o.y=y - Return o - End Function - - Function Load:TVectorGfxPoint(s:TStream) - Local o:TVectorGfxPoint - o=New TVectorGfxPoint - o.x=s.ReadInt() - o.y=s.ReadInt() - Return o - End Function - - Method Save(s:TStream) - s.WriteInt(x) - s.WriteInt(y) - End Method -End Type - -Rem -bbdoc: Defines a line -EndRem -Type TVectorGfxLine - Field i1:Int - Field i2:Int - Field id:Int - Field r:Int - Field g:Int - Field b:Int - - Rem - bbdoc: Create a line. - returns: The created line. - about: @i1 and @i2 are the indexes into the point list. @r, @g and @b is the line's colour. @id is the collision map mask for the line. - EndRem - Function Create:TVectorGfxLine(i1:Int, i2:Int, r:Int, g:Int, b:Int, id:Int) - Local o:TVectorGfxLine=New TVectorGfxLine - - o.i1=i1 - o.i2=i2 - o.r=r - o.g=g - o.b=b - o.id=id - - Return o - End Function - - Function Load:TVectorGfxLine(s:TStream) - Local o:TVectorGfxLine - o=New TVectorGfxLine - o.i1=s.ReadInt() - o.i2=s.ReadInt() - o.r=s.ReadInt() - o.g=s.ReadInt() - o.b=s.ReadInt() - o.id=s.ReadInt() - Return o - End Function - - Method Save:TVectorGfxLine(s:TStream) - s.WriteInt(i1) - s.WriteInt(i2) - s.WriteInt(r) - s.WriteInt(g) - s.WriteInt(b) - s.WriteInt(id) - End Method -End Type - -Private - -Type Static - Global linedraw:TVectorGfxLineStyle - - Function Init() - linedraw=New LineSolid - End Function -End Type - -Type LineSolid Extends TVectorGfxLineStyle - Method LineToCollisionMap:Int(x1:Int, y1:Int, x2:Int, y2:Int, r:Int, g:Int, b:Int, id:Int, obj:TVectorGfxObject, line:Int, colmap:TVectorGfxCollisionMap, actor:Int, list:TList) - Local mask:Int=0 - Local lp:TList=DoLine(x1,y1,x2,y2) - - SetColor(r,g,b) - - For Local p:TAlgoPoint=EachIn lp - If colmap - If actor - Local c:TVectorGfxCollision=colmap.GetCollision(p.x,p.y) - - If c - mask:|c.mask - If list - list.AddLast(c) - EndIf - EndIf - Else - mask:|colmap.SetCollision(p.x,p.y,id,obj,line) - EndIf - EndIf - Plot(p.x,p.y) - Next - - Return mask - End Method - - Method LineToPointList:Int(x1:Int, y1:Int, x2:Int, y2:Int, r:Int, g:Int, b:Int, list:TList) - Local mask:Int=0 - Local lp:TList=DoLine(x1,y1,x2,y2) - - SetColor(r,g,b) - - For Local p:TAlgoPoint=EachIn lp - Plot(p.x,p.y) - list.AddLast(TVectorGfxPoint.Create(p.x,p.y)) - Next - - Return mask - End Method -End Type - -Static.Init() +' Copyright (c) 2006 Ian Cowburn
+'
+' Permission is hereby granted, free of charge, to any person obtaining a copy of
+' this software and associated documentation files (the "Software"), to deal in
+' the Software without restriction, including without limitation the rights to
+' use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+' of the Software, and to permit persons to whom the Software is furnished to do
+' so, subject to the following conditions:
+'
+' The above copyright notice and this permission notice shall be included in all
+' copies or substantial portions of the Software.
+'
+' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+' IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+' AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+' LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+' OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+' SOFTWARE.
+'
+' $Id$
+'
+Rem
+bbdoc: noddybox.vectorgfx
+EndRem
+Module noddybox.vectorgfx
+
+ModuleInfo "Framework: 2D Vector Graphics classes"
+ModuleInfo "Copyright: Ian Cowburn -- released under the MIT License"
+ModuleInfo "Author: Ian Cowburn"
+ModuleInfo "Version: $Revision$"
+
+Import brl.linkedlist
+Import brl.math
+Import brl.endianstream
+Import brl.max2d
+Import noddybox.vector
+Import noddybox.algorithm
+
+Rem
+bbdoc: Wibble
+about: Wobble
+EndRem
+
+Rem
+bbdoc: Defines a method for drawing vector lines
+about: For an example of creating a line drawing routine view the LineSolid type in the private section of this module.
+EndRem
+Type TVectorGfxLineStyle Abstract
+ Rem
+ bbdoc: Draws a vector line using IDs and @TVectorGfxCollisionMap method.
+ returns: The or'ed mask of all collision IDs overwritten in @colmap by this line, or zero if @colmap is null.
+ about: This routine must draw a line from @x1, @y1 to @x2, @y2 using the colour @r,@g,@b.
+ about: @id, @obj and @line must be written into the collision map @colmap if @colmap is not null and @actor is false.
+ about: If @colmap is set and @actor true, then collisions must be returned but no points written into the collision map.
+ about: If @colmap is set, @actor is true and @list is not null then any collisions should be recorded into this list
+ about: (no requirement for duplicate checking).
+ EndRem
+ Method LineToCollisionMap:Int(x1:Int, y1:Int, x2:Int, y2:Int, r:Int, g:Int, b:Int, id:Int, obj:TVectorGfxObject, line:Int, colmap:TVectorGfxCollisionMap, actor:Int, list:TList) Abstract
+
+ Rem
+ bbdoc: Draws a vector line using the point list method.
+ about: This routine must draw a line from @x1, @y1 to @x2, @y2 using the colour @r,@g,@b.
+ about: If list is not null, then the points drawn must be stored in the list as @TVectorGfxPoint objects.
+ about: For an example of creating a line drawing routine view the LineSolid type in the private section of this module.
+ EndRem
+ Method LineToPointList:Int(x1:Int, y1:Int, x2:Int, y2:Int, r:Int, g:Int, b:Int, list:TList) Abstract
+End Type
+
+Rem
+bbdoc: Set to use solid lines for drawing.
+about: This mode draws vector lines as solid colour lines using the current alpha, and is the default mode.
+EndRem
+Function VectorGfxSetSolid()
+ Static.linedraw=New LineSolid
+End Function
+
+Rem
+bbdoc: Set to use a custom drawing method.
+EndRem
+Function VectorGfxSetCustom(linedraw:TVectorGfxLineStyle)
+ Static.linedraw=linedraw
+End Function
+
+Rem
+bbdoc: Defines a point in the vector graphics collision map.
+EndRem
+Type TVectorGfxCollision
+ Rem
+ bbdoc: The X co-ordinate of this collision (in the object co-ordinate space).
+ EndRem
+ Field x:Int
+
+ Rem
+ bbdoc: The Y co-ordinate of this collision (in the object co-ordinate space).
+ EndRem
+ Field y:Int
+
+ Rem
+ bbdoc: The collision masks at this point.
+ EndRem
+ Field mask:Int
+
+ Rem
+ bbdoc: The last vector object that wrote at this point.
+ EndRem
+ Field obj:TVectorGfxObject
+
+ Rem
+ bbdoc: The index of the line in the last vector object that wrote at this point.
+ EndRem
+ Field line:Int
+
+ Function Create:TVectorGfxCollision(x:Int, y:Int, mask:Int, obj:TVectorGfxObject, line:Int)
+ Local o:TVectorGfxCollision=New TVectorGfxCollision
+ o.x=x
+ o.y=y
+ o.mask=mask
+ o.obj=obj
+ o.line=line
+ Return o
+ End Function
+End Type
+
+
+Rem
+bbdoc: Defines a vector graphics collision map.
+about: Collisions using this method in the library are defined using a bitmask (allowing 32 collision masks).
+EndRem
+Type TVectorGfxCollisionMap
+
+ Field width:Int
+ Field height:Int
+ Field xoff:Int
+ Field yoff:Int
+ Field data:TVectorGfxCollision[,]
+
+ Rem
+ bbdoc: Create a collision map.
+ returns: The created collision map.
+ about: @width and @height are the size of the collision map.
+ EndRem
+ Function Create:TVectorGfxCollisionMap(width:Int, height:Int)
+ Local o:TVectorGfxCollisionMap=New TVectorGfxCollisionMap
+
+ o.width=width
+ o.height=height
+ o.xoff=0
+ o.yoff=0
+ o.Clear()
+ Return o
+ End Function
+
+ Rem
+ bbdoc: Set the offset of the collision map.
+ about: @x and @y are the offsets into the co-ordinate space where the collision map lives.
+ EndRem
+ Method SetOffset(x:Int, y:Int)
+ xoff=x
+ yoff=y
+ End Method
+
+ Rem
+ bbdoc: Get a collision point.
+ returns: The collision point, or null if nothing drawn there.
+ about: @x and @y are the co-ordinates (in the objects co-ordinate space, not the collision map space)
+ EndRem
+ Method GetCollision:TVectorGfxCollision(x:Int, y:Int)
+ If x<xoff Or x>=xoff+width Or y<yoff Or y>=yoff+height
+ Return Null
+ Else
+ Return data[x-xoff,y-yoff]
+ EndIf
+ End Method
+
+ Rem
+ bbdoc: Set a collision point.
+ returns: The current collision mask for that point, or zero if the point is out of the map's range.
+ about: @x and @y are the co-ordinates (in the objects co-ordinate space, not the collision map space)
+ EndRem
+ Method SetCollision:Int(x:Int, y:Int, id:Int, obj:TVectorGfxObject, line:Int)
+ If x<xoff Or x>=xoff+width Or y<yoff Or y>=yoff+height
+ Return 0
+ EndIf
+
+ Local ax:Int=x-xoff
+ Local ay:Int=y-yoff
+
+ Local cur:TVectorGfxCollision=data[ax,ay]
+
+ If Not cur
+ cur=TVectorGfxCollision.Create(x,y,id,obj,line)
+ data[ax,ay]=cur
+ Else
+ cur.mask:|id
+ cur.obj=obj
+ cur.line=line
+ EndIf
+
+ Return cur.mask
+ End Method
+
+ Rem
+ bbdoc: Clear the collision map
+ EndRem
+ Method Clear()
+ data=New TVectorGfxCollision[width,height]
+ End Method
+End Type
+
+
+Rem
+bbdoc: Defines a 2D vector graphics object
+EndRem
+Type TVectorGfxObject
+ Rem
+ bbdoc: The points making up this object
+ EndRem
+ Field points:TVectorGfxPoint[]
+ Rem
+ bbdoc: The lines making up this object
+ EndRem
+ Field lines:TVectorGfxLine[]
+ Rem
+ bbdoc: The X co-ordinate of the object
+ EndRem
+ Field x:Int
+ Rem
+ bbdoc: The Y co-ordinate of the object
+ EndRem
+ Field y:Int
+ Rem
+ bbdoc: The minimum X co-ordinate of the object. Only valid after a call to SetPoints().
+ EndRem
+ Field min_x:Int
+ Rem
+ bbdoc: The maximum X co-ordinate of the object. Only valid after a call to SetPoints().
+ EndRem
+ Field max_x:Int
+ Rem
+ bbdoc: The minimum Y co-ordinate of the object. Only valid after a call to SetPoints().
+ EndRem
+ Field min_y:Int
+ Rem
+ bbdoc: The maximum Y co-ordinate of the object. Only valid after a call to SetPoints().
+ EndRem
+ Field max_y:Int
+ Rem
+ bbdoc: The width of the object. Only valid after a call to SetPoints().
+ EndRem
+ Field width:Int
+ Rem
+ bbdoc: The height of the object. Only valid after a call to SetPoints().
+ EndRem
+ Field height:Int
+ Rem
+ bbdoc: The angle of the object, as degrees*10. Must be within the range 0-3599 inclusive.
+ EndRem
+ Field ang:Int
+ Rem
+ bbdoc: The scale of the object.
+ EndRem
+ Field scale:Double
+
+ Field rotated:TVectorGfxPoint[]
+
+ Rem
+ bbdoc: Creates a new empty object
+ returns: The created object.
+ EndRem
+ Method New()
+ points=Null
+ lines=Null
+ rotated=Null
+ x=0
+ y=0
+ min_x=9999999
+ min_y=9999999
+ max_x=-9999999
+ max_y=-9999999
+ width=0
+ height=0
+ ang=0
+ scale=1
+ End Method
+
+ Rem
+ bbdoc: Clones this object
+ about: Returns a copy of this object, with its own copy of the line and points.
+ EndRem
+ Method Clone:TVectorGfxObject()
+ Local o:TVectorGfxObject=New TVectorGfxObject
+ o.x=x
+ o.y=y
+ o.min_x=min_x
+ o.min_y=min_y
+ o.max_x=max_x
+ o.max_y=max_y
+ o.width=width
+ o.height=height
+ o.ang=ang
+ o.scale=scale
+ o.SetPoints(points)
+ o.SetLines(lines)
+ Return o
+ End Method
+
+ Rem
+ bbdoc: Sets the points for this object
+ about: @pa is an array of points for this object.
+ EndRem
+ Method SetPoints(pa:Object[])
+ points=New TVectorGfxPoint[pa.length]
+ For Local f:Int=0 Until pa.length
+ points[f]=TVectorGfxPoint(pa[f])
+ min_x=Min(min_x,points[f].x)
+ min_y=Min(min_y,points[f].y)
+ max_x=Max(max_x,points[f].x)
+ max_y=Max(max_y,points[f].y)
+ Next
+ width=max_x-min_x
+ height=max_y-min_y
+ End Method
+
+ Rem
+ bbdoc: Sets the lines for this object.
+ about: @la is the array of lines for this object.
+ EndRem
+ Method SetLines(la:Object[])
+ lines=New TVectorGfxLine[la.length]
+ For Local f:Int=0 Until la.length
+ lines[f]=TVectorGfxLine(la[f])
+ Next
+ End Method
+
+ Rem
+ bbdoc: Whether a point is inside the object
+ returns: True if the point lies inside the object. The object is assumed to be a closed polygon for this test.
+ about: @cx, @cy is the point to test.
+ about: This routine is based on code from comp.graphics.algorithms FAQ 2.03
+ EndRem
+ Method IsInside:Int(cx:Int, cy:Int)
+ If rotated=Null
+ Return False
+ EndIf
+
+ Local cross:Int=False
+
+ For Local l:TVectorGfxLine=EachIn lines
+ Local x1:Int=x+rotated[l.i1].x
+ Local y1:Int=y+rotated[l.i1].y
+ Local x2:Int=x+rotated[l.i2].x
+ Local y2:Int=y+rotated[l.i2].y
+
+ If ((((y1<=cy) And (cy<y2)) Or ((y2<=cy) And (cy<y1))) And (cx < (x2 - x1) * (cy - y1) / (y2 - y1) + x1))
+ cross=Not cross
+ EndIf
+ Next
+
+ Return cross
+ End Method
+
+ Rem
+ bbdoc: A line's adjusted co-ordinates.
+ returns: The rotated and scaled points (in object co-ordinates) of the line.
+ about: @i is the index of the line to return the points for.
+ about: Calling it before drawing the object will return null.
+ EndRem
+ Method AdjustedCoords:TVectorGfxPoint[](i:Int)
+ If rotated=Null
+ Return Null
+ EndIf
+
+ Local p:TVectorGfxPoint[]=New TVectorGfxPoint[2]
+ Local l:TVectorGfxLine=lines[i]
+ p[0]=rotated[l.i1]
+ p[1]=rotated[l.i2]
+ Return p
+ End Method
+
+ Rem
+ bbdoc: A line's normal.
+ returns: The normal of the selected line.
+ about: @i is the index of the line to return the normal of. This will return the normal due to the rotation of the object after the object is drawn.
+ about: Calling it before drawing the object will return null.
+ EndRem
+ Method Normal:TVector(i:Int)
+ If rotated=Null
+ Return Null
+ EndIf
+
+ Local l:TVectorGfxLine=lines[i]
+ Local v:TVector=TVector.Create(rotated[l.i2].y-rotated[l.i1].y,rotated[l.i1].x-rotated[l.i2].x)
+ v.Normalise()
+ Return v
+ End Method
+
+ Rem
+ bbdoc: Loads the object from the supplied @filename.
+ returns: The loaded object, or null if the file could not be opened.
+ EndRem
+ Function Load:TVectorGfxObject(filename:String)
+ Local s:TStream=ReadStream(filename)
+
+ If Not s
+ Return Null
+ EndIf
+
+ s=LittleEndianStream(s)
+ Local o:TVectorGfxObject=New TVectorGfxObject
+
+ o.x=s.ReadInt()
+ o.y=s.ReadInt()
+ o.ang=s.ReadInt()
+
+ Local l:TList=CreateList()
+ Local i:Int=s.ReadInt()
+
+ For Local f=0 Until i
+ l.AddLast(TVectorGfxPoint.Load(s))
+ Next
+
+ o.SetPoints(l.ToArray())
+
+ l.Clear()
+
+ i=s.ReadInt()
+
+ For Local f=0 Until i
+ l.AddLast(TVectorGfxLine.Load(s))
+ Next
+
+ o.SetLines(l.ToArray())
+
+ s.Close()
+
+ Return o
+ End Function
+
+ Rem
+ bbdoc: Saves the object to the supplied @filename.
+ EndRem
+ Method Save(filename:String)
+ Local s:TStream=WriteStream(filename)
+
+ If Not s
+ Return Null
+ EndIf
+
+ s=LittleEndianStream(s)
+
+ s.WriteInt(x)
+ s.WriteInt(y)
+ s.WriteInt(ang)
+
+ s.WriteInt(points.length)
+ For Local p:TVectorGfxPoint=EachIn points
+ p.Save(s)
+ Next
+
+ s.WriteInt(lines.length)
+ For Local l:TVectorGfxLine=EachIn lines
+ l.Save(s)
+ Next
+
+ s.Close()
+ End Method
+
+ Rem
+ bbdoc: Draw the object, not bothering about collisions.
+ EndRem
+ Method Draw()
+ rotated=New TVectorGfxPoint[points.length]
+
+ For Local f:Int=0 Until points.length
+ Local p:TAlgoPointD=DoRotateD(points[f].x*scale,points[f].y*scale,ang)
+ rotated[f]=TVectorGfxPoint.Create(p.x,p.y)
+ Next
+
+ For Local l:TVectorGfxLine=EachIn lines
+ Static.linedraw.LineToCollisionMap(x+rotated[l.i1].x,y+rotated[l.i1].y,x+rotated[l.i2].x,y+rotated[l.i2].y,l.r,l.g,l.b,0,Self,0,Null,True,Null)
+ Next
+ End Method
+
+ Rem
+ bbdoc: Draw the object, using the collision map routines.
+ returns: A bitmask of collisions.
+ about: Draws the object. If @colmap is null then no collision processing takes place.
+ about: If @actor is true then collision processing takes place, but the object will
+ about: not write into the collision map.
+ about: If @list is not null then any collisions will be written into this list. This only applies if @colmap is set and @actor true.
+ EndRem
+ Method DrawToCollisionMap:Int(colmap:TVectorGfxCollisionMap=Null, actor:Int=False, list:TList=Null)
+ Local col:Int=0
+
+ rotated=New TVectorGfxPoint[points.length]
+
+ For Local f:Int=0 Until points.length
+ Local p:TAlgoPointD=DoRotateD(points[f].x*scale,points[f].y*scale,ang)
+ rotated[f]=TVectorGfxPoint.Create(p.x,p.y)
+ Next
+
+ Local i:Int=0
+
+ For Local l:TVectorGfxLine=EachIn lines
+ col:|Static.linedraw.LineToCollisionMap(x+rotated[l.i1].x,y+rotated[l.i1].y,x+rotated[l.i2].x,y+rotated[l.i2].y,l.r,l.g,l.b,l.id,Self,i,colmap,actor,list)
+ i:+1
+ Next
+
+ Return col
+ End Method
+
+ Rem
+ bbdoc: Draw the object, using returning a point list.
+ returns: The list of points plotted as @TVectorGfxPoint objects.
+ EndRem
+ Method DrawToPointList:TList()
+ Local list:TList=CreateList()
+ Local col:Int=0
+
+ rotated=New TVectorGfxPoint[points.length]
+
+ For Local f:Int=0 Until points.length
+ Local p:TAlgoPointD=DoRotateD(points[f].x*scale,points[f].y*scale,ang)
+ rotated[f]=TVectorGfxPoint.Create(p.x,p.y)
+ Next
+
+ Local i:Int=0
+
+ For Local l:TVectorGfxLine=EachIn lines
+ col:|Static.linedraw.LineToPointList(x+rotated[l.i1].x,y+rotated[l.i1].y,x+rotated[l.i2].x,y+rotated[l.i2].y,l.r,l.g,l.b,list)
+ i:+1
+ Next
+
+ Return list
+ End Method
+End Type
+
+Rem
+bbdoc: Defines a point
+EndRem
+Type TVectorGfxPoint
+ Rem
+ bbdoc: The X co-ordinate of the point
+ EndRem
+ Field x:Int
+ Rem
+ bbdoc: The Y co-ordinate of the point
+ EndRem
+ Field y:Int
+
+ Rem
+ bbdoc: Create a point.
+ returns: The created point.
+ about: @x and @y are the co-ordinates of the point.
+ EndRem
+ Function Create:TVectorGfxPoint(x:Int, y:Int)
+ Local o:TVectorGfxPoint=New TVectorGfxPoint
+ o.x=x
+ o.y=y
+ Return o
+ End Function
+
+ Function Load:TVectorGfxPoint(s:TStream)
+ Local o:TVectorGfxPoint
+ o=New TVectorGfxPoint
+ o.x=s.ReadInt()
+ o.y=s.ReadInt()
+ Return o
+ End Function
+
+ Method Save(s:TStream)
+ s.WriteInt(x)
+ s.WriteInt(y)
+ End Method
+End Type
+
+Rem
+bbdoc: Defines a line
+EndRem
+Type TVectorGfxLine
+ Field i1:Int
+ Field i2:Int
+ Field id:Int
+ Field r:Int
+ Field g:Int
+ Field b:Int
+
+ Rem
+ bbdoc: Create a line.
+ returns: The created line.
+ about: @i1 and @i2 are the indexes into the point list. @r, @g and @b is the line's colour. @id is the collision map mask for the line.
+ EndRem
+ Function Create:TVectorGfxLine(i1:Int, i2:Int, r:Int, g:Int, b:Int, id:Int)
+ Local o:TVectorGfxLine=New TVectorGfxLine
+
+ o.i1=i1
+ o.i2=i2
+ o.r=r
+ o.g=g
+ o.b=b
+ o.id=id
+
+ Return o
+ End Function
+
+ Function Load:TVectorGfxLine(s:TStream)
+ Local o:TVectorGfxLine
+ o=New TVectorGfxLine
+ o.i1=s.ReadInt()
+ o.i2=s.ReadInt()
+ o.r=s.ReadInt()
+ o.g=s.ReadInt()
+ o.b=s.ReadInt()
+ o.id=s.ReadInt()
+ Return o
+ End Function
+
+ Method Save:TVectorGfxLine(s:TStream)
+ s.WriteInt(i1)
+ s.WriteInt(i2)
+ s.WriteInt(r)
+ s.WriteInt(g)
+ s.WriteInt(b)
+ s.WriteInt(id)
+ End Method
+End Type
+
+Private
+
+Type Static
+ Global linedraw:TVectorGfxLineStyle
+
+ Function Init()
+ linedraw=New LineSolid
+ End Function
+End Type
+
+Type LineSolid Extends TVectorGfxLineStyle
+ Method LineToCollisionMap:Int(x1:Int, y1:Int, x2:Int, y2:Int, r:Int, g:Int, b:Int, id:Int, obj:TVectorGfxObject, line:Int, colmap:TVectorGfxCollisionMap, actor:Int, list:TList)
+ Local mask:Int=0
+ Local lp:TList=DoLine(x1,y1,x2,y2)
+
+ SetColor(r,g,b)
+
+ For Local p:TAlgoPoint=EachIn lp
+ If colmap
+ If actor
+ Local c:TVectorGfxCollision=colmap.GetCollision(p.x,p.y)
+
+ If c
+ mask:|c.mask
+ If list
+ list.AddLast(c)
+ EndIf
+ EndIf
+ Else
+ mask:|colmap.SetCollision(p.x,p.y,id,obj,line)
+ EndIf
+ EndIf
+ Plot(p.x,p.y)
+ Next
+
+ Return mask
+ End Method
+
+ Method LineToPointList:Int(x1:Int, y1:Int, x2:Int, y2:Int, r:Int, g:Int, b:Int, list:TList)
+ Local mask:Int=0
+ Local lp:TList=DoLine(x1,y1,x2,y2)
+
+ SetColor(r,g,b)
+
+ For Local p:TAlgoPoint=EachIn lp
+ Plot(p.x,p.y)
+ list.AddLast(TVectorGfxPoint.Create(p.x,p.y))
+ Next
+
+ Return mask
+ End Method
+End Type
+
+Static.Init()
|