Physics Issue - Can someone see the issue?

Take the simple code below, start running in Codea, and tilt the iPad, and hit
reload a few times to see once in a while the ball starts bouncing between walls.

This creates a bit of an issue during backingMode retained as the balls goes out of the “path”

I’m wondering if this is a physics bug and how to correct or work around it?



function setup()
    physics.gravity(0,0)
    supportedOrientations(PORTRAIT)
    displayMode(FULLSCREEN)
    backingMode(STANDARD)
    walls = {}
    balls = {}
    drawn = 0
    noSmooth()
end

function createCircle(x,y,r)
    local circle = physics.body(CIRCLE, r)
    circle.type = DYNAMIC
    circle.x = x
    circle.y = y
    circle.restitution = 0
    circle.mass = 0
    circle.friction = 0
    circle.interpolate = false
    circle.sleepingAllowed = false
    circle.info = i
    table.insert(balls,circle)
end

function createBox(x,y,w,h)
    local box = physics.body(POLYGON, vec2(-w/2,h/2), vec2(-w/2,-h/2), vec2(w/2,-h/2), vec2(w/2,h/2))
    box.type = STATIC
    box.x = x
    box.y = y
    box.restitution = 0
    box.mass = 0
    box.friction = 0
    box.interpolate = false
    box.sleepingAllowed = false
    table.insert(walls,box)
end

function draw()
    
    background(0, 0, 0, 255)
    
    if drawn == 0 then

        background(40, 60, 40, 255)
        fill(30, 50, 30, 255)

        for y = 0, 10 do
            for x = 0, 2 do
                if x == 0 or x == 2 or y == 0 or y == 10 then
                    createBox(x*30,y*30,30,30)
                end
            end
        end

        createCircle(30,30,30/2)
        drawn = 1
        
    end

    for i,body in ipairs(walls) do
        fill(50, 100, 80, 255)
        rect(body.x,body.y,30,30)
    end
    
    for i,body in ipairs(balls) do

            fill(136, 215, 50, 255)
            ellipse(body.x+body.radius,body.y+body.radius,body.radius*2)

            Gravx = math.ceil(Gravity.x*25)
            Gravy = math.ceil(Gravity.y*25)
            if Gravx > 3 then Gravx = 3 end
            if Gravx < -3 then Gravx = -3 end
            if Gravy > 3 then Gravy = 3 end
            if Gravy < -3 then Gravy = -3 end
            body.position = body.position + vec2(Gravx,Gravy)

    end

end


@escape75 - the problem is probably that although you think you are restarting completely - you aren’t. Your previous physics objects are still there, for about a minute, invisible and getting in the way, then they suddenly vanish.

This is very strange until you know why.

Physics objects exist separately to all your other variables. So when you define a variable (say) Ball, equal to a physics object, you are actually pointing to something completely separate.

When you say Ball=nil to destroy the object - or restart, which does the same thing - you get rid of your variable that points to the physics object, but the physics object is still there.

Codea has a garbage collector that (about once a minute) looks for ways to get rid of unwanted memory. It comes along and sees you have a phyiscs object with nothing pointing to it, and deletes it. But it could take up to a minute.

So how do you delete your physics objects? You destroy them before setting your variables to nil, eg

-- destroy should be used before setting a body to nil
circle = physics.body(CIRCLE, 100)
circle:destroy()
circle = nil

But what if you’re restarting? There isn’t a chance to destroy the physics objects first. I think the solution is to manually call for garbagecollection with the command

collectgarbage()

at the top of the setup function.

I tried collectgarbage() in the above example and it didn’t seem to work.

What’s even stranger is that sometimes (1 out of 10 maybe?) fresh runs
(go back to code and start again) the ball will behave erratically.
It’s constrained by the “wall” so it should only move in the y direction,
but sometimes it seems to move in the x direction … I think ?

@escape75 - you seem to be creating a new physics circle at each draw.

You only need one physics object, which you can create in setup.

I don’t seem to get any problems running it.

I think there’s only 1 copy of physics object created, see “if drawn == 0”

I could move that to setup but it won’t change things I don’t think …

Try running the simulation a few times, you’ll notice most of the time

it will be good, except once in a while the ball will be jumpy going

up and down, having a weird vibration bouncing off the side walls.

@escape75 The problem you’re having is because you’re mixing physics and non physics values. You’re using Gravity as a direct value for the movement of the ball. The ball is trying to break thru the bottom of the opening that it’s rolling in because of the Gravity constantly being added to the ball position. The boxes are pushing the ball back up causing it to have the bouncy effect. You need to control the movement of the ball using the physics value body.linearVelocity. See the example code below. You may have to adjust the values for the way you want it to move.


    for i,body in ipairs(balls) do
            fill(136, 215, 50, 255)
            ellipse(body.x+body.radius,body.y+body.radius,body.radius*2)
            Gravx = Gravity.x*500
            Gravy = Gravity.y*500
            body.linearVelocity=vec2(Gravx,Gravy)
    end

Ahh ok, yes linearVelocity definitely solves this issue, thanks!