Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Bezier Animation Demo

edited July 2012 in Examples Posts: 202

At least this is something that also runs with loveCodea on Linux. The problems under Linux seem to be sprite related, I think.

Visit this inspirational page to see what you can expect from the code below:

http://www.jasondavies.com/animated-bezier/

(And I leave you wondering if this posting is more about loveCodea or Bezier Curves.)


if require then require("loveCodea") end -- Interactive Bezier Curve Animation, loosely inspired by this: -- http://www.jasondavies.com/animated-bezier/ -- Tap on circle to create a new node. -- Drag node to X to delete. BEZIER_STEP = 0.01 STARTING_DOTS = 4 dots = {} -- animation progess, 0 ... 1 p = 0 touches = {} touched_dots = {} function setup() for i = 1, STARTING_DOTS do NewDot() end -- for drawing fine lines noSmooth() end function draw() p = p + 0.01 if p > 1 then p = 0 end background(255, 255, 230, 255) local curve = {} for i,d in ipairs(dots) do table.insert(curve, d.x) table.insert(curve, d.y) end Bezier(curve, p) -- green O in upper right fill(0, 255, 0) ellipse(WIDTH - 20, HEIGHT - 20, 40, 40) -- red X in lower right stroke(255, 0, 0) line(WIDTH, 0, WIDTH - 40, 40) line(WIDTH, 40, WIDTH - 40, 0) end function touched(touch) if touch.state == ENDED then touches[touch.id] = nil touched_dots[touch.id] = nil -- Circle touched, create a node if touch.x > WIDTH - 40 and touch.y > HEIGHT - 40 then NewDot() end else touches[touch.id] = touch local td = touched_dots[touch.id] -- Touch has hit nothing yet, try finding a dot nearby if td == nil then touched_dots[touch.id] = FindDot(touch.x, touch.y) else td.x = touch.x td.y = touch.y -- Dragging to X, delete node if td:Contains(WIDTH - 20, 20) then for i,d in ipairs(dots) do if d == td then table.remove(dots, i) break end end end end end end -- Creates a new dot somewhere function NewDot() table.insert(dots, Dot(math.random(500), math.random(500))) end -- Returns if a there's a dot at x/y function FindDot(x, y) local dot = nil for i,d in ipairs(dots) do if d:Contains(x, y) then dot = d end end return dot end -- Draws Bezier and helper lines. -- xy_list: list with x/y coordinates of the nodes -- p: progress (0 ... 1) function Bezier(xy_list, p) DrawBezierOverlay(xy_list, p) DrawBezier(xy_list, p) end -- Draws Bezier Curve function DrawBezier(xy_list, p) if #xy_list == 0 then return end stroke(0, 0, 0) strokeWidth(3) local x0, y0 for i = 0, p, BEZIER_STEP do local x, y = ReduceChain(xy_list, i) if i > 0 then line(x0, y0, x, y) end x0, y0 = x, y end end -- Reduces the xy_list to a single x/y coordinate at progress p. function ReduceChain(xy_list, p) local n_coords = #xy_list / 2 while n_coords > 1 do xy_list = ReduceChainBy1(xy_list, p) n_coords = n_coords - 1 end return xy_list[1], xy_list[2] end function DrawBezierOverlay(xy_list, p) local n_coords = #xy_list / 2 local r = 20 while n_coords > 0 do DrawChain(xy_list, r) xy_list = ReduceChainBy1(xy_list, p) n_coords = n_coords - 1 r = 10 end end -- Reduces the xy_list by one coordinate at progress p, -- returning the reduced list. function ReduceChainBy1(xy_list, p) local reduced = {} local n_coords = #xy_list / 2 local x0, y0 for i = 1, n_coords do local x = xy_list[i * 2 - 1] local y = xy_list[i * 2] -- skip first point, cannot draw a line with only 1 point if i > 1 then local xi = x0 + (x - x0) * p local yi = y0 + (y - y0) * p table.insert(reduced, xi) table.insert(reduced, yi) end x0, y0 = x, y end return reduced end -- Draws a chain, i.e. a series of dots linked by lines. -- Draws the primary nodes as well as the reduced chain. function DrawChain(xy_list, r) local n_coords = #xy_list / 2 local x0 local y0 stroke(255, 100, 0) strokeWidth(1) fill(255, 100, 0) if n_coords == 1 then fill(100, 100, 100) end for i = 1, n_coords do local x = xy_list[i * 2 - 1] local y = xy_list[i * 2] if i > 1 then line(x0, y0, x, y) end ellipse(x, y, r) x0, y0 = x, y end end Dot = class() function Dot:init(x, y) self.x = x self.y = y self.r = 20 end function Dot:Contains(x, y) local dx = x - self.x local dy = y - self.y return (dx * dx) + (dy * dy) <= (self.r * self.r) end

Comments

  • Posts: 505

    Hi @codeslinger,

    Sooooperb!!!!

    Hope we can get these routines incorporated into the core code so that we can create Bezier designs within Codea. I'll play around with your code to see if I can make a small demo with it.

    Thanks for this.

    Bri_G

    :)

  • Posts: 2,820

    WOW!'Great for entertaining simple minds like mine!

  • Posts: 59

    This is my favorite codea forum download yet by far... I just added like 100 points and it goes bannanas!!!

Sign In or Register to comment.