My special FX

Code:

--# Main
-- FX
displayMode(FULLSCREEN)
function setup()
    supportedOrientations(LANDSCAPE_LEFT)
    iparameter("balls",2,100,200)
    iparameter("number",1,100,200)
    tab1={}    -- table for objects
    radius=WIDTH/(balls*3)    -- starting radius
    prevBalls=0
    prevNumber=0
    getOffset()
    create()
end     

function draw()
    background(0, 0, 0, 255)
    smooth()
    -- balls or number were changed with iparameters
    if prevBalls ~= balls or prevNumber ~= number then
        create()
    end

    for z=1,balls do
        
        ball=tab1[z].bodyA             
        --ball shine
        fill(255, 255, 255, 42)
        ellipse(ball.x,ball.y,ball.radius*3)
        ellipse(ball.x,ball.y,ball.radius*2)
        ellipse(ball.x,ball.y,ball.radius*1.5)
        fill(255, 255, 255, 170)  
        ellipse(ball.x,ball.y,ball.radius*1)

    end         
end

function create()
    if prevBalls ~= balls or prevNumber ~= number then 
        for z=1,prevBalls do
            tab1[z].bodyA:destroy()
            tab1[z]:destroy()
            tab1[z]=nil
        end

        if number > balls-1 then
            number = balls-1
        end
        
        prevBalls=balls       
        prevNumber=number
        radius=WIDTH/(balls*3)
        getOffset()
    end

    for z=1,balls do
        hanger=physics.body(CIRCLE,0)
        hanger.type=STATIC
        hanger.x=z*r2+offset
        hanger.y=1000
        ball=physics.body(CIRCLE,10)
        ball.restitution=0
        ball.x=z*r2+offset
        ball.y= math.random(1000)

        if z<=number then
           ball.linearVelocity=vec2(math.random(100),math.random(100)) 
        end 

        tab1[z]=physics.joint(REVOLUTE,ball,hanger,hanger.position)
    end 
end 

function getOffset()

    r2=radius*2+2
    c=r2*balls-r2
    offset=((WIDTH-c)/2)-r2
end

That’s an interesting effect. I found the spacing (r2) and getOffset() logic difficult to follow, and produced the simplified code below while working through it.


supportedOrientations(LANDSCAPE_LEFT)
displayMode(FULLSCREEN)

function setup()    
    create(200)
end

function create(n)         -- n > 1
    joints = {}            -- table for joints  
    delta = WIDTH/(n - 1)  -- spacing (more simple)
    for i = 1, n do
        local x = WIDTH/2 + delta * ((i - 1) - (n - 1)/2) -- Ball starts below its hanger
        local hanger = physics.body(CIRCLE, 0)
        hanger.type = STATIC
        hanger.x = x
        hanger.y = 1000
        local ball = physics.body(CIRCLE, 10)
        ball.restitution = 0
        ball.x = x
        ball.y = math.random(0, HEIGHT) -- Keep the ball on the viewer
        ball.linearVelocity = vec2(math.random(100), 0) -- Only horizontal component relevant
        joints[i] = physics.joint(REVOLUTE, ball, hanger,
            hanger.position)
    end
end    

function draw()
    background(0)
    smooth()
    for i, joint in ipairs(joints) do
        local ball = joint.bodyA
        local x = ball.x
        local y = ball.y
        local r = ball.radius
        fill(255, 42)
        ellipse(x, y, r * 3)
        ellipse(x, y, r * 2)
        ellipse(x, y, r * 1.5)
        fill(255, 170)  
        ellipse(x, y, r)
    end         
end

It is kinda like a lava lamp, just needs colour and some 70’s music…

Can you code Music.