Why is it moving? (Physics question from an eternal newbie) [Solved]

Hi!
I’m playing around with physics, using a code from @VonClossen: http://twolivesleft.com/Codea/Talk/discussion/1927/crates%3A-a-physics-experiment/p1

What I am doing is trying to spin a crate (the blue one on the video, next) when spinning another crate (the yellow one). When I create only the yellow crate, it doesn’t translate in the plane, as expected. But when I create the nearby blue crate, both translate when in contact after spinning the yellow one, when I’m expecting that both just rotate. Why? How can I avoid that?
Thanks in advance and I’m still a newbie :smiley:

(See code and video attached)

http://youtube.com/watch?v=EqPA186-UuY


supportedOrientations(LANDSCAPE_ANY)
displayMode(FULLSCREEN)
    
function setup()
    physics.gravity(0,0)
    angle = 0
    spin = 0
    Objects:init()
    touches = {}
end

function draw()
    background(40, 40, 50)
    strokeWidth(5)
    stroke(0, 0, 0, 255)
    
    drawPoly(blue)
    drawPoly(gold)
    
    Objects:draw()

    if CurrentTouch.state == BEGAN or CurrentTouch.state == MOVING then
        if CurrentTouch.x < WIDTH/2 then
            spin = 50
            gold:applyTorque(spin) 
        end
        if CurrentTouch.x > WIDTH/2 then
            spin = -50
            gold:applyTorque(spin) 
        end
    end
end

function drawPoly(body)
    pushMatrix()
    translate(body.x, body.y)
    rotate(body.angle)
    if body.shapeType == POLYGON then
        local points = body.points
        local a, b
        for j = 1,#points do
            a = points[j]
            b = points[(j % #points)+1]
            line(a.x, a.y, b.x, b.y)
        end 
    end
    popMatrix()
end

Objects = class()

function Objects:init()
    blue = physics.body(POLYGON, vec2(0,0), vec2(100,0), vec2(100,100), vec2(0,100))
    blue.type = DYNAMIC
    blue.x = WIDTH/2 + 110
    blue.y = HEIGHT/2 - 50
    blue.sleepingAllowed = false
    blue.angle = 0
    
    gold = physics.body(POLYGON, vec2(0,0), vec2(100,0), vec2(100,100), vec2(0,100))
    gold.type = DYNAMIC
    gold.x = WIDTH/2
    gold.y = HEIGHT/2
    gold.sleepingAllowed = false
    gold.angle = 0
end

function Objects:draw()
    pushMatrix()
    translate(blue.x, blue.y)
    rotate(blue.angle)
    sprite("Cargo Bot:Crate Blue 1", 50,50, 100, 100)
    popMatrix() 
    
    pushMatrix()
    translate(gold.x, gold.y)
    rotate(gold.angle)
    sprite("Cargo Bot:Crate Yellow 1", 50,50, 100, 100)
    popMatrix()  
end

function Objects:touched(touch)
    -- Codea does not automatically call this method
end

I think, my question is fairly related to that of @EpicPotato: http://twolivesleft.com/Codea/Talk/discussion/3451/physics-gravity#Item_1

@quezadav I’m not sure what your question is, but the spinning of the crate is controlled in the touch routine. If you touch the left side of the screen, the gold crate spins in one direction. If you touch the right side of the screen, the gold crate spins in the opposite direction. There isn’t any code in touch to cause the blue crate to spin. The spin of the blue crate is caused by the collision with the gold crate. If I’m totally off with this answer, let me know.

Hi @dave1707, thank you very much for your answer!
I’m really sorry about my poor formulation in the above message :((
What I’ve tried to say is that, indeed, I want both crates to spin, but not to move left-right or up-down. I hope I’ve made it clearer :slight_smile:
Edit: sorry if I sound unpolite, my mother tongue is spanish.

Edit 2: I want to spin the blue crate as a reaction of it interacting with the yellow one.

@quezadav - it’s very easy. The x and y values of both physics objects will change because of the collision. But you don’t have to use them when drawing the sprites. Just store the original x and y positions before you collide them, then draw the sprites at these x and y positions (rotating the boxes of course).

Thanks Ignatz! But I really want to have physics objects: one of them making rotate the other one.

Edit: I mean, rotating both objects around their own static axis.

Edit 2: I think, I should use a joint to fix them, but I’m not sure how (I’m just checking the manual).

What you can do at the top of the draw function is reset the x,y positions of the objects back to their original positions, ie

function Objects:draw()
    blue.x, blue.y = blueStart.x, blueStart.y 
    --where blueStart.x = WIDTH/2 +110
    --and blueStart.y = HEIGHT/2 - 50
    --ie store these in variables to make it easy to change them later
   
    --now do the same for gold

Thanks. Solved: It was just a matter of setting the linear velocity to zero every frame.

Edit: this is not a complete solution though, because I note that, every frame, the axles displace a little bit until the crates are separated enough for not touching each other…

@quezadav I think this might be what you’re after. You want the 2 crates to react to collisions with each other, but to remain stationary. Here is a little demo showing something similar to that. This shown the 2 crates reacting to a 3rd object, that reacts to the 2 crates. You’re probably after the physics.joint(REVOLUTE command. See the explanation in the physics documentation.


function setup()    
    a1=physics.body(CIRCLE,0)
    a1.x=0
    a1.y=0
    a1.type=STATIC
    a1.sensor=true
    
    c1=physics.body(CIRCLE,18)
    c1.x=0
    c1.y=700
    
    p2=physics.body(POLYGON,
        vec2(-50,-50),
        vec2(-50,50),
        vec2(50,50),
        vec2(50,-50))
    p2.x=100
    p2.y=300
    
    p3=physics.body(POLYGON,
        vec2(-50,-50),
        vec2(-50,50),
        vec2(50,50),
        vec2(50,-50))
    p3.x=-30
    p3.y=350
  
    j1=physics.joint(REVOLUTE,a1,p2,vec2(100,300))   
    j2=physics.joint(REVOLUTE,a1,p3,vec2(-30,350))      
end

function draw() 
    background(40, 40, 50)
    strokeWidth(2)
    
    if c1.y<-200 then
        c1.y=700
        c1.x=40
        c1.linearVelocity=vec2(0,0)
    end
    
    pushMatrix()
    translate(200,200)     
    sprite("Platformer Art:Guy Standing",c1.x,c1.y,30)
    noFill()
    stroke(255)
    popMatrix()
    
    pushMatrix()
    translate(300,500)  
    xx=p2.angle
    rotate(xx)
    sprite("Cargo Bot:Crate Blue 1",0,0,107)
    popMatrix()
    
    pushMatrix()
    translate(170,550)  
    xx=p3.angle
    rotate(xx)
    sprite("Cargo Bot:Crate Yellow 1",0,0,107)
    popMatrix()
end

Oh God! Yes! Thank you @dave1707!