Bezier Path Generator - TerryRitchie - 10-06-2024
Has anyone worked with Bezier curves?
I'm attempting to write a path generator for items such as enemy ships, like when the ships form up in Galaga at the start of a level, or during a challenging stage.
The code below is a quick and dirty Bezier path maker. It works, but no matter what I set the variable Detail to the path comes up jagged, with a sort of stair step effect to it. Does anyone know how I can smooth this out if possible?
Code: (Select All) TYPE POINT
x AS INTEGER
y AS INTEGER
END TYPE
DIM Curve(3) AS POINT
REDIM Path(0) AS POINT
DIM p AS POINT
Curve(0).x = 0
Curve(0).y = 479
Curve(1).x = 639
Curve(1).y = 239
Curve(2).x = 0
Curve(2).y = 239
Curve(3).x = 639
Curve(3).y = 0
SCREEN _NEWIMAGE(640, 480, 32)
Detail = .00001
FOR t = 0 TO 1 STEP Detail
CurvePoint Curve(), p, t
New = -1
FOR i = 0 TO UBOUND(Path) - 1
IF p.x = Path(i).x AND p.y = Path(i).y THEN
New = 0
EXIT FOR
END IF
NEXT i
IF New THEN
Path(UBOUND(Path)) = p
REDIM _PRESERVE Path(UBOUND(Path) + 1) AS POINT
END IF
'PSET (p.x, p.y)
NEXT t
PSET (Path(0).x, Path(0).y)
FOR i = 1 TO UBOUND(Path) - 1
LINE -(Path(i).x, Path(i).y)
NEXT i
PRINT UBOUND(Path)
SUB CurvePoint (c() AS POINT, p AS POINT, t AS SINGLE)
'Quick and dirty Bezier point calculator
'Note: only works for 4 points
p.x = (1 - t) * (1 - t) * (1 - t) * c(0).x + 3 * (1 - t) * (1 - t) * t * c(1).x + 3 * (1 - t) * t * t * c(2).x + t * t * t * c(3).x
p.y = (1 - t) * (1 - t) * (1 - t) * c(0).y + 3 * (1 - t) * (1 - t) * t * c(1).y + 3 * (1 - t) * t * t * c(2).y + t * t * t * c(3).y
END SUB
RE: Bezier Path Generator - TerryRitchie - 10-06-2024
After playing around with some other Bezier code it would seem this is normal. I streamlined the program above to be much faster and yield different numbers of points when using AND or OR in line 30 of the code.
When using AND the curve is very smooth when connected with lines. However, some detail is lost if successive X or Y coordinates are equal, not ideal for enemy ship path following but great when connecting the points with lines.
When using OR the data points are perfect for path following.
Code: (Select All) TYPE POINT
x AS INTEGER
y AS INTEGER
END TYPE
DIM Curve(3) AS POINT
REDIM Path(1) AS POINT
DIM p AS POINT
Curve(0).x = 0
Curve(0).y = 479
Curve(1).x = 639
Curve(1).y = 239
Curve(2).x = 0
Curve(2).y = 239
Curve(3).x = 639
Curve(3).y = 0
SCREEN _NEWIMAGE(640, 480, 32)
Detail = .0001
t = 0
DO
CurvePoint Curve(), p, t
IF p.x <> Path(UBOUND(Path) - 1).x OR p.y <> Path(UBOUND(Path) - 1).y THEN ' OR can be changed to AND for different results
Path(UBOUND(Path)) = p
REDIM _PRESERVE Path(UBOUND(Path) + 1) AS POINT
PSET (p.x, p.y)
END IF
t = t + Detail
LOOP UNTIL t > 1
'PSET (Path(1).x, Path(1).y) ' Draw lines instead when using AND above (very smooth)
'FOR i = 2 TO UBOUND(Path) - 1 ' OR yeilds 1102 points
' LINE -(Path(i).x, Path(i).y) ' AND yields 368 points that need to be connected with lines
'NEXT i
PRINT UBOUND(Path) - 1
SLEEP
SUB CurvePoint (c() AS POINT, p AS POINT, t AS SINGLE)
'Quick and dirty Bezier point calculator
'Note: only works for 4 points
DIM a AS SINGLE
DIM b AS SINGLE
DIM c AS SINGLE
DIM d AS SINGLE
a = (1 - t) * (1 - t) * (1 - t)
b = 3 * (1 - t) * (1 - t) * t
c = 3 * (1 - t) * t * t
d = t * t * t
p.x = a * c(0).x + b * c(1).x + c * c(2).x + d * c(3).x
p.y = a * c(0).y + b * c(1).y + c * c(2).y + d * c(3).y
'p.x = (1 - t) * (1 - t) * (1 - t) * c(0).x + 3 * (1 - t) * (1 - t) * t * c(1).x + 3 * (1 - t) * t * t * c(2).x + t * t * t * c(3).x
'p.y = (1 - t) * (1 - t) * (1 - t) * c(0).y + 3 * (1 - t) * (1 - t) * t * c(1).y + 3 * (1 - t) * t * t * c(2).y + t * t * t * c(3).y
END SUB
RE: Bezier Path Generator - vince - 10-07-2024
check out this mod
Code: (Select All)
defdbl a-z
sw = 800
sh = 600
screen _newimage(sw, sh, 32)
n = 8
dim x(n), y(n)
x(0)=sw/2:y(0)=sh/7
x(1)=sw/3:y(1)=2*sh/7
x(2)=2*sw/3:y(2)=3*sh/7
x(3)=sw/5:y(3)=4*sh/7
x(4)=sw/2:y(4)=5*sh/7
x(5)=sw/5:y(5)=5*sh/7
x(6)=sw/2:y(6)=6*sh/7
x(7)=4*sw/5:y(7)=6*sh/7
cls
preset (x(0), y(0))
for i=0 to n - 1
line -(x(i), y(i)), _rgb(55,55,0)
circle (x(i), y(i)), 3, _rgb(255,255,0)
next
preset (x(0), y(0))
dt = 0.0001
for t=0 to 1 step dt
bx = 0
by = 0
'dx = 0
'dy = 0
for i=0 to n - 1
bin = 1
for j=1 to i
bin = bin*(n - j)/j
next
p = bin*((1 - t)^(n - 1 - i))*(t^i)
bx = bx + p*x(i)
by = by + p*y(i)
'q = bin*((1 - t)^(n - 2 - i))*(t^(i - 1))*(i - n*t + t)
'dx = dx + q*x(i)
'dy = dy + q*y(i)
next
if abs(bx - ox)>1 and abs(by - oy)>1 then
line -(bx, by), _rgb(255,0,0)
ox = bx
oy = by
end if
'm = sqr(dx*dx + dy*dy)
'line -step(10*dx/m, 10*dy/m), _rgb(0,255,0)
next
line -(bx, by), _rgb(255,0,0)
RE: Bezier Path Generator - TerryRitchie - 10-07-2024
(10-07-2024, 06:29 AM)vince Wrote: check out this mod
Code: (Select All)
defdbl a-z
sw = 800
sh = 600
screen _newimage(sw, sh, 32)
n = 8
dim x(n), y(n)
x(0)=sw/2:y(0)=sh/7
x(1)=sw/3:y(1)=2*sh/7
x(2)=2*sw/3:y(2)=3*sh/7
x(3)=sw/5:y(3)=4*sh/7
x(4)=sw/2:y(4)=5*sh/7
x(5)=sw/5:y(5)=5*sh/7
x(6)=sw/2:y(6)=6*sh/7
x(7)=4*sw/5:y(7)=6*sh/7
cls
preset (x(0), y(0))
for i=0 to n - 1
line -(x(i), y(i)), _rgb(55,55,0)
circle (x(i), y(i)), 3, _rgb(255,255,0)
next
preset (x(0), y(0))
dt = 0.0001
for t=0 to 1 step dt
bx = 0
by = 0
'dx = 0
'dy = 0
for i=0 to n - 1
bin = 1
for j=1 to i
bin = bin*(n - j)/j
next
p = bin*((1 - t)^(n - 1 - i))*(t^i)
bx = bx + p*x(i)
by = by + p*y(i)
'q = bin*((1 - t)^(n - 2 - i))*(t^(i - 1))*(i - n*t + t)
'dx = dx + q*x(i)
'dy = dy + q*y(i)
next
if abs(bx - ox)>1 and abs(by - oy)>1 then
line -(bx, by), _rgb(255,0,0)
ox = bx
oy = by
end if
'm = sqr(dx*dx + dy*dy)
'line -step(10*dx/m, 10*dy/m), _rgb(0,255,0)
next
line -(bx, by), _rgb(255,0,0)
Whoa, thank you. I was wondering how to incorporate more than 4 points into the mix. So simple.
RE: Bezier Path Generator - Petr - 10-07-2024
Thank you all for sharing it. It is all very interestingly.
|