Probably completely irrelevant, but it's something to play with.
Strict
Const MAX_POINTS = 20
'Local fullscreen
'If AppArgs.length = 1
' fullScreen = True
'ElseIf AppArgs[1].ToLower() = "/p"
' fullscreen = False
' 'mainWindow = AppArgs[2]
'EndIf
Type TPoint
Field x#, y#
Field vx#, vy#
Function create:TPoint(x, y)
Local thisPoint:TPoint = New TPoint
thisPoint.x# = x
thisPoint.y# = y
Return thisPoint
End Function
End Type
Local windowWidth = GadgetWidth(Desktop())
Local windowHeight = GadgetHeight(Desktop())
SetGraphicsDriver GLMax2DDriver()
SeedRnd MilliSecs()
Local mainWindow:TGadget = CreateWindow("Silly String", 0, 0, windowWidth, windowHeight, Null, Null)
Local mainCanvas:TGadget = CreateCanvas(0, 0, ClientWidth(mainWindow), ClientHeight(mainWindow), mainWindow)
SetGraphics CanvasGraphics(mainCanvas)
Local points:TPoint[MAX_POINTS]
For Local p=0 Until MAX_POINTS
points[p] = TPoint.Create(Rand(0, windowWidth - 1), Rand(0, windowHeight - 1))
points[p].vx# = Rnd(-2, 2)
points[p].vy# = Rnd(-2, 2)
Next
Local looseness# = 1
Local stepSize# = 0.01
Local showPoints = 0
Local currentR# = Rand(255), currentG# = Rand(255), currentB# = Rand(255)
Local targetR# = Rand(255), targetG# = Rand(255), targetB# = Rand(255)
Local colourStep# = 0.1
Local deltaR# = colourStep# * Sgn(targetR# - currentR#)
Local deltaG# = colourStep# * Sgn(targetG# - currentG#)
Local deltaB# = colourStep# * Sgn(targetB# - currentB#)
Local mainTimer:TTimer = CreateTimer(60)
SetBlend ALPHABLEND
glEnable(GL_LINE_SMOOTH)
SetLineWidth 2
ActivateGadget mainCanvas
Repeat
Select WaitEvent()
Case EVENT_MOUSEDOWN, EVENT_KEYDOWN
End
Case EVENT_TIMERTICK
For Local p=0 Until MAX_POINTS
points[p].x# :+ points[p].vx#
If points[p].x# <= 0
points[p].vx# = -points[p].vx#
points[p].x# = 0
ElseIf points[p].x# >= (windowWidth - 1)
points[p].vx# = -points[p].vx#
points[p].x# = (windowWidth - 1)
EndIf
points[p].y# :+ points[p].vy#
If points[p].y# <= 0
points[p].vy# = -points[p].vy#
points[p].y# = 0
ElseIf points[p].y# >= (windowHeight - 1)
points[p].vy# = -points[p].vy#
points[p].y# = (windowHeight - 1)
EndIf
Next
currentR# :+ deltaR#
If Abs(targetR# - currentR#) < Abs(deltaR#)
currentR# = targetR#
targetR# = Rand(255)
deltaR# = colourStep# * Sgn(targetR# - currentR#)
EndIf
currentG# :+ deltaG#
If Abs(targetG# - currentG#) < Abs(deltaG#)
currentG# = targetG#
targetG# = Rand(255)
deltaG# = colourStep# * Sgn(targetG# - currentG#)
EndIf
currentB# :+ deltaB#
If Abs(targetB# - currentB#) < Abs(deltaB#)
currentB# = targetB#
targetB# = Rand(255)
deltaB# = colourStep# * Sgn(targetB# - currentB#)
EndIf
RedrawGadget mainCanvas
Case EVENT_GADGETPAINT
Cls
SetColor currentR#, currentG#, currentB#
For Local p=0 Until MAX_POINTS
If p
DrawCardinalSpline(points[p - 1], points[p], points[(p + 1) Mod MAX_POINTS], points[(p + 2) Mod MAX_POINTS], stepSize#, looseness#)
Else
DrawCardinalSpline(points[MAX_POINTS - 1], points[0], points[1], points[2], stepSize#, looseness#)
EndIf
If showPoints Then DrawOval points[p].x# - 5, points[p].y# - 5, 10, 10
Next
Flip
End Select
Forever
End
'Spline code adapted from some crusty old QBasic source I found on the net,
'so possibly not the most efficient implementation.
Function DrawCardinalSpline(p0:TPoint, p1:TPoint, p2:TPoint, p3:TPoint, s#=0.1, l#=0.5)
Local t2# = 2.0 - l#, t3# = l# - 2.0, t5# = 2.0 * l#, t6# = l# - 3.0, t7# = 3 - t5#
Local d#, d1#, d2#, h1#, h2#, h3#, out = False
Local p:TPoint = New TPoint, op:TPoint = TPoint.Create(p1.x, p1.y)
Repeat
If d# > 1
d# = 1
out = True
EndIf
d1# = d# * d#
d2# = d1# * d#
p.x# = (((-l# * p0.x#) + (t2# * p1.x#) + (t3# * p2.x#) + (l# * p3.x#)) * d2#) +..
(((t5# * p0.x#) + (t6# * p1.x#) + (t7# * p2.x#) + (-l# * p3.x#)) * d1#) +..
(((-l# * p0.x#) + (l# * p2.x#)) * d#) + p1.x#
p.y# = (((-l# * p0.y#) + (t2# * p1.y#) + (t3# * p2.y#) + (l# * p3.y#)) * d2#) +..
(((t5# * p0.y#) + (t6# * p1.y#) + (t7# * p2.y#) + (-l# * p3.y#)) * d1#) +..
(((-l# * p0.y#) + (l# * p2.y#)) * d#) + p1.y#
DrawLine op.x#, op.y#, p.x#, p.y#, False
op.x# = p.x#
op.y# = p.y#
d# :+ s#
Until out
End Function