Date: Mon, 21 Oct 1996 15:38:45 -0700 From: Eric WoodsWell, it sounded fun, so I spent a little time on it (too much time!), and learned some things along the way. My code to make a curved slider path follows.Subject: Re: Circular Slider Code... Steven Shane wrote about circular slider code... > The other day Robert sent out a neat variation on a slider handler. > but lets get funky and see if we can make the smile on a happy face > into a slider path.
The main thing I learned was that the way to construct something like this is to begin by constraining a sprite path along something simple (like a circle) and then further constrain it along something more complex (like an arc, which represents the smile on a happy face).
Here's some code you can use to constrain a sprite to a circle or an arc. Please note that when you define the limiting angles you are measuring clockwise from the x-axis (horizontal), not counter-clockwise like you typically do for standard graphing. (The reason for this, of course, is that a screen location is defined with down be positive, rather than negative.)
on mousedown
set constraintCenter = point(100,100)
set constraintRadius = 25.0
--* FOR CONSTRAINING TO AN ARC, ADD THESE ANGLES
set constraintAngleMin = 20 * pi()/180
set constraintAngleMax = 160 * pi()/180
repeat while the mouseDown
set mouseX = the mouseH - the locH of constraintCenter
set mouseY = the mouseV - the locV of constraintCenter
--* IF YOU JUST WANT TO CONSTRAIN TO A CIRCLE, USE THIS...
set mouseRadius = sqrt((mouseX * mouseX) + (mouseY * mouseY))
if mouseRadius = 0 then next repeat
set reductionRatio = constraintRadius/mouseRadius
set constrainedX = integer(mouseX * reductionRatio)
set constrainedY = integer(mouseY * reductionRatio)
--* IF YOU WANT TO CONSTRAIN TO AN ARC, ADD THIS...
if mouseX = 0 then next repeat
set mouseAngle = atan(float(mouseY)/float(mouseX))
if mouseX * mouseY > 0 then
if mouseX > 0 then set quadrant = 1
else set quadrant = 3
else
if mouseY > 0 then set quadrant = 2
else set quadrant = 4
end if
case quadrant of
1: set mouseAngle = mouseAngle
2: set mouseAngle = pi() + mouseAngle
3: set mouseAngle = pi() + mouseAngle
4: set mouseAngle = 2*pi() + mouseAngle
end case
if (mouseAngle > constraintAngleMax) OR
(mouseAngle << constraintAngleMin) then next repeat
set the loc of sprite the clickOn =
point(constrainedX, constrainedY) + constraintCenter
updatestage
end repeat
end
I separated the if-then clauses from the case clauses just for clarity
(to show that the if-then statements are in there to determine what
quadrant the arctangent function is describing). They could easily be
compressed into just the if-then statements.
Anyone want to come up with a more efficient method of doing this? Or to continue in the spirit of the first post, anyone want to try to add to this function the ability to constrain something to a path of arcs, instead of just one (for instance, an "S" or string made up of semi-circle arcs)?
Date: Thu, 24 Oct 1996 13:10:58 -0700 From: Eric WoodsWell, with some help from Darrel Plant and his bezier curve demo (see http://www.moshplant.com/direct-or/), I put several solutions to this constraint idea into one movie. The first two solutions I've already posted the code for (they were handlers that constrained a sprite to a circle or an arc and constrained a sprite to an angled line). The third solution is the one that could be a universal solution that John's code didn't handle -- constraint curves that have crossover points, such a bezier curve which loops back on itself. You can view the solution at http://home.earthlink.net/~lizneric/constraints/constraint.html. (Note: you can grab a copy of the movie, which isn't protected, by locating it in your browser's cache directory, openning it with Director and then saving it under a different name).Subject: Re: Circular Slider Code... At 5:16 PM -0700 10/23/96, John Dowdell wrote: >Richard Schedler writes on Oct 22, "Or even a wavy line? Sorry maths wasn't my >strong point either. Anyone got any ideas?" Gary Martin later adds, "Can an >object be constrained to a line on an angle?"
The key to the bezier curve solution (and thanks to Darrel for the insight
on this) is to measure the distance between the current slider position
(call it 't') and the mouse position, and compare this with the distance
between t+1 and t-1 positions and the mouse -- then move the slider to the
position which is closest to the mouse. The primary code for this function
is below, and it probably makes more sense than my explanation.
The bezier curve solution can map a slider graphic to any *single* bezier
curve. But it should be easy put several beziers together simply by
offsetting the variable which defines the location on the curve. In other
words, let t range from 0 to the number of curves and let t1, t2, t3, etc.
be defined as t1 = t, t2=t-1, t3=t-2, etc. Then when t<1, you map to curve
1, and when 1
on mousedown
--* these globals are used to define the bezier curve
--* the curve gets defined in another handler
global x1,y1,ax,ay,bx,by,cx,cy,t
set fx = []
set fy = []
set dx = []
set dy = []
set x0 = 0
set y0 = 0
set numPoints = 50
if t < 0 then set t = 0
repeat while the stillDown
set prevt = t
repeat with i = 1 to 3
set t = prevt + (i - 2)
--* put in equation here to determine X and Y for t-1, t, and t+1
set t1 = float (t) / numPoints
set t2 = float (t1 * t1)
set t3 = float (t2 * t1)
set constraintX = ax * t3 + bx * t2 + cx * t1 + x1
set constraintY = ay * t3 + by * t2 + cy * t1 + y1
setAt(fx,i,constraintX)
setAt(fy,i,constraintY)
end repeat
--* this calculates the closest point for t-1, t, and t+1
set x0 = the mouseH
set y0 = the mouseV
set dx = fx - x0
set dy = fy - y0
set r2 = dx * dx + dy * dy
set r2min = min(r2)
set i = getPos(r2, r2min)
set t = prevt + (i - 2)
if t > numPoints then set t = numPoints
else if (t < 0) then set t = 0
--* put in equation here, using the new t to determine X and Y
set t1 = float (t) / numPoints
set t2 = float (t1 * t1)
set t3 = float (t2 * t1)
set constrainedX = integer (ax * t3 + bx * t2 + cx * t1 + x1)
set constrainedY = integer (ay * t3 + by * t2 + cy * t1 + y1)
--* this relocates the control sprite
set the locH of sprite 12 = constrainedX
set the locV of sprite 12 = constrainedY
updateStage
end repeat
end