how can i force the joints to be "stricter"?

my example code is down there. i want that wheel to cind of “collect” (dont know the english word) this chain and move this cind of strange crane up or down. but my joints dont: they always go around the wheel. how can i change this?

greetings, maxiking

the Main:

function setup()
    displayMode(FULLSCREEN)
    supportedOrientations(LANDSCAPE_ANY)
    w = WIDTH
    h = HEIGHT
    getImages()
    debugDraw = PhysicsDebugDraw()
    debugDraw:init()
    --manager = SceneManager()
    --scenes = {}
    --manager:init(scenes)
    createWorld()
    pc = color(125, 30, 30, 255)
    npc = color(255, 0, 0, 255)
    buttonC = button("closeButton",w - 70,h - 70,w - 30,h - 30,pc,npc,"rect")
    buttonR = button("right",w - 70,30,w - 30,70,pc,npc,"rect")
    buttonL = button("left",w - 170,30,w - 130,70,pc,npc,"rect")
    buttonS = button("stop",w - 170,100,w - 30,140,pc,npc,"rect")
    frame = 0
end

function draw()
    background(40, 40, 50)
    touched()
    drawButtons()
    debugDraw:draw()
    frame = frame + 1
    if rotatingLeft then
        wheel.angle = wheel.angle + 5
    elseif rotatingRight then
        wheel.angle = wheel.angle - 5
    end
end

function touched()
    t = CurrentTouch
    buttonC:touched(t)
    buttonR:touched(t)
    buttonL:touched(t)
    buttonS:touched(t)
    debugDraw:touched(t)
end

function drawButtons()
    buttonC:draw()
    buttonR:draw()
    buttonL:draw()
    buttonS:draw()
    local xx = (w - 170 + w - 30) / 2
    local yy = (100 + 140) / 2
    font("ArialRoundedMTBold")
    fill(0, 0, 0, 255)
    fontSize(15)
    text("stop",xx,yy)
    local Cstate = buttonC:getInfo()[2]
    local Rstate = buttonR:getInfo()[2]
    local Lstate = buttonL:getInfo()[2]
    
    if Cstate == 3 then
        close()
    end
    
    if Rstate== 1 or Rstate == 2 or Rstate == 3 then
        rotatingRight = true
    else
        rotatingRight = false
    end
    
    if Lstate == 1 or Lstate == 2 or Lstate == 3 then
        rotatingLeft = true
    else
        rotatingLeft = false
    end
end

function createWorld()
    physics.pause()
    
    -- Creating the crane:
    crane = physics.body(POLYGON, 
        vec2(-5,0),
        vec2(-5,-50),
        vec2(-45,-50),
        vec2(-45,-60),
        vec2(45,-60),
        vec2(45,-50),
        vec2(5,-50),
        vec2(5,0))
    crane.x = 300
    crane.y = h - 100
    crane.mass = 0.5
    debugDraw:addBody(crane)
    
    -- Creating the chainpoints:
    cp1 = physics.body(CIRCLE,10)
    cp1.x = 315
    cp1.y = h - 80
    cp1.type = STATIC
    debugDraw:addBody(cp1)
    cp2 = physics.body(CIRCLE,10)
    cp2.x = 285
    cp2.y = h - 80
    cp2.type = STATIC
    debugDraw:addBody(cp2)
    
    -- Creating the chain itself:
    --chain = physics.body(CHAIN,
    --    vec2(300,h - 100),
    --    vec2(300,h - 90),
    --    vec2(300,h - 80),
    --    vec2(300,h - 70),
    --    vec2(300,h - 60),
    --    vec2(310,h - 60),
    --    vec2(320,h - 60),
    --    vec2(330,h - 60),
    --    vec2(340,h - 60),
    --    vec2(350,h - 60),
    --    vec2(360,h - 60))
    --debugDraw:addBody(chain)
    -- hmmm... the chain seems always to be static. lets try it like this:
    
    chain = {}
    chainJoints = {}
    local xx = 300
    local yy = h - 100
    for i = 1, 3 do
        chain[i] = physics.body(POLYGON,
            vec2(xx - 1,yy),
            vec2(xx - 1,yy + 20),
            vec2(xx + 1,yy + 20),
            vec2(xx + 1,yy))
        debugDraw:addBody(chain[i])
        chainJoints[i] = physics.joint(REVOLUTE,chain[i - 1],chain[i],vec2(xx,yy))
        debugDraw:addJoint(chainJoints[i])
        yy = yy + 20
    end
    for i = 4,15 do
        chain[i] = physics.body(POLYGON,
            vec2(xx ,yy - 1),
            vec2(xx + 20,yy - 1),
            vec2(xx + 20,yy + 1),
            vec2(xx,yy + 1))
        debugDraw:addBody(chain[i])

        chainJoints[i] = physics.joint(REVOLUTE,chain[i - 1],chain[i],vec2(xx,yy))
        debugDraw:addJoint(chainJoints[i])
        xx = xx + 20
    end
    for i = 16,21 do
        chain[i] = physics.body(POLYGON,
            vec2(xx + 1,yy),
            vec2(xx - 1,yy),
            vec2(xx - 1,yy - 20),
            vec2(xx + 1,yy - 20))
        debugDraw:addBody(chain[i])

        chainJoints[i] = physics.joint(REVOLUTE,chain[i - 1],chain[i],vec2(xx,yy))
        debugDraw:addJoint(chainJoints[i])
        yy = yy - 20
    end
    for i = 22,28 do
        chain[i] = physics.body(POLYGON,
            vec2(xx ,yy - 1),
            vec2(xx - 20,yy - 1),
            vec2(xx - 20,yy + 1),
            vec2(xx,yy + 1))
        debugDraw:addBody(chain[i])

        chainJoints[i] = physics.joint(REVOLUTE,chain[i - 1],chain[i],vec2(xx,yy))
        debugDraw:addJoint(chainJoints[i])
        xx = xx - 20
    end
    
   
    -- Creating a joint between the crane and the chain:
    craneConnection = physics.joint(REVOLUTE,chain[1],crane,vec2(300,h - 100))
    debugDraw:addJoint(craneConnection)
    
    -- Creating the wheel:
    wheel = physics.body(CIRCLE,30)
    wheel.x = 400
    wheel.y = h - 130
    wheel.type = STATIC
    debugDraw:addBody(wheel)
    
    -- Creating a joint between the wheel and the chain:
    wheelConnection = physics.joint(REVOLUTE,chain[#chain],wheel,vec2(400,h - 160))
    debugDraw:addJoint(wheelConnection)
    physics.resume()
end

my Button Class ( !UPDATED! you can take it from here.)

button = class()
-- by max tamussino
-- contact: max@visuals.at

function button:init(title,x1,y1,x2,y2,colorPressed,colorNotPressed,image1,image2)
    -- this button class makes it easier to create buttons. the best thing is: it keeps
    -- the touched function short ;)
    -- so here is how to use it:
    -- - the title the title should be a string, and should represent the function of the button,
    --   like: "closeButton"
    -- - x1,y1,x2,y2 are the coordinates
    -- - good to know: the button can either be a rect or a sprite (in spritely or not). 
    --        1) For the rect:
    --        - colorPressed: the color the rect is filled with when the button is pressed.
    --        - colorNotPressed: the color the rect is filled with when the button is not pressed.
    --        - image1: must be set to ""rect"" (string!!).
    --        - image2: must be nil.
    --        - coordinates: for rectMode(CORNERS)
    --        2) For the sprite:
    --               Two possibilities:
    --               a) changing image:
    --                   - this possibility changes the normal image (image1) to image2 if 
    --                     the button is touched.
    --                   - colorPressed and colorNotPressed both must be nil.
    --                   - image1: normal image
    --                   - image2: displayed instead of the normal one when touched.
    --               b) changing tint:
    --                   - this possibility changes the fill color of the sprite if the 1
    --                     button is touched
    --                   - colorPressed: the tint() if the button is not touched
    --                   - colorNotPressed: the tint() if the button is touched
    --                   - image2: must be nil
    --
    --
    -- the button:getInfo() function returns a table with the title ( [1] )and the state( [2] ).
    -- to use this, you can can keep track of your buttonstates like this:
    --
    --
    --
    --
    --    if button:getInfo()[2] == 3 then
    --        if button:getInfo()[1] == "closeButton" then
    --            close()
    --        elseif button:getInfo()[1] == "openMenuButton" then
    --            if not menuShown then
    --                menuShown = true
    --            else
    --                menuShown = false
    --            end
    --        elseif button:getInfo()[1] == "showHelpScreenButton" then
    --            if not helpScreenShown then
    --                helpScreenShown = true
    --            else
    --                helpScreenShown = false
    --            end
    --        end
    --    end
    --
    -- i hope it helps you guys! have fun creating buttons! :)
    
    self.title = title
    self.x1 = x1
    self.y1 = y1
    self.x2 = x2
    self.y2 = y2
    self.cp = colorPressed
    self.cnp = colorNotPressed
    self.image1 = image1
    if not self.cp then
        if not self.cnp then 
            self.image2 = image2
        end
    end
    self.pressed = false
    rectMode(CORNERS)
end

function button:draw()
    spriteMode(CORNERS)
    
    if self.state == 1 or self.state == 2 then
        self.pressed = true
    else
        self.pressed = false
    end
    
    if self.image1 == "rect" then
        if self.pressed then
            fill(self.cp)
            rect(self.x1 - 2,self.y1 - 2,self.x2 - 2,self.y2 - 2)
        else
            fill(self.cnp)
            rect(self.x1,self.y1,self.x2,self.y2)
        end
    elseif self.image2 then
        if self.pressed then
            sprite(self.image2,self.x1 - 2,self.y1 - 2,self.x2 - 2,self.y2 - 2)
        else
            sprite(self.image1,self.x1,self.y1,self.x2,self.y2)
        end
    else
        if self.pressed then
            tint(self.cp)
            sprite(self.image1,self.x1 - 2,self.y1 - 2,self.x2 - 2,self.y2 - 2)
        else
            tint(self.cnp)
            sprite(self.image1,self.x1,self.y1,self.x2,self.y2)
        end
    end
    
    if self.state == 3 then
        if ElapsedTime > endTime + 0.01 then
            self.state = 0
        end
    end
end

function button:touched()
    t = CurrentTouch
    if t.x > self.x1 and t.y > self.y1 and t.x < self.x2 and t.y < self.y2 then
        if t.state == BEGAN then
            self.state = 1
            touching = true
        elseif t.state == MOVING then
            self.state = 2
        elseif t.state == ENDED then
            if touching then
                self.state = 3
            end
            touching = false
            endTime = ElapsedTime
        end
    else
        self.state = 0
    end
end

function button:getInfo()
    return {self.title, self.state}
end

and the debug draw:

PhysicsDebugDraw = class()

function PhysicsDebugDraw:init()
    self.bodies = {}
    self.joints = {}
    self.touchMap = {}
    self.contacts = {}
end

function PhysicsDebugDraw:addBody(body)
    table.insert(self.bodies,body)
end

function PhysicsDebugDraw:addJoint(joint)
    table.insert(self.joints,joint)
end

function PhysicsDebugDraw:clear()
    -- deactivate all bodies
    
    for i,body in ipairs(self.bodies) do
        body:destroy()
    end
  
    for i,joint in ipairs(self.joints) do
        joint:destroy()
    end      
    
    self.bodies = {}
    self.joints = {}
    self.contacts = {}
    self.touchMap = {}
end

function PhysicsDebugDraw:draw()
    
    pushStyle()
    smooth()
    strokeWidth(5)
    stroke(128,0,128)

    local gain = 2.0
    local damp = 0.5
    for k,v in pairs(self.touchMap) do
        local worldAnchor = v.body:getWorldPoint(v.anchor)
        local touchPoint = v.tp
        local diff = touchPoint - worldAnchor
        local vel = v.body:getLinearVelocityFromWorldPoint(worldAnchor)
        v.body:applyForce( (1/1) * diff * gain - vel * damp, worldAnchor)
            
        line(touchPoint.x, touchPoint.y, worldAnchor.x, worldAnchor.y)
    end
    
    stroke(0,255,0,255)
    strokeWidth(5)
    if self.joints then
        for k,joint in pairs(self.joints) do
            local a = joint.anchorA
            local b = joint.anchorB
            line(a.x,a.y,b.x,b.y)
        end
    end
    
    stroke(255,255,255,255)
    noFill()
    
    if self.bodies then
        for i,body in ipairs(self.bodies) do
            pushMatrix()
            translate(body.x, body.y)
            rotate(body.angle)
        
            if body.type == STATIC then
                stroke(255,255,255,255)
            elseif body.type == DYNAMIC then
                stroke(150,255,150,255)
            elseif body.type == KINEMATIC then
                stroke(150,150,255,255)
            end
        
            if body.shapeType == POLYGON then
                strokeWidth(5.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(5.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(5.0)
                line(0,0,body.radius-3,0)
                strokeWidth(2.5)
                ellipse(0,0,body.radius*2)
            end
            
            popMatrix()
        end 
    end
    
    stroke(255, 0, 0, 255)
    fill(255, 0, 0, 255)

    for k,v in pairs(self.contacts) do
        for m,n in ipairs(v.points) do
            ellipse(n.x, n.y, 10, 10)
        end
    end
    
    popStyle()
end

function PhysicsDebugDraw:touched(touch)
    local touchPoint = vec2(touch.x, touch.y)
    if touch.state == BEGAN then
        for i,body in ipairs(self.bodies) do
            if body.type == DYNAMIC and body:testPoint(touchPoint) then
                self.touchMap[touch.id] = {tp = touchPoint, body = body, anchor = body:getLocalPoint(touchPoint)} 
                return true
            end
        end
    elseif touch.state == MOVING and self.touchMap[touch.id] then
        self.touchMap[touch.id].tp = touchPoint
        return true
    elseif touch.state == ENDED and self.touchMap[touch.id] then
        self.touchMap[touch.id] = nil
        return true;
    end
    return false
end

I’ll ask @John to see if he has any suggestions — it sounds like you are trying to drive a chain with a wheel, like a bicycle?

Yes, exactly. I was trying to create a crane steerable with wheels.

I’d recommend using motors instead of trying to simulate a chain like that. The reason is that the simulation probably wont be stable enough to give you the results you want. The only other suggestion I would give is to increase the friction of the chain and wheel bodies and maybe decrease the length of the chain links to make it tighter.

motors? whats that?
well, i decreased the length, but thats quite hard because the joint between wheel and the chain dös not behave correctly, ill play around with it, but thanks!

Check out the demo code Physics Lab test 6 " motors"