Cloth example

I was playing around with the ROPE command and that turned into this example. The Rate is slow on an iPad Air, but it still runs OK. If it’s too slow, reduce the size of x1 or y1. Slide your finger around the screen to move the corner with the red dot.


displayMode(FULLSCREEN)
supportedOrientations(PORTRAIT_ANY)

function setup()
    x1=15
    y1=30
    size=25
    dx,dy=0,0
    tab={}
    for x=1,x1 do
        tab[x]={}
        for y=1,y1 do
            local r=physics.body(CIRCLE,0)
            r.x=10+x*size
            r.y=900-y*size
            r.gravityScale=.5
            if y==1 then
                r.type=STATIC
            end           
            tab[x][y]=r
            r=nil
        end
    end
    jVert={}
    for x=1,x1 do
        for y=2,y1 do
            local j=physics.joint(ROPE,tab[x][y-1],tab[x][y],
                tab[x][y-1].position,tab[x][y].position,size)
            table.insert(jVert,j)
            j=nil
        end
    end
    jHorz={}
    for x=2,x1 do
        for y=1,y1 do
            local j=physics.joint(ROPE,tab[x-1][y],tab[x][y],
                tab[x-1][y].position,tab[x][y].position,size)
            table.insert(jHorz,j)
            j=nil
        end
    end
    
end

function draw()
    background(192, 225, 208, 255)
    stroke(0, 161, 255, 255)
    strokeWidth(2)
    for x=1,x1 do
        for y=1,y1 do
            if x>1 then
                line(tab[x-1][y].x,tab[x-1][y].y,tab[x][y].x,tab[x][y].y)
            end
            if y>1 then
                line(tab[x][y-1].x,tab[x][y-1].y,tab[x][y].x,tab[x][y].y)
            end
        end
    end  
    stroke(255,0,0)
    fill(255,0,0)
    ellipse(tab[1][1].x,tab[1][1].y,10)
    text("Cloth example",WIDTH/2,HEIGHT-10)
    text("Slide your finger to move the red dot",WIDTH/2,HEIGHT-40)
    text("Rate  "..1//DeltaTime,WIDTH/2,HEIGHT-70)
    text("KB Memory used  "..collectgarbage("count")//1,WIDTH/2,HEIGHT-100)
end

function touched(t)
    if t.state==MOVING then
        for z=1,x1-1 do
            tab[z][1].type=DYNAMIC
        end
        dx=dx+t.deltaX*200
        dy=dy+t.deltaY*200
        tab[1][1].linearVelocity=vec2(dx,dy)
    end
    if t.state==ENDED then
        dx,dy=0,0
        tab[1][1].type=STATIC
        collectgarbage()
    end    
end

Very impressive @dave1707 a unique recreation of the cloth example and good speed for 15x10 on iPad Air (55fps).

@Luatee Thanks. I noticed that if I make this change, CIRCLE,1 to CIRCLE,0 it runs a little faster. Changed the code above.

EDIT: It also doesn’t appear to use much memory like it did with CIRCLE,1 .

            local r=physics.body(CIRCLE,0)

@dave1707 that’s quite interesting, it’s using less than half the memory. I wouldn’t have thought a circle with no size could work considering box2D joints work using mass as part of the equation. I can get 25fps at 15x30.

Edit: playing around I made dragging the anchor a bit more stable:

displayMode(FULLSCREEN)
supportedOrientations(LANDSCAPE_ANY)

function setup()
    x1=15
    y1=15
    size=25
    dx,dy=0,0
    tab={}
    for x=1,x1 do
        tab[x]={}
        for y=1,y1 do
            local r=physics.body(CIRCLE,0)
            r.x=10+x*size
            r.y=600-y*size
            r.gravityScale=.5
            if y==1 then
                r.type=STATIC
            end           
            tab[x][y]=r
            r=nil
        end
    end
    jVert={}
    for x=1,x1 do
        for y=2,y1 do
            local j=physics.joint(ROPE,tab[x][y-1],tab[x][y],
                tab[x][y-1].position,tab[x][y].position,size)
            table.insert(jVert,j)
            j=nil
        end
    end
    jHorz={}
    for x=2,x1 do
        for y=1,y1 do
            local j=physics.joint(ROPE,tab[x-1][y],tab[x][y],
                tab[x-1][y].position,tab[x][y].position,size)
            table.insert(jHorz,j)
            j=nil
        end
    end
    for z=2,x1-1 do
            tab[z][1].type=DYNAMIC
        end
end

function draw()
    background(192, 225, 208, 255)
    stroke(0, 161, 255, 255)
    strokeWidth(2)
    for x=1,x1 do
        for y=1,y1 do
            if x>1 then
                line(tab[x-1][y].x,tab[x-1][y].y,tab[x][y].x,tab[x][y].y)
            end
            if y>1 then
                line(tab[x][y-1].x,tab[x][y-1].y,tab[x][y].x,tab[x][y].y)
            end
        end
    end  
    stroke(255,0,0)
    fill(255,0,0)
    ellipse(tab[1][1].x,tab[1][1].y,10)
    text("Cloth example",WIDTH/2,HEIGHT-10)
    text("Slide your finger to move the red dot",WIDTH/2,HEIGHT-40)
    text("Rate  "..1//DeltaTime,WIDTH/2,HEIGHT-70)
    text("KB Memory used  "..collectgarbage("count")//1,WIDTH/2,HEIGHT-100)
end

function touched(t)
    if t.state==MOVING then
        for z=1,1 do
            tab[z][1].type=KINEMATIC
        end
        dx=dx+t.deltaX*2
        dy=dy+t.deltaY*2
        tab[1][1].linearVelocity=vec2(dx,dy)
    end
    if t.state==ENDED then
        dx,dy=0,0
        for z=1,1 do
            tab[z][1].type=STATIC
        end
        collectgarbage()
    end    
end


@Luatee I was surprised that using 0 affected the memory as much as it did. I noticed that the change you made, KINEMATIC, allowed the top of the cloth to be stretched which affects the way it looks. I like the change that allowed the cloth to droop so I modified the original code to do that.

Bravo Guys! That really looks reallistic!

miraculous effect