General question regarding physics.body EDGE

I’m just starting to dig into codeas built in physics, and have been playing around with some basic shapes and physics types. Everything’s been fairly straight forward, but I’m a little confused about the use of physics.body EDGE. Are edges generally meant to remain stationary?

My goal is to simply be able to control the pitch of the floor with my 2 parameters. So far I can raise the line/edge easily enough, but I am unable to lower the edge once raised, it almost seems as though I’m creating many ghost edges that get left behind… then Codea crashes. This behavior leads me to believe that I may be going about things incorrectly.

How can I make my line as drawn behave more like a solid object?

function setup()
    -- parameters to control the line
    -- line starting point
    x1=0
    parameter.number("y1",0,HEIGHT/3,100)
    -- line end point
    x2=WIDTH
    parameter.number("y2",0,HEIGHT/3,100)
    -- line thickness
    lw = 10

    -- create an image to represent the physics object
    img=readImage("Platformer Art:Crate")
    id=img.width/2 -- image dimensions
    --create the physics object
    p_img = physics.body(POLYGON,vec2(-id,id),vec2(-id,-id),
    vec2(id,-id),vec2(id,id))
    p_img.x = WIDTH/2
    p_img.y = HEIGHT/2
    p_img.angle=math.random(0,360)
    p_img.gravityScale = 1     -- gravity 
    p_img.restitution = 0.7    -- bounce
    p_img.friction = 0.001     -- friction
    p_img.linearDamping = .3   -- drag
    p_img.linearVelocity = vec2(math.random(400),math.random(400))
    p_img.info="box"           -- object name

    CreateWalls()   
end

function draw()
    background(10,10,20) stroke(255) strokeWidth(lw)
    -- Draw line
    line(x1,y1,x2,y2)    
    -- Move the edge along with line?
    physics.body(EDGE,vec2(x1,y1),vec2(x2,y2))
    -- draw the box
    pushMatrix() 
        translate(p_img.x, p_img.y)
        rotate(p_img.angle)
        sprite(img,0,0)
    popMatrix() 
end

--creates the frame
function CreateWalls()
    WallL = CreateEdge(1,1,1,HEIGHT-1,1.0) 
    WallR = CreateEdge(WIDTH-1,0,WIDTH-1,HEIGHT-1,0.9) 
    WallB = CreateEdge(1,1,WIDTH-1,1,0.2) 
    WallT = CreateEdge(1,HEIGHT-1,WIDTH-1,HEIGHT-1,0.7)
end

--creates one Edge/wall
function CreateEdge(x,y,x1,y1,r)
    local w = physics.body(EDGE,vec2(x,y),vec2(x1,y1)) -- vec2
    w.restitution=r 
    return w
end

@Circuit Basically you are creating ghost edges. Once you create a physics object, that object remains until you destroy it. Since an edge is static, it remains where you first defined it. That’s why you were able to raise the edge and it looked like it was working, but once you started to lower it, the upper ones were still there. Look in the reference under physics for destroy.

EDIT: Also, you shouldn’t create a physics object in the draw function unless you have code to limit how many you create. That will cause Codea to crash because you’re creating physic objects at 60 times per second and you’ll eventually run out of memory.

@Circuit Here’s a quick fix. There’s probably a better way, but I was in a hurry.

EDIT: Modified my first fix that was here. Here’s a better way to handle changing and destroying the physics object. See where I added the comments added change and added this function. I also removed some code from the draw function.

function setup()
    -- parameters to control the line
    -- line starting point
    x1=0
    parameter.number("y1",0,HEIGHT/3,100,change)    -- added change
    -- line end point
    x2=WIDTH
    parameter.number("y2",0,HEIGHT/3,100,change)    -- added change
    -- line thickness
    lw = 10

    -- create an image to represent the physics object
    img=readImage("Platformer Art:Crate")
    id=img.width/2 -- image dimensions
    --create the physics object
    p_img = physics.body(POLYGON,vec2(-id,id),vec2(-id,-id),
    vec2(id,-id),vec2(id,id))
    p_img.x = WIDTH/2
    p_img.y = HEIGHT/2
    p_img.angle=math.random(0,360)
    p_img.gravityScale = 1     -- gravity 
    p_img.restitution = 0.7    -- bounce
    p_img.friction = 0.001     -- friction
    p_img.linearDamping = .3   -- drag
    p_img.linearVelocity = vec2(math.random(400),math.random(400))
    p_img.info="box"           -- object name

    CreateWalls()   
end

function change()   -- added this function
    -- Move the edge along with line?
    if p~=nil then
        p:destroy()
    end
    p=physics.body(EDGE,vec2(x1,y1),vec2(x2,y2))
end

