Probably dumb physics question

Hey all

Trying to learn to work with physics as the next step. Messing with a random little program but it’s bugging out when I change game states. Pretty much a static ball in center of screen and another ball controlled by device gravity, when the 2 balls collide, the gameState changes, but it’s bugging out when this happens. I imagine I need to remove the physics.body and then reset it when I press play again. Kind of lost on how to do that.

Any tips would be appreciated.

Thanks

This is the code I’m working with.


displayMode(FULLSCREEN)
supportedOrientations(PORTRAIT_ANY)

-- Use this function to perform your initial setup
function setup()
    playerX=WIDTH/6
    playerY=HEIGHT/1.2
    
    goalX = WIDTH/2
    goalY = HEIGHT/2
    
    ball = physics.body(CIRCLE,18)
    ball.x = playerX
    ball.y = playerY
    ball.restitution = 0.5
    --ball.info="A"
    
    ball2 = physics.body(CIRCLE,9)
    ball2.type = STATIC
    ball2.x = goalX
    ball2.y = goalY
    ball2.restitution = 0
    --ball2.info="B"
    
    wall1 = physics.body(EDGE,vec2(0,0),vec2(0,HEIGHT))
    wall2 = physics.body(EDGE,vec2(0,0),vec2(WIDTH,0))
    wall3 = physics.body(EDGE,vec2(WIDTH,0),vec2(WIDTH,HEIGHT))
    wall4 = physics.body(EDGE, vec2(0,HEIGHT),vec2(WIDTH,HEIGHT))
    wall1.type = STATIC
    wall2.type = STATIC
    wall3.type = STATIC
    wall4.type = STATIC
    wall1.restitution = 0.5
    wall2.restitution = 0.5
    wall3.restitution = 0.5
    wall4.restitution = 0.5
    
    fontSize(96)
    fill(255, 0, 0, 255)
    
    gameState=0
end

function touched(t)
    if gameState==0 and t.state==BEGAN then
        gameState=1
    end
    
    if gameState==2 and t.state==ENDED then
        gameState=0
    end
end

-- This function gets called once every frame
function draw()
    if gameState==0 then
        text("PLAY",WIDTH/2,HEIGHT/2)
    end
    
    if gameState==1 then
    physics.gravity(Gravity)
        background(0,0,0,255)
        ellipse(ball.x,ball.y,ball.radius*2)
        ellipse(ball2.x,ball2.y,ball2.radius*2)
        if ball:testOverlap(ball2) then
            gameState=2
        end
    end
    
    if gameState==2 then
        text("Try Again",WIDTH/2,HEIGHT/2)
    end
    
end

try using the collide(contact) function

the touched function detects finger touches, not physics collisions. You need the collide function for that.

https://coolcodea.wordpress.com/2013/03/21/6-more-physics/

@Crumble Some things I changed in your code. I added the background command to draw. I removed the STATIC lines for EDGE. EDGEs are static by default. I also removed the restitution on the EDGES. You have restitution on the ball, so that’s enough. I removed the blank lines just to make the code smaller to repost it. Other than that, the code works fine. The testOverlap is good enough for the collision. Here’s your modified code that works fine for me.


displayMode(FULLSCREEN)
supportedOrientations(PORTRAIT_ANY)

function setup()
    playerX=WIDTH/6
    playerY=HEIGHT/1.2
    goalX = WIDTH/2
    goalY = HEIGHT/2
    ball = physics.body(CIRCLE,18)
    ball.x = playerX
    ball.y = playerY
    ball.restitution = 0.5
    ball2 = physics.body(CIRCLE,9)
    ball2.type = STATIC
    ball2.x = goalX
    ball2.y = goalY
    ball2.restitution = 0
    wall1 = physics.body(EDGE,vec2(0,0),vec2(0,HEIGHT))
    wall2 = physics.body(EDGE,vec2(0,0),vec2(WIDTH,0))
    wall3 = physics.body(EDGE,vec2(WIDTH,0),vec2(WIDTH,HEIGHT))
    wall4 = physics.body(EDGE, vec2(0,HEIGHT),vec2(WIDTH,HEIGHT))
    fontSize(96)
    fill(255, 0, 0, 255)
    gameState=0
end

function touched(t)
    if gameState==0 and t.state==BEGAN then
        gameState=1
        ball.linearVelocity=vec2(0,-200)
    end
    if gameState==2 and t.state==ENDED then
        gameState=0
    end
end

function draw()
    background(0)
    if gameState==0 then
        text("PLAY",WIDTH/2,HEIGHT/2)
    end
    if gameState==1 then
        physics.gravity(Gravity)
        background(0,0,0,255)
        ellipse(ball.x,ball.y,ball.radius*2)
        ellipse(ball2.x,ball2.y,ball2.radius*2)
        if ball:testOverlap(ball2) then
            gameState=2
            ball.x=WIDTH/6
            ball.y=HEIGHT/1.2
            ball.linearVelocity=vec2(0,0)
            physics.gravity(0,0)
        end
    end    
    if gameState==2 then
        text("Try Again",WIDTH/2,HEIGHT/2)
    end
end

I thought that function was global, so would trigger when the ball hits the walls also.

@Ignatz the touch function was just for switching gameStates.

@dave1707 Thanks Dave! So it was just that I forgot to draw the background on the other 2 gameStates. Oops. Good to know about the other physics stuff.

Question, it seems that the ball is still moving around in the background, even when on the play and try again screens, which could cause a problem. Is there an easy way to remove the ball that is moving around, after it collides, and then reset it to the starting position when I press play again?

Also another strange behavior that I noticed is that if I let the ball come to a rest on a corner, it gets stuck. Any way to get around that?

Sorry for all the questions.

Appreciate the help guys!

@Crumble I changed my code above so the ball stops moving after the collision. It also starts in the same position. I don’t have a solution why the ball sticks in the corner yet.

@dave1707 Thanks much Dave! Much appreciated! I didn’t realize that you can just turn off gravity like that, or adjust linear velocity like that… I’m a newbie to the physics in Codea.

Last quick question, if I just want normal gravity, and not accelerometer gravity, would I just do physics.gravity(0,1)?

Nope, the x,y values set strength as well as direction, so y=1 is probably not what you want

Try physics.gravity() to reset to real world gravity

See reference - “physics.gravity( x, y ) sets the gravity of the world, units are in pixels per second^2. Use the Gravity global to set to device gravity. When no parameters are passed, function returns current world gravity as a vec2.”

@Ignatz Nice, thanks!