Physics problems.

Once again I’m getting stumped with using physics. What I’m trying to do is create a wheel that rotates on swipe. It has pegs that should rotate around the center so the flapper can hit the pegs. Problem is it goes crazy when you swipe. I’m guessing that the pegs are adding to the rotation speed of the center but I’m not sure how to fix it.

What I’ve done.

  • Created a static physics body in the center
  • Created another physics body to act as the wheel.
  • Used a REVOLUTE joint to anchor the wheel to center
  • Created the peg physics bodies.
  • Used a WELD joint to attach the pegs to the center wheel.


function setup()
    pegs = {}
    joints = {}
    pegLength = 100
    size = 100
    -- you can accept and set parameters here
    x = WIDTH/2
    y = HEIGHT/2
    
    
    --Center anchor
    center = physics.body(CIRCLE,15)
    center.type = STATIC
    center.x=WIDTH/2
    center.y=HEIGHT/2
    
    --Wheel
    wheel = physics.body(CIRCLE,15)
    wheel.x=WIDTH/2
    wheel.y=HEIGHT/2
    wheel.gravityScale=0
    wheel.angularVelocity=0
    wheel.angularDamping=2
    
    --Create pegs
    createPegs()
    
    --Lock wheel to center
    local jcenter = physics.joint(REVOLUTE,center,wheel,center.position,wheel.position)
    jcenter.frequency = 0
    table.insert(joints,jcenter)
end

function createPegs()
    local inc = 360/16
    local angle = 0
    for i=1,16 do
        local p1 = physics.body(CIRCLE,5)
        p1.x = WIDTH/2 + (pegLength * math.cos(math.rad(angle)))
        p1.y = HEIGHT/2 + (pegLength * math.sin(math.rad(angle)))
        p1.gravityScale = 0
        --p1.angularVelocity=0
        --p1.angularDamping=.2
       -- p1.linearVelocity = 0
        p1.mass = 0
        p1.restitution = 0
        table.insert(joints,physics.joint(WELD,wheel,p1,wheel.position,p1.position))
        table.insert(pegs,p1)
        angle = angle + inc
    end
end

function draw()
    -- Codea does not automatically call this method
    background(185, 181, 181, 255)
    text("tap screen to spin",WIDTH/2,HEIGHT-100)
    pushMatrix()
    translate(wheel.x,wheel.y)

    rotate(wheel.angle)
    stroke(0, 0, 0, 255)
    strokeWidth(2)
    fill(255)
    ellipse(0,0,wheel.radius*2)
    local lineAngle = 0
    noFill()
    strokeWidth(2)
    ellipse(0,0,200)
    for i=1,8 do
    line(0,0,100*math.cos(math.rad(lineAngle)),100*math.sin(math.rad(lineAngle)))
        lineAngle = lineAngle + (360/8)
    end
    popMatrix()
    
    
    stroke(0,255,0,255)
    strokeWidth(5)
    for k,joint in pairs(joints) do
        local a = joint.anchorA
        local b = joint.anchorB
        line(a.x,a.y,b.x,b.y)
    end
    
    stroke(255,255,255,255)
    noFill()
    
    for i,body in ipairs(pegs) 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(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
        
        popMatrix()
    end 
    
end

function touched(t)
   -- self.flapper.angularVelocity = 5
    -- Codea does not automatically call this method
    if t.state==MOVING then
       if math.abs(t.deltaX) > math.abs(t.deltaY) then
        wheel.angularVelocity= t.deltaX --*150
        else
        
        wheel.angularVelocity= t.deltaY-- *150
        end
    end
end

Scratch that. It was a problem with mass. 0 did not work, it needed a float.

@Briarfox

EDIT: Original program deleted and replaced with this one. Not sure if the image will be correct.


displayMode(FULLSCREEN)

function setup()
    c=physics.body(CIRCLE,20)
    c.x=WIDTH/2
    c.y=HEIGHT/2
    c.gravityScale=0
    c.angularVelocity=0
    c.angularDamping=.2
    getImg()    
end

function draw()
    background(255)
    if img then
        pushMatrix()
        translate(WIDTH/2,HEIGHT/2)
        rotate(c.angle)
        sprite(img,-2,-1,800)
        popMatrix()
        if c.angularVelocity<10 then
            c.angularVelocity=0
        end
        fill(0)
        text("Swipe screen to spin wheel",WIDTH/2,HEIGHT-30)
    else
        fill(0)
        text("Loading image",WIDTH/2,HEIGHT/2)
    end
end

function touched(t)
    if t.state==MOVING then
        v=math.min(math.abs(math.max(math.abs(t.deltaX),math.abs(t.deltaY)))*10,200)
        c.angularVelocity=v
    end
end

function getImg()
    http.request('http://s2.postimg.org/yq31er9nd/image.jpg',gotImage)
end

function gotImage(image,status,header)
    img=image
end

@dave1707 I set the body mass to 0 which it didn’t like. Setting mass to 0.00001 works.

@Briarfox I replaced my above program with another spinning wheel.

@Briarfox I think my spinning wheel program above should have been posted in you other discussion, “Best way to make a Jeopardy type wheel”.