function draw()
    background(10,10,20) stroke(255) strokeWidth(lw)
    -- Draw line
    line(x1,y1,x2,y2)    
    -- draw the box
    pushMatrix() 
        translate(p_img.x, p_img.y)
        rotate(p_img.angle)
        sprite(img,0,0)
    popMatrix() 
end

--creates the frame
function CreateWalls()
    WallL = CreateEdge(1,1,1,HEIGHT-1,1.0) 
    WallR = CreateEdge(WIDTH-1,0,WIDTH-1,HEIGHT-1,0.9) 
    WallB = CreateEdge(1,1,WIDTH-1,1,0.2) 
    WallT = CreateEdge(1,HEIGHT-1,WIDTH-1,HEIGHT-1,0.7)
end

--creates one Edge/wall
function CreateEdge(x,y,x1,y1,r)
    local w = physics.body(EDGE,vec2(x,y),vec2(x1,y1)) -- vec2
    w.restitution=r 
    return w
end

@dave1707 thank you for your quick response and both fixes. I kind of figured it was something along those lines causing the issue/crash, but was unaware that I could destroy the objects in that manner. I was starting to think that an edge was not meant to be utilized in this way.

My current issue I’m now trying to wrap my head around is getting my edge to apply force back to the box in a somewhat realistic manner. I was hoping the line would end up with a slightly more pinball paddle like feel, but I’m not sure exactly how to achieve this with an edge. I’ve been playing around with linearVelocity a bit, but I’m clearly missing something.

@Circuit Giving the box a greater than 1 restitution value will cause it to react to the edge more.

@dave1707 Actually, that’s one of the first things I tried, and it did improve things slightly but I felt the box was then too bouncy/unrealistic and almost never stopped moving. What I’m noticing is that the box is only affected by its own momentum. Once the box sits still for a moment, I am unable to transfer momentum to it by moving the line up quickly (in an attempt to toss the box back into the air). It seems to just lift the box to the level of the line and then drops it from that point.

Here I added a 2nd red line using CHAIN that is a little more like what I was going for. It has a lot more influence over the box, but I’m having trouble getting the red line to move in the same manner using my original parameters. My experimentation with velocity has been a little confusing to say the very least.

How would I go about getting the red line/CHAIN to move and control like my original white EDGE using my first two parameters?

function setup()
    -- parameters to control the line
    -- line starting point
    x1=0
    parameter.number("y1",0,HEIGHT/3,100,change)    -- added change
    -- line end point
    x2=WIDTH
    parameter.number("y2",0,HEIGHT/3,100,change)    -- added change
    -- line thickness
    lw = 10
--line 2 parameters (Red Line)
    parameter.number("redY",-400,400,0)
    line2=physics.body(CHAIN,false,vec2(-WIDTH/2,0),vec2(WIDTH/2,0))
    line2.x=WIDTH/2
    line2.y=50
    line2.angle = 0
    line2.type=KINEMATIC
----
    -- create an image to represent the physics object
    img=readImage("Platformer Art:Crate")
    id=img.width/2 -- image dimensions
    --create the physics object
    p_img = physics.body(POLYGON,vec2(-id,id),vec2(-id,-id),
    vec2(id,-id),vec2(id,id))
    p_img.bullet = true
    p_img.x = WIDTH/2
    p_img.y = HEIGHT/2
    p_img.angle=math.random(0,360)
    p_img.gravityScale = 1     -- gravity 
    p_img.restitution = 0.7    -- bounce
    p_img.friction = 0.001     -- friction
    p_img.linearDamping = .3   -- drag
    p_img.linearVelocity = vec2(math.random(400),math.random(400))
    p_img.info="box"           -- object name

    CreateWalls()   
end

function change()   -- added this function
    -- Move the edge along with line?
    if p~=nil then
        p:destroy()
    end
    p=physics.body(EDGE,vec2(x1,y1),vec2(x2,y2))
end

function draw()
    background(10,10,20) stroke(255) strokeWidth(lw)
    -- Draw line
    line(x1,y1,x2,y2)    
--line 2 (CHAIN)
    stroke(255, 0, 0, 255)
    strokeWidth(2)
    line(line2.x-WIDTH/2,line2.y,line2.x+WIDTH/2,line2.y)
    line2.linearVelocity=vec2(0 ,redY)
---- 
    -- draw the box
    pushMatrix() 
        translate(p_img.x, p_img.y)
        rotate(p_img.angle)
        sprite(img,0,0)
    popMatrix() 
end

--creates the frame
function CreateWalls()
    WallL = CreateEdge(1,1,1,HEIGHT-1,1.0) 
    WallR = CreateEdge(WIDTH-1,0,WIDTH-1,HEIGHT-1,0.9) 
    WallB = CreateEdge(1,1,WIDTH-1,1,0.2) 
    WallT = CreateEdge(1,HEIGHT-1,WIDTH-1,HEIGHT-1,0.7)
end

--creates one Edge/wall
function CreateEdge(x,y,x1,y1,r)
    local w = physics.body(EDGE,vec2(x,y),vec2(x1,y1)) -- vec2
    w.restitution=r 
    return w
end

@Circuit The problem you’re having with the edge is because you’re overriding the physics engine when you’re moving it. Anytime you use physics objects, you have to let the physics engine do everything. In my example above, when I destroy and recreate the edge in the function change, the edge doesn’t have any velocity, so the box doesn’t react to it like you expect. Anytime you want to manually move a physics, you have to give it a linearVelocity or angularVelocity.

@dave1707 Yeah, I was reading about that yesterday a bit. I spent about 3 hours last night messing around with both linearVelocity and angularVelocity to interact with my red line. I’m having a hard time figuring out how to use them both to control objects accurately. I get movement, just not always in the way I had intended.

Thanks again for all the help. It’s kinda funny that what started as just goofing around with the physics engine has now taken up days of my life. Oh Codea…

@Circuit Don’t look at it as taking up days of your life, look at it as you are learning about the physics engine. The more you play around with it, the more things you’ll run into, but the more you’ll learn. I’ve been playing around with Codea for 5 years and there’s still things I don’t know how to do. Of course there’s probably a lot I’ve forgotten, but relearning doesn’t take as long as the first time.

@Circuit Here’s something that might give you an idea. Use the parameter slider to vary the angular velocity of the polygon.

function setup()
    physics.continuous=true
    
    b2=physics.body(CIRCLE,0)
    b2.x=WIDTH/2
    b2.y=160
    b2.type=STATIC
    
    b3=physics.body(CIRCLE,20)
    b3.x=350
    b3.y=600
    b3.restitution=1
    
    e=physics.body(CHAIN,false,vec2(0,0),vec2(WIDTH,0),
            vec2(WIDTH,HEIGHT),vec2(0,HEIGHT),vec2(0,0))
    e.type=STATIC
    
    p2=physics.body(POLYGON,vec2(-150,-5),vec2(150,-5),vec2(150,5),vec2(-150,5))
    p2.x=WIDTH/2
    p2.y=160
    
    j3=physics.joint(REVOLUTE,p2,b2,b2.position)
    
    parameter.integer("ang",-720,720,0,inc)
end


function inc()
    p2.angularVelocity=ang
end

function draw()
    background(40, 40, 50)
    fill(255)
    stroke(255)
    strokeWidth(2)
    
    ellipse(b2.x,b2.y,5)
    ellipse(b3.x,b3.y,40)
    
    pushMatrix()
    translate(p2.x,p2.y)
    rotate(p2.angle)   
    line(-150,-5,150,-5)
    line(150,-5,150,5)
    line(150,5,-150,5)
    line(-150,5,-150,-5)
    popMatrix()
end

@dave1707 Actually, yesterday on my own, I had created an almost identical project to your most recent example. However, spinning the object is about all I can figure out how to do using angularVelocity and my slider. Controlling an object in this manner using angularVelocity and linearVelocity still seems quite awkward, and I find it very difficult to get the exact movement I’m aiming for.

Unfortunately, I’m still having a really hard time simulating the subtle behavior of my white line from my original post. Although, as you had previously stated, I am learning a heck of a lot about the physics engine along the way.

@Circuit Try this one. Hold your finger on the left half of the screen above or below the line to move it up or down. Do the same on the right half. You can move both edges at the same time.

displayMode(FULLSCREEN)

function setup()
    y1,y2=0,0 
      
    ball=physics.body(CIRCLE,20)
    ball.x=350
    ball.y=600
    ball.restitution=1
    
    edges=physics.body(CHAIN,false,vec2(0,0),vec2(WIDTH,0),
            vec2(WIDTH,HEIGHT),vec2(0,HEIGHT),vec2(0,0))
    edges.type=STATIC  
      
    ch1,ch2=200,200
    ch=physics.body(CHAIN,false,vec2(0,ch1),vec2(WIDTH,ch2))
end

function draw()
    background(40, 40, 50)
    fill(255)
    stroke(255)
    strokeWidth(2)    
    line(0,ch1,WIDTH,ch2)
    ellipse(ball.x,ball.y,40)   
    if l1~=0 or l2~=0 then 
        ch1=ch1+y1
        ch2=ch2+y2
        ch:destroy()
        ch=physics.body(CHAIN,false,vec2(0,ch1),vec2(WIDTH,ch2))
    end   
end

function touched(t)
    if t.state==BEGAN then
        if t.x<WIDTH/2 then
            if t.y>ch1 then
                y1=2
            else
                y1=-2
            end
        else
            if t.y>ch2 then
                y2=2
            else
                y2=-2
            end
        end
    end
    if t.state==ENDED then
        y1,y2=0,0
    end
end