Haha, solved it! Didn't make any changes to the library, I put all necessary code into the main source.
To draw the bezier curve, you make many small line segments. Starting from the beginning of the curve, I add the distance of each line segment together, recording the overall distance that each point lies from the start. Also, store the total length of the curve.
Then, take that total distance and your step value (whatever you want the time index to be between 0 and 1) to calculate how far you are along the curve. Now that we know how far we are, we can look up which line segment we currently fall on.
Determine the length of that line segment by subtracting its value(the precalculated values we did) from the value of the next point ahead. Then calculate how far along this single segment we actually are by subtracting that points value (its distance from the start of the curve, not its length) from the overall distance we are at on the curve.
Divide those two values to get a new time value for that line segment. I've explained each line in the code comments which might be easier to understand.
setVirtualResolution(800,600)
`setsyncrate(60,1)
`setvirtualresolution(getdevicewidth(),getdeviceheight())
`setdisplayaspect(getdeviceheight()/getdevicewidth())
#include "Bezier Curve Library.agc"
gosub _bc_setup // this has to be called before any BC command, preferably before anything at all
global debug = 1
global closed = 0 // whether or not to draw as open or closed curve
setprintsize(16)
//////////////////////////////////////////////////
// Stuff I added for this example
//////////////////////////////////////////////////
Global dim stuff#[0]
totalLength# = 0
thing = createSprite(0)
setSpriteSize(thing, 5, 5)
setSpriteColor(thing, 255,0,0,255)
//////////////////////////////////////////////////
//////////////////////////////////////////////////
repeat
if debug=1
print("--Debug Information--")
print("Frames per second: "+str(screenfps(),0))
print("Screen size: "+str(getdevicewidth())+"x"+str(getdeviceheight()))
print("Camera position, x: "+str(getviewoffsetx())+" y: "+str(getviewoffsety()))
print("--Variables--")
print("")
endif
print("Click to add new points to the curve")
print("Press SPACE to remove all curve points")
print("Press C to draw as a closed curve")
print("Press O to draw as an open curve")
print("The green line points to the closest point on the curve to the mouse")
//////////////////////////////////////////////////
// Constant speed around the bezier curve
//////////////////////////////////////////////////
if bc_getcurvesegmentpointcount() > 0
// Simply to control an even time update
if timestamp <= getMilliseconds()
// A point on the bezier curver lies between 0 and 1.
t# = t# + 0.001
// If time goes beyond 1, subtract 1. This will provide
// a more even movement.
if t# > 1 then t# = t# - 1
// How far from the beginning of the curve are we
seg# = totalLength# * t#
// Find the point at the beginning of the line segment that we are currently on
s = getCurveSegmentPointAtDistance(seg#)
// Calculate the length of this line segment
segLength# = stuff#[s+1] - stuff#[s]
// Calculate how far along this single line segment we are
partSegLength# = seg# - stuff#[s]
n# = partSegLength# / segLength#
// Use some linear interpolation to determine the coordinates on this line segment
x = bc_getcurvesegmentpointx(s) + (bc_getcurvesegmentpointx(s+1)-bc_getcurvesegmentpointx(s))*n#
y = bc_getcurvesegmentpointy(s) + (bc_getcurvesegmentpointy(s+1)-bc_getcurvesegmentpointy(s))*n#
// Position the sprite
setSpritePosition(thing, x, y)
// Update timer
timestamp = getMilliseconds() + 20
endif
endif
gosub _processinput
gosub _drawcurve
sync()
until getRawKeyPressed(27) = 1
end
_processinput:
if getpointerpressed()=1
bc_addcurvepoint(getrawmousex(),getrawmousey())
if closed = 0
bc_calculateopencurvesegmentpoints()
else
bc_calculateclosedcurvesegmentpoints()
endif
//////////////////////////////////////////////////
// Added these two lines here
//////////////////////////////////////////////////
dim stuff#[bc_getcurvesegmentpointcount()]
totalLength# = calculateLength()
endif
if getrawkeystate(32) = 1
bc_removecurvepoints()
endif
if getrawkeystate(67) = 1
closed=1
bc_calculateclosedcurvesegmentpoints()
endif
if getrawkeystate(79) = 1
closed = 0
bc_calculateopencurvesegmentpoints()
endif
return
_drawcurve:
if bc_getcurvesegmentpointcount() > 0
for i = 0 to bc_getcurvesegmentpointcount() - 2 //normally use -1, but I want to stop 1 early of the end of the array
drawline(bc_getcurvesegmentpointx(i),bc_getcurvesegmentpointy(i),bc_getcurvesegmentpointx(i+1),bc_getcurvesegmentpointy(i+1),255,255,255)
next i
bc_calculateclosestpointtocurve(getrawmousex(),getrawmousey())
drawline(getrawmousex(),getrawmousey(),bc_getclosestpointx(),bc_getclosestpointy(),0,255,0)
endif
return
//////////////////////////////////////////////////
// Calculates the distance of each point from the
// beginning of the curve.
// Returns total length of the curve.
//////////////////////////////////////////////////
function calculateLength()
total# = 0
if bc_getcurvesegmentpointcount() > 0
for i = 0 to bc_getcurvesegmentpointcount() - 2
x# = (bc_getcurvesegmentpointx(i)-bc_getcurvesegmentpointx(i+1))^2
y# = (bc_getcurvesegmentpointy(i)-bc_getcurvesegmentpointy(i+1))^2
d# = sqrt(x# + y#)
total# = total# + d#
stuff#[i] = total#
next i
endif
endfunction total#
//////////////////////////////////////////////////
// Finds which line segment that 'd#' falls on.
// Since this array is technically a sorted list,
// it can be modified into a binary search for
// improved lookup speeds.
//////////////////////////////////////////////////
function getCurveSegmentPointAtDistance(d#)
for i = 0 to bc_getcurvesegmentpointcount() - 2
if d# >= stuff#[i] and d# < stuff#[i+1] then exitfunction i
next i
endfunction 0