Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion

General question regarding physics.body EDGE

in Questions Posts: 28

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

Comments

  • dave1707dave1707 Mod
    edited May 2 Posts: 5,744

    @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.

  • dave1707dave1707 Mod
    edited May 2 Posts: 5,744

    @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
    
  • Posts: 28

    @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.

  • dave1707dave1707 Mod
    Posts: 5,744

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

  • Posts: 28

    @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
    
  • dave1707dave1707 Mod
    Posts: 5,744

    @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.

  • Posts: 28

    @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...

  • dave1707dave1707 Mod
    Posts: 5,744

    @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.

  • dave1707dave1707 Mod
    Posts: 5,744

    @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
    
  • Posts: 28

    @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.

  • dave1707dave1707 Mod
    edited May 7 Posts: 5,744

    @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
    
Sign In or Register to comment.