Skip to content

Instantly share code, notes, and snippets.

@ursetto
Created November 18, 2018 00:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ursetto/24bc8efe721c8aa1c163d74d49e86438 to your computer and use it in GitHub Desktop.
Save ursetto/24bc8efe721c8aa1c163d74d49e86438 to your computer and use it in GitHub Desktop.
-- pico8 bezier demo https://github.com/ursetto
-- derived from https://twitter.com/freyaholmer/status/1063633408411295744
w1=40 w2=w1+16
p0={x=64-w1,y=90,c=8}
p1={x=64-w2,y=30,c=9}
p2={x=64+w2,y=30,c=10}
p3={x=64+w1,y=90,c=11}
◆={p0,p1,p2,p3}
cls()
t=0
-- t := 0..1.
function lerp(p1,p2,t)
local x local y
x = p1.x + (p2.x-p1.x) * t
y = p1.y + (p2.y-p1.y) * t
return {x=x,y=y}
end
function linep(p0,p1,c)
line(p0.x,p0.y,p1.x,p1.y,c)
end
function circp(p,c)
circfill(p.x,p.y,1,c) -- p.c?
end
function bezier(p0,p1,p2,p3,t)
local x=bezier★(p0.x,p1.x,p2.x,p3.x,t)
local y=bezier★(p0.y,p1.y,p2.y,p3.y,t)
return {x=x,y=y}
end
function bezier★(x0,x1,x2,x3,t)
-- returns a 1-d point
-- p = p0*(-t^3+3t^2-3t+1)+
-- p1*(3t^3-6t^2+3t)+
-- p2*(-3t^3+3t^2)+
-- p3*(t^3)
-- p = p0*(1-t)(1-t)(1-t) +
-- p1*3*t*(1-t)(1-t) +
-- p2*3*t*t(1-t) +
-- p3*t*t*t
local omt = 1-t
local omt2 = omt*omt
local t2 = t*t
return x0 * omt2 * omt +
x1 * 3 * t * omt2 +
x2 * 3 * t2 * omt +
x3 * t * t2
end
function beziercurve(p0,p1,p2,p3,tmin,tmax,step,c)
local t=tmin
p = bezier(p0,p1,p2,p3,t)
pset(p.x,p.y,c)
t += step
while (t < tmax) do
pold = p
p = bezier(p0,p1,p2,p3,t)
--pset(p.x,p.y,c)
linep(pold,p,c)
t += step
end
t = tmax
p = bezier(p0,p1,p2,p3,t)
pset(p.x,p.y,c)
end
function _draw()
cls()
local p
local t0=t/90 -- speed divisor
-- convert 1..-1 to 0..1
t0=(cos(t0+0.5)+1)/2
-- draw the traversed curve
-- up to the current point
beziercurve(p0,p1,p2,p3,0,t0,0.02,1)
for p in all(◆) do
circp(p,p.c)
end
-- interpolate once
pi0=lerp(p0,p1,t0)
pi1=lerp(p1,p2,t0)
pi2=lerp(p2,p3,t0)
linep(pi0,pi1,5)
linep(pi1,pi2,5)
circp(pi0,6)
circp(pi1,6)
circp(pi2,6)
-- interpolate again
pii0=lerp(pi0,pi1,t0)
pii1=lerp(pi1,pi2,t0)
linep(pii0,pii1,5)
circp(pii0,6)
circp(pii1,6)
-- interpolate once more
piii0=lerp(pii0,pii1,t0)
circp(piii0,12)
end
function _update60()
t=t+0.5
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment