Drop 2000 squares into a pile at 30+fps

My thought is to then build in touch to destroy areas in the pile and let it collapse in an exciting way…

It seems to surge a little which I think is the setContext being quite heavy in use…

--# Main

-- Use this function to perform your initial setup
function setup()
    displayMode(FULLSCREEN)
    myFPSReporter = FPSReporter(4)
    watch("t.grains[1]")
    t = Terrain()
    cycles = 0
    w2 = WIDTH / 2
    h2 = HEIGHT / 2
    bImg = image(WIDTH, HEIGHT)
    setContext(bImg)
    background(40,40,50)
    f=1
end

-- This function gets called once every frame
function draw()
    f=f+1
    if cycles < 2000 then
        t:addGrain()
        cycles=cycles+1
    end
    -- This sets a dark background color 
    background(40, 40, 50)
    if f==10 then
        setContext(bImg)
        t:park()
        setContext()
        f=1
    end
    sprite(bImg, w2, h2)
    t:draw()
    myFPSReporter:draw(4)
    
    
    -- Do your drawing here
    
end


--# Terrain
Terrain = class()

function Terrain:init(x)
    -- you can accept and set parameters here
    self.grains = {}
    self.edges = {}
    self.edges[1] = physics.body(EDGE, vec2(0,0), vec2(WIDTH,0))
    self.edges[2] = physics.body(EDGE, vec2(0,0), vec2(0,HEIGHT))
    self.edges[3] = physics.body(EDGE, vec2(WIDTH,0), vec2(WIDTH,HEIGHT))
end

function Terrain:addGrain()
    local size = math.random(3,10)
    self.grains[cycles] = {size = size, body = physics.body(POLYGON, vec2(-size,-size), vec2(-size,size), vec2(size,size), vec2(size, -size))}
    self.grains[cycles].body.position = vec2(math.random(20,WIDTH-300),HEIGHT - math.random(1,20))
end

function Terrain:draw()
    -- Codea does not automatically call this method
    for k,v in pairs(self.grains) do
        if v.body.type ~= STATIC then
            pushMatrix()
            translate(v.body.x, v.body.y)
            rotate(v.body.angle)
            rect(-v.size,-v.size, v.size*2, v.size*2)
            popMatrix() 
        end
    end
end

function Terrain:park()
    for k,v in pairs(self.grains) do
        if v.body.type ~= STATIC then
            if v.body.type ~= STATIC and v.body.y < HEIGHT - 30 and v.body.linearVelocity:len() < 1 then
                v.body.type = STATIC
                pushMatrix()
                translate(v.body.x, v.body.y)
                rotate(v.body.angle)
                rect(-v.size,-v.size, v.size*2, v.size*2)
                popMatrix() 
            end
        end
    end
end

function Terrain:touched(touch)
    -- Codea does not automatically call this method
end

--# FPSReporter
FPSReporter = class()

function FPSReporter:init(rate)
    self.spacing = 1/rate
    self.last = ElapsedTime
    self.count = 0
    self.rate = 60
end

function FPSReporter:draw(pos)
    self.count = self.count + 1
    local now = ElapsedTime
    local delta = now - self.last
    if delta >= self.spacing then
        self.rate = self.count/delta
        self.count = 0
        self.last = now
    end
    pushStyle()
    local s = string.format("%d", self.rate)
    local w, h = textSize(s)
    textMode(CENTER)
    fontSize(18)
    font("Inconsolata")
    fill(255)
    pos = pos - 1
    local x = math.floor(pos/2) % 2 * (WIDTH - w) + w/2
    local y = pos % 2 * (HEIGHT - h) + h/2
    text(s, x, y)  
    popStyle()
end

@spacemonkey this is a lovely demo. Thanks for sharing!

May be collapsing, I mean destroying, some particles rises the FPS.