Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Fat Duck :: bezier paths - Lua [Codea]
BezierCurve = class()
function BezierCurve:init()
    self:generate_new_bezier()
end
function BezierCurve:draw()
    for i=1,(#self.curve)-1 do
        line(self.curve[i].x,self.curve[i].y,self.curve[i+1].x,self.curve[i+1].y)
    end
end
function BezierCurve:generate_new_bezier()
    self.curve={}
    self:ComputeBezier(
        { 
         vec2(math.random(-6,-1),1),
         vec2(math.random(9,66),math.random(111,333)),
         vec2(math.random(111,333),math.random(111,666)),
         vec2(math.random(666,WIDTH),math.random(66,HEIGHT)),
         --vec2(math.random(777,),math.random(666,HEIGHT)),
         
        },99
    )
end
function BezierCurve:PointOnCubicBezier(cp, t )
    local   ax, bx, cx
    local   ay, by, cy
    local   tSquared, tCubed
    local   result = vec2(0,0)
 
  --  /* calculation of the polinomial coeficients */
 
    cx = 3.0 * (cp[2].x - cp[1].x)
    bx = 3.0 * (cp[1].x - cp[2].x) - cx
    ax = cp[4].x - cp[1].x - cx - bx
 
    cy = 3.0 * (cp[2].y - cp[1].y)
    by = 3.0 * (cp[3].y - cp[2].y) - cy
    ay = cp[4].y - cp[1].y - cy - by
 
  --  /* calculate the curve point at parameter value t */
 
    tSquared = t * t
    tCubed = tSquared * t
 
    result.x = (ax * tCubed) + (bx * tSquared) + (cx * t) + cp[1].x
    result.y = (ay * tCubed) + (by * tSquared) + (cy * t) + cp[1].y
 
    return result
end
 
-- ComputeBezier fills an array of Point2D structs with the curve   
-- points generated from the control points cp. Caller must 
-- allocate sufficient memory for the result, which is 
-- <sizeof(Point2D) numberOfPoints>
 
function BezierCurve:ComputeBezier( cp, numberOfPoints
    local   dt
    local   i
 
    dt = 1.0 / ( numberOfPoints - 1 )
 
    for i = 1, numberOfPoints do
        self.curve[i] = self:PointOnCubicBezier( cp, i*dt )
        i = i + 1
    end
end
Duck = class()
-- duck modes
DUCK_FLYING = 1
DUCK_HITTED = 2
function Duck:init()
    self.farts = {}
    self.bezier = BezierCurve()
    self.point = 1 -- start from bezier curve point number 1
    self.state = DUCK_FLYING
end
function Duck:fly()
    self.point = self.point + math.random(2)
    if self.point>(#self.bezier.curve) then
        self.point = 1
        self.bezier:generate_new_bezier()
    end
    text("🚀", --use emoji or sprite here to draw the bird ;-)
        self.bezier.curve[self.point].x,
        self.bezier.curve[self.point].y
        )
end
function Duck:fall()
    sprite("Tyrian Remastered:Space Bug Larvae",
        self.bezier.curve[self.point].x,
        self.bezier.curve[self.point].y
    )
end
function Duck:draw()
    --self.bezier:draw() -- debug purposes
    if self.state==DUCK_FLYING then
        self:fly()
    elseif self.state == DUCK_HITTED then
        self:fall()
    end
end
function Duck:touched(touch)
    if self.state ~= DUCK_FLYING then return false end
    if (touch.state == ENDED) then
        local t = vec2(touch.x,touch.y)
        local p = vec2(self.bezier.curve[self.point].x, self.bezier.curve[self.point].y)
        local d = t:distSqr(p)
        --print(d)
        if d<170 then
            self.state = DUCK_HITTED
            return true
        end
    end
end
-- Main
displayMode(FULLSCREEN)
supportedOrientations(LANDSCAPE_ANY)
MAX_DUCKS = 6
-- Use this function to perform your initial setup
function setup()
    print("Fart Duck!")
    scene = Scene()
    ducks = {}
    table.insert(ducks, Duck())
end
-- This function gets called once every frame
function draw()
    scene:draw()
    -- setup emoji:
    strokeWidth(5)
    fontSize(66)
    font("AppleColorEmoji")
    -- draw:
    for i,d in ipairs(ducks) do
        d:draw()
    end
    -- more ducks:
    if (#ducks)<MAX_DUCKS and math.random(100)>90 then
        table.insert(ducks, Duck())
    end
end
function touched(touch)
    for i,d in ipairs(ducks) do
        if d:touched(touch) then -- one duck hitted at a time (one touch)
            return
        end
    end
end
Scene = class()
function Scene:init()
    self.rows = math.abs( WIDTH/100 )
    self.cols = math.abs( HEIGHT/171)+2
end
function Scene:draw()
    --backingMode()
    background(0, 0, 0, 4)
    
    --for j=0 ,self.cols do
       -- for i=0, self.rows do
           -- sprite("Planet Cute:Roof South",i*101,90+(j*120) )
        --end
   -- endJ
end
function Scene:touched(touch)
    
        
   
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.