Howdy, Stranger!

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

Phyisc balls and distance joints

Hi,
I've a rather stupid question.
I create two physic bodies CIRCLE of radius R=10 and link them with a physics joint DISTANCE anchored at each ball's body.position with a distance length of 2body.radius
Then I draw these bodies as ellipse(0,0,2
body.radius) with a strokewidth(1).

However, the two circles are (just) not touching each other. Why?

Comments

  • Posts: 31

    And furthermore, what is wrong with my code (below) that it doesn't update the balls based on the parameter?
    (If I use math.random() instead, the updates first work and then suddenly stop.)

  • Posts: 31
    -- My Test 
    
    function setup()
        parameter.number("LinkL",0,500,105)
    
        b1 = physics.body(CIRCLE,10)
        b1.x = 300
        b1.y = 300
        b2 = physics.body(CIRCLE,50)
        b2.x = 400
        b2.y = 300
      physics.gravity(0,0)
    
        li = physics.joint(DISTANCE,b1,b2,b1.position,b2.position)
        li.length = b1.radius + b2.radius
    end
    
    function draw()
        li.length = LinkL
        --li.length = math.random(100,500)
        print(li.length)
        background(212, 211, 212, 255)    
        drawBody(b1)
        drawBody(b2)
        drawLink(li)
    end
    
    function drawBody(body)
        pushStyle()
        pushMatrix()
    
        stroke(31, 75, 31, 255)
        translate(body.x, body.y)
        rotate(body.angle)
        if ( body.shapeType == CIRCLE) then
            strokeWidth(1.0)
            ellipse(0,0,2*body.radius)
        end
    
        popMatrix()
        popStyle()
    end
    
    function drawLink(link)
        pushStyle()
        pushMatrix()
        stroke(0,0,0)
        strokeWidth(2)
    
        line( link.anchorA.x, link.anchorA.y, link.anchorB.x, link.anchorB.y )
    
        popMatrix()
        popStyle()
    
    end
    
  • dave1707dave1707 Mod
    Posts: 7,923

    @Bejoscha Add this line at the end of draw to give one of the balls a little velocity. Then try the parameter slider.

    b2.linearVelocity=vec2(0,1)
    
  • dave1707dave1707 Mod
    Posts: 7,923

    @Bejoscha I haven't played with the physics joints for a long time. I think the purpose of the DISTANCE joint is to keep 2 objects connected at some distance. As one of the objects moves, the other will follow at the connected distance.

  • Posts: 31

    Yes, I wanted to use it as a spring-type connection. Essentially I want to recreate some code I once did in Processing, just to learn Luna. I could recreate my Ball and Spring classes from scratch but I thought if there is already a physics library it would be better to use that.
    Your code line did fix the parameter. However, does this mean the distance link acts only if one of the bodies is moving? It seems so. (Is it event triggered?)

    The other issue - the “not quite touching” drawing is also annoying. Is it a rounding issue? Or am I missing something?

  • Posts: 31

    Ha! My own comment make me remember that I ‘be seen some body parameter that might be related. And indeed, setting sleepingAllowed = false Does the trick.

  • Posts: 31

    Remains the drawing issue... Any comment here?

  • dave1707dave1707 Mod
    Posts: 7,923

    @Bejoscha sleepingAllowed, I remember it well, now. Like I said, I haven't played with the physics code for quite awhile and totally forgot about that. As for the ellipse drawing, the size of the ellipse isn't quite what gets set. I don't remember if something can be set or if you just have to add 1 or 2 to the size. I would have to play with some collision code to see if collisions happen at the correct sizes or if that's off a little.

  • Posts: 31

    It seems the collisions with FLAT surfaces are spot-on. It is the collisions between two circles which is off. (Also in the other example code.) But that's a bit of a shame, because it means I cannot simply draw a little larger - it would look funky with flat surfaces.

    Hmm, maybe I port my own code. But it feels kind of like reinventing the wheel if there is already some library - with possibly more speed optimized code than I have.

  • dave1707dave1707 Mod
    Posts: 7,923

    @Bejoscha In the below code, even though the circle sizes aren't correct, when the code runs you can't tell there is a slight difference.

    function setup()
        fill(255, 0, 0, 255)
        b1 = physics.body(CIRCLE,10)
        b1.position=vec2(300,400)
        b1.restitution=1
        b2 = physics.body(CIRCLE,50)
        b2.type=STATIC
        b2.position=vec2(300,100)
    end
    
    function draw()
        background(212, 211, 212, 255)    
        drawBody(b1)
        drawBody(b2)
    end
    
    function drawBody(body)
        ellipse(body.x,body.y,2*body.radius)
    end
    
  • Posts: 31

    Yes, the problem comes when they come to a rest like in the modified physics example below

  • Posts: 31
    -- Simple Physics
    
    -- Use this function to perform your initial setup
    function setup()
        print("Hello Physics!")
    
        print("Touch the screen to make boxes")
        parameter.boolean("Circle")
        -- Table to store our physics bodies
        bodies = {}
    
        -- Create some static boxes (not effected by gravity or collisions)
        local left = makeBox(WIDTH/4, HEIGHT/2, WIDTH/3, 15, -30)
        left.type = STATIC
    
        local right = makeBox(WIDTH - WIDTH/4, HEIGHT/2, WIDTH/3, 15, 30)
        right.type = STATIC
    
        local floor = maeekeBox(WIDTH/2, 10, WIDTH, 20, 0)
        floor.type = STATIC
    
        table.insert(bodies, left)
        table.insert(bodies, right)
        table.insert(bodies, floor)
    end
    
    -- This function gets called once every frame
    function draw()
        -- This sets a dark background color
        background(40, 40, 50)
    
        -- Draw all our physics bodies
        for k,body in pairs(bodies) do
            drawBody(body)
        end
    end
    
    function touched(touch)
        -- When you touch the screen, create a random box
        if touch.state == BEGAN then
            if Circle then
            table.insert(bodies, makeCircle(touch.x, touch.y, math.random(10, 25))) 
            else
            table.insert(bodies, makeBox(touch.x, touch.y, math.random(25, 50), math.random(25, 50), 0))
            end
        end
    end
    
    -- Helper function to create a box using a polygon body
    function makeBox(x,y,w,h,r)
        -- Points are defined in counter-clockwise order
        local body = physics.body(POLYGON,vec2(-w/2, h/2),
        vec2(-w/2, -h/2), vec2(w/2, -h/2), vec2(w/2, h/2))
    
        -- Set the body's transform (position, angle)
        body.x = x
        body.y = y
        body.angle = r
    
        -- Make movement smoother regardless of framerate
        body.interpolate = true
    
        return body
    end
    
    function makeCircle(x,y,r)
        local circle = physics.body(CIRCLE, r)
        -- enable smooth motion
        circle.interpolate = true
        circle.x = x
        circle.y = y
        circle.restitution = 0.25
        circle.sleepingAllowed = false
        return circle
    end
    
    -- Helper function to draw a physics body
    function drawBody(body)
        -- Push style and transform matrix so we can restore them after
        pushStyle()
        pushMatrix()
    
        strokeWidth(5)
        stroke(148, 224, 135, 255)
        translate(body.x, body.y)
        rotate(body.angle)
    
        -- Draw body based on shape type
        if body.shapeType == POLYGON then
            strokeWidth(3.0)
            local points = body.points
            for j = 1,#points do
                a = points[j]
                b = points[(j % #points)+1]
                line(a.x, a.y, b.x, b.y)
            end
        elseif body.shapeType == CHAIN or body.shapeType == EDGE then
            strokeWidth(3.0)
            local points = body.points
            for j = 1,#points-1 do
                a = points[j]
                b = points[j+1]
                line(a.x, a.y, b.x, b.y)
            end
        elseif body.shapeType == CIRCLE then
            strokeWidth(3.0)
            line(0,0,body.radius-3,0)
            ellipse(0,0,body.radius*2)
        end
    
        -- Restore style and transform
        popMatrix()
        popStyle()
    end
    
  • dave1707dave1707 Mod
    Posts: 7,923

    @Bejoscha You can do something like this. Multiply the radius by 2.15 or whatever value gives the best view. It doesn't affect the collision distance, just the display for the circle.

        elseif body.shapeType == CIRCLE then
            strokeWidth(3.0)
            line(0,0,body.radius-3,0)
            ellipse(0,0,body.radius*2.15)
        end
    
  • Posts: 31

    Yeah, but the problem is that it then looks odd for contacts with straight features. I think it really can only be fixed in the library...

Sign In or Register to comment.