Code archives/Miscellaneous/simple graph library
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
| updated: 4th Feb, 2003 three files are included. monitor.bb contains all the functions needed. there are two extra examples to show how it all works. You can use this to monitor vaiables or fps or anything thaty changes like stats in the game with a funky graph. it's mostly for debugging really. I think it's pretty funky. Hope someone makes use of it. Any questions: matt.birdinsky@... | |||||
; -------------------------------------
; author: matthew griffiths
; Funky Graph Library (v1.1); use as you like.
; Updated: 1st Feb, 2003
; There was a bug with the update
; time in the updateMonitor function.
; works ok now.
;
; contact: matt.birdinsky@gmail.com
; -------------------------------------
; available functions:
; createMonitor ; constructor
; processTime ; gets the time taken to process a cycle
; getValue ; get a value from the monitor
; updateMonitor ; updates the monitor with data
; drawMonitor ; draws the graph to the screen
; getMonitorFromName ; an function that gets an object from a name
; setSaveHistory ; sets and starts a save log to an image
; there are two ways you can access these function:
; either by name$ or using the object. For more info, see the functions themselves
Const MONITOR_MAXIMUM_IMAGE_WIDTH=1000
Type monitor
Field value#[2]
Field w,h
Field r,g,b
Field name$
Field image,invert
Field maxValue,processTime
Field born,updateTime
Field x,saveHistory$
End Type
Function createMonitor.monitor(name$,r,g,b,maxValue,h,w, updateTime=500,invert=-1)
m.monitor=New monitor
m\name=Lower(name)
m\r=r : m\g=g : m\b=b
m\maxValue=maxValue
m\w=w : m\h=h
m\image=CreateImage(w,h)
m\born=MilliSecs()
m\updateTime=updateTime
m\saveHistory=""
m\x=0
m\invert=invert
Return m
End Function
; set to "" for no save history,
; othewise, set to location and file, like: "c:\game\output"
Function setSaveHistory(o.monitor,n$,location$="")
If o=Null
v.monitor=getMonitorFromName(n)
Else
v.monitor=o
EndIf
v\saveHistory=location
End Function
Function processTime(o.monitor,n$)
If o=Null
v.monitor=getMonitorFromName(n)
Else
v.monitor=o
EndIf
If v= Null Then Return -1
Return v\processTime
End Function
Function getValue#(o.monitor,n$,a=0)
If o=Null
v.monitor=getMonitorFromName(n)
Else
v.monitor=o
EndIf
If v= Null Then Return
Return v\value[a]
End Function
Function deletePreviousLogs(n$)
f=ReadDir(CurrentDir())
Repeat
file$=Lower(NextFile(f))
If file="" Then Exit
If Instr(file,Lower(n))
If Lower(Right(file,4))=".bmp"
DeleteFile file
EndIf
EndIf
Forever
CloseDir f
End Function
Function updateMonitor(o.monitor,n$,value#, average=0, updateTime=-1 ,drawLineAtLength=2)
If o=Null
v.monitor=getMonitorFromName(n)
Else
v.monitor=o
EndIf
If v= Null Then Return
marker_colour=80
marker_height#=0.15
If (MilliSecs()-v\born) > v\updateTime
If updateTime <> -1 Then v\updateTime=updateTime
v\born=MilliSecs()
Else
Return
EndIf
m=MilliSecs()
If updateTime <> -1
; update our... erm... update time
If v\updateTime <> updateTime
v\updateTime=updateTime
v\born=MilliSecs()
EndIf
EndIf
v\value[2]=v\value[1]
If average
v\value[1]=(value+v\value[1])/2
Else
v\value[1]=value
EndIf
v\x=v\x+1
If v\x > v\w
v\x=1
If Len(v\saveHistory)
; save this to an image
If FileSize(v\saveHistory+".bmp")
i=LoadImage(v\saveHistory+".bmp")
new_width=ImageWidth(i)+v\w
If new_width < MONITOR_MAXIMUM_IMAGE_WIDTH
p=CreateImage(new_width,v\h) ; create a new "frame"
CopyRect(0,0,ImageWidth(i),v\h,0,0,ImageBuffer(i),ImageBuffer(p))
CopyRect(0,0,v\w,v\h,new_width-v\w,0,ImageBuffer(v\image),ImageBuffer(p))
SetBuffer ImageBuffer(p)
Color marker_colour,marker_colour,marker_colour
Rect ImageWidth(i)-1,0,1,(v\h*marker_height)
Rect ImageWidth(i)-1,v\h-(v\h*marker_height),1,(v\h*marker_height)
SetBuffer BackBuffer()
SaveBuffer(ImageBuffer(p),v\saveHistory+".bmp")
Else
; it's a bit big, don't bother
EndIf
FreeImage i
Else
p=CreateImage(v\w,v\h)
CopyRect(0,0,v\w,v\h,0,0,ImageBuffer(v\image),ImageBuffer(p))
SetBuffer ImageBuffer(p)
Color marker_colour,marker_colour,marker_colour
Rect 0,0,1,(v\h*marker_height)
Rect 0,v\h-(v\h*marker_height),1,(v\h*marker_height)
Rect v\w-1,0,1,(v\h*marker_height)
Rect v\w-1,v\h-(v\h*marker_height),1,(v\h*marker_height)
SetBuffer BackBuffer()
SaveBuffer(ImageBuffer(v\image),v\saveHistory+".bmp")
EndIf
EndIf
SetBuffer ImageBuffer(v\image)
Color 0,0,0
Rect 0,0,v\w,v\h,1
SetBuffer BackBuffer()
EndIf
SetBuffer ImageBuffer(v\image)
Color v\r,v\g,v\b
delta#=(Float(v\h)/Float(v\MaxValue))
If v\invert=-1
y1#=v\h-(delta*v\value[1])
y2#=v\h-(delta*v\value[2])
Else
y1#=(delta*v\value[1])
y2#=(delta*v\value[2])
EndIf
svy#=Abs(y1-y2)
length# = Sqr((svy * svy))
If length > drawLineAtLength
Line v\x-1,y2,v\x,y1
EndIf
Rect v\x,y1-1,1,1
SetBuffer BackBuffer()
v\processTime=MilliSecs()-m
End Function
; set outline to 0 to get no outline, otherwise,
; set it to a colour, 20 being 20,20,20
Function drawMonitor(o.monitor,n$,x,y,outputText$="",outline=20)
If o=Null
v.monitor=getMonitorFromName(n)
Else
v.monitor=o
EndIf
If v= Null Then Return
If outline
Color outline,outline,outline
Rect x,y, v\w,1
Rect x,y+v\h, v\w,1
EndIf
DrawImage v\image,x,y
If Len(outputText)
outPutText=outPutText+v\value[1]
Color v\r,v\g,v\b
Text (x+v\w)-StringWidth(outPutText),(y+v\h)-FontHeight(),outputText
EndIf
End Function
Function getMonitorFromName.monitor(n$)
For m.monitor=Each monitor
If Lower(m\name)=Lower(n)
Return m
EndIf
Next
End Function
Function deleteMonitor(o.monitor,n$)
If o=Null
v.monitor=getMonitorFromName(n)
Else
v.monitor=o
EndIf
If v= Null Then Return
FreeImage v\image
Delete v
End Function
; -----------------------------------
; Very simple example
; -----------------------------------
Include "monitor.bb"
Graphics 640,480,0,2
SetBuffer BackBuffer()
createMonitor("monitor",255,255,0,GraphicsHeight(),20,60,500) ; every half a second
While KeyHit(1)=0
Cls
updateMonitor(Null,"monitor",MouseY()) ; update value
drawMonitor(Null,"monitor",0,1) ; draw it
;drawMonitor(Null,"monitor",2,2,"",255) ; try adding two drawMonitors.
Flip
Wend
deleteMonitor(Null,"monitor")
End
; -----------------------------------
; Extended example
; -----------------------------------
; monitor example
; the monitor allows you to create a graph and add data to it.
; the graph is split up into three section:
; 1) create it and set certain values (float or int)
; 2) update it with a value
; 3) draw it to the screen
; LOGGING
; there's also an option to save upto 1000 pixels worth of graph to an image
; to see how this works, please see the example below. You can change the 1000 is you wish.
; you'll need to set the log to active using 'setSaveHistory(o.monitor,n$,location$="")', location
; being the filename and location you want to save, like "c:\game\fps log". the .bmp is added automatically
; in order to stop this being affected by old logs, you can use the 'deletePreviousLogs(n$)' function
; which will delete all files with n in their name.
; CREATING:
; when you create a monitor, you specify the name (case insenstive) and colour of the monitor graph
; in r,g,b; it's maximum value (to scale), like an fps graph would probably have a maximum value
; of 120 Or something. then specifiy the width and height of the graph, and the updatetime in milliseconds.
;
; createMonitor.monitor(name$,r,g,b,maxValue,height,width, updateTime=500,invert=-1)
;
; invert.. well, inverts the graph values. so if it is set to -1, which is default,
; a value of 100 in a graph of maximum 100 will be at the top.
; set it to 1 and 100 in a max 100 graph will be at the bottom.
; When using the functions, the first parameter is a monitor object. if you specifiy NULL,
; the function will use the name you specifiy next to search for the monitor.
; obviously the former method is faster, but the latter easier to use.
; ---------------------------------------------------------------------------
; UPDATING
; when you update the monitor, you may update it every cycle, as the monitor uses
; an internal method of updating depeding on your initial values. In this function though,
; you can change has fast the monitor updates with a parameter.
;
; updateMonitor(o.monitor,n$,value#, average=0, updateTime=-1 ,drawLineAtLength=2)
;
; when you set average to 1, the previous value is added to the current and divided by two
; giving a slightly smoother graph.
; the updateTime parameter allows you to change the updatetime. set this to -1 if you do not widh
; to change the value.
; ie:
; updateMonitor(Null,"fps",myFPS, 0, -1)
; is the same as doing:
; updateMonitor(Null,"fps",myFPS, 0)
; as the updateTime defaults to -1
; DRAWING
; you have to draw the monitor to the screen to be able to see it.
; you don't have to, obviously.
;
; drawMonitor(o.monitor,n$,x,y,outputText$="",outline=20)
;
; the output text will output the text you add in the parameter and add the value on the end,
; so, "fps:" will output "fps:12.2". to change where, mess with the functions in 'monitor.bb'
; outline is set to 20 by default. if this is 0, there will be no line drawn, otherwise,
; a line of colour outline,outline,outline (always a grey of some sort) will draw
; a maximum and minimum line. good so you know what the hell is a high and low value.
Include "monitor.bb"
Graphics 640,480,0,2
SetBuffer BackBuffer()
updateTime=80
average=0
logHistory=0
; you can invert the graph result, by adding a 1 at the end. the default is -1
m1.monitor=createMonitor("mousey()", 255,0, 0, GraphicsHeight(), 100,300, updateTime)
m2.monitor=createMonitor("mousex()", 0, 255,0, GraphicsWidth(), 100,300, updateTime)
m1.monitor=createMonitor("mousey() invert", 255,0, 120, GraphicsHeight(), 100,300, updateTime,1)
m2.monitor=createMonitor("mousex() invert", 120, 255,0, GraphicsWidth(), 100,300, updateTime,1)
; delete any previously created log images in the directory
; use with caution
deletePreviousLogs("mousex() log")
deletePreviousLogs("mousey() log")
deletePreviousLogs("mousey() invert log")
deletePreviousLogs("mousex() invert log")
While KeyHit(1)=0
Cls
updateMonitor(Null,"mousey()",MouseY(),average, updateTime)
updateMonitor(Null,"mousex()",MouseX(),average, updateTime)
updateMonitor(Null,"mousex() invert",MouseX(),average, updateTime)
updateMonitor(Null,"mousey() invert",MouseY(),average, updateTime)
drawMonitor(Null,"mousey()",0,150, "",20)
drawMonitor(Null,"mousex()",0,150, "",20)
drawMonitor(Null,"mousey() invert",0,150, "",20)
drawMonitor(Null,"mousex() invert",0,150, "",20)
; and some debug code..
Color 255,255,255
Text 0,20,"Time to process mousey(): "+processTime(Null,"mousey()")+" ms"
Text 0,40,"Time to process mousex(): "+processTime(Null,"mousex()")+" ms"
Text 0,60,"Average: "+average
Text 0,80,"Log History: "+logHistory
Text 0,100,"Update time: "+updateTime
If KeyHit(57) Then average=1-average
If KeyHit(35)
logHistory=1-logHistory
If logHistory
setSaveHistory(Null,"mousex()","mousex() log")
setSaveHistory(Null,"mousey()","mousey() log")
Else
setSaveHistory(Null,"mousex()","")
setSaveHistory(Null,"mousey()","")
EndIf
EndIf
If KeyDown(2) Then updateTime=updateTime-10
If KeyDown(3) Then updateTime=updateTime+10
If updateTime < 0 Then updateTime=0
Flip
Wend
deleteMonitor(Null,"mousey()")
deleteMonitor(Null,"mousex()")
deleteMonitor(Null,"mousey() invert")
deleteMonitor(Null,"mousex() invert")
End |
Comments
None.
Code Archives Forum