Getting started with Physics

Hi all,
Just wanted to share with you a very simple physics example, that helped me to understand the basic functions.

(An update is available later in this post, below)

--# Main
supportedOrientations(LANDSCAPE_LEFT)
saveProjectInfo("Description", "Just a simple ball to bounce around.")

-- Use this function to perform your initial setup
function setup()
    parameter("GravityScale", .25, 10, 3)
    
    ball = physics.body(CIRCLE, 50)
    ball.x = WIDTH/2
    ball.y = HEIGHT/2
    ball.restitution = .5

    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(WIDTH,HEIGHT),vec2(0,HEIGHT))
    wall1.type = STATIC
    wall2.type = STATIC
    wall3.type = STATIC
    wall4.type = STATIC
    wall1.restitution = .1
    wall2.restitution = .1
    wall3.restitution = .1
    wall4.restitution = .1
end

-- This function gets called once every frame
function draw()
    physics.gravity(Gravity)
    background(40, 40, 50)
    strokeWidth(0)
    fill(255, 255, 0, 255)
    ellipse(ball.x,ball.y,ball.radius*2)
end

Hello @Rob10. Thank you for the example. Is the line parameter("GravityScale", .25, 10, 3) used in your code? I believe the walls are created .type = STATIC by default.

Curiously, if the ball comes to rest in the top left corner, it can become trapped there. I wonder if this is an artifact of the walls being one-dimensional EDGEs rather than two-dimensional POLYGONs (like the ground in the Physics Lab example project).

Hi @Rob10, nice and compact code! Ideal for beginners like me :wink:
The program seems not to respond to the parameter slide, just to the initial value. In fact, I got the same problem with a similar program that I wrote few days ago and I’m looking here in the forum how to get rid of that problem.
Greetings,
Victor ~O)

@mpilgrem, I’m not sure about that, but “to be safe” I constructed similar walls, in a program of mine, with Edge but a bit dettached from the screen borders… :smiley:
P.S. The “glued” ball occurs in every corner!

You’re right, @quezadav: I tried replacing EDGEs with POLYGONs below, but it still results in a glued ball.

Update: the ball gets glued because it ‘goes to sleep’. A solution is to not allow it to sleep.


supportedOrientations(LANDSCAPE_RIGHT)

function setup()
    ball = physics.body(CIRCLE, 50)
    ball.x = WIDTH/2
    ball.y = HEIGHT/2
    ball.restitution = .5
    ball.sleepingAllowed = false --<<< Fix for glued ball in corners
    
    local t = 10 -- Set the thickness
    
    w = { -- Store the walls in a table
    wall(vec2(t, t), vec2(t,HEIGHT - t), t),
    wall(vec2(t,HEIGHT - t), vec2(WIDTH - t, HEIGHT - t), t),
    wall(vec2(WIDTH - t, HEIGHT - t), vec2(WIDTH - t, t), t),
    wall(vec2(WIDTH - t, t), vec2(t, t), t),
    }   
    
    fill(255, 255, 0)
end

-- Helper function to draw the walls
function wall(from, to, thickness)
    local points = {} -- Store the points in a table
    table.insert(points, from)
    table.insert(points, to)
    local p = to + (to - from):rotate90():normalize() * thickness
    table.insert(points, p)
    local p = p + (from - to)
    table.insert(points, p)
    local wallBody = physics.body(POLYGON, unpack(points))
    wallBody.type = STATIC
    wallBody.restitution = 0.1
    return wallBody
end
    
function draw()
    physics.gravity(Gravity)
    background(0)
    
    stroke(0, 255, 0)
    strokeWidth(5)
    for i = 1, #w do
        polygon(w[i].points)
    end
    
    noStroke()    
    ellipse(ball.x,ball.y,ball.radius*2)
end

-- Helper function to draw polygons
function polygon(points)
    for i = 1, #points - 1 do
        line(points[i].x, points[i].y, points[i + 1].x, points[i + 1].y)
    end
    line(points[#points].x, points[#points].y, points[1].x, points[1].y)
end

@mpilgrem, I’m not sure, but it can be due to the deffault value of the “sleepingAllowed” parameter for a physics.body: true. I’ve learnt in these days that it is useful to prevent continued drawing of the object when it reaches rest… :smiley: Try to set it “false” to see what happens…

Edit: Cool! I went to W.C. and have overseen yor update. :smiley:

@Rob10, EDGE can be used for the boundaries too.

@mpilgrem, after problem fixed, now a newbie-question: how can a parameter-slide be set for being used to start a simulation from a given value, not the initial one when restarting the program? :slight_smile:

Hi all,

Thanks for all the comments. You were right, I forgot to use the parameter for “GravityScale” within my code. At this occasion I also added the parameter for “Restitution” of the ball.
Second topic in your commends was that the ball got trapped in the corners. And @quezadav is right, this is due to the “sleepingAllowed” parameter. I set this now to false.
Regarding the question from @quezadav: not sure whether I got your question right, but if you want to define a start value within the range of the parameter slider, you can do this at the parameter definition.
So please find below my updated example.

--# Main
supportedOrientations(LANDSCAPE_LEFT)
saveProjectInfo("Description", "Just a simple ball to bounce around.")

-- Use this function to perform your initial setup
function setup()
    parameter("GravityScale", .25, 10, 3)
    parameter("Restitution", 0, 1, .5)
    
    ball = physics.body(CIRCLE, 50)
    ball.x = WIDTH/2
    ball.y = HEIGHT/2
    ball.sleepingAllowed = false

    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(WIDTH,HEIGHT),vec2(0,HEIGHT))
    wall1.type = STATIC
    wall2.type = STATIC
    wall3.type = STATIC
    wall4.type = STATIC
    wall1.restitution = .1
    wall2.restitution = .1
    wall3.restitution = .1
    wall4.restitution = .1
end

-- This function gets called once every frame
function draw()
    physics.gravity(Gravity)
    ball.gravityScale = GravityScale
    ball.restitution = Restitution
    background(40, 40, 50)
    strokeWidth(0)
    fill(255, 255, 0, 255)
    ellipse(ball.x,ball.y,ball.radius*2)
end

Great.
Small typo in line 14. Should be vec not rvec

Thanks for the hint @West. Sometimes the virtual keyboard is a challange for me.
I corrected the typo above.

Hello @quezadav. I was not sure if @Rob10’s answer satisfied your question about parameter() or iparameter(). I understood you to ask how you could do the same sort of thing that the Physics Lab example project does with its test_number slider.

The answer is that it polls the slider variable in draw() to see if it has changed from the previous value, and - if it has changed - calls a function that resets things accordingly:


function setup()
...
    setTest(currentTestIndex) -- Initialise during setup
...
end

function draw()
...
    if test_number ~= currentTestIndex then
        setTest(test_number) -- Reinitialise
    end
...
end

@Rob10, @mpilgrem, many thanks: I didn’t understand even my own question
:smiley: (I’m preparing an exam and my head is a mess). I’ll try your suggestions, before I reformulate my question.
Saludos desde México ~O)

Hi all, Codea Gurus, :smiley:
I have a “little” problem with a simple Physics simulation:
I want to follow the “real” effect of a falling ball over a “table”. It seems that the physics is OK, but I can’t visualize it properly. See my code, please, to check what happens (a non-Newtonian-Physics! OMG! :-ss )
Thanks in advance!
Victor ~O)


supportedOrientations(LANDSCAPE_ANY)

function setup()
    xc=WIDTH/2
    yc=HEIGHT/2
    physics.gravity(Gravity)
-- the falling ball    
    ball = physics.body(CIRCLE, 50)
    ball.x = xc-200
    ball.y = yc+200
    ball.restitution = 1
-- a "table" 
    mesa=physics.body(POLYGON,vec2(xc-300,yc),vec2(xc-300,yc+50),vec2(xc+300,yc+50),
    vec2(xc+300,yc))
    mesa.type=DYNAMIC
-- the table's base
    base=physics.body(POLYGON,vec2(xc,0),vec2(xc,yc),vec2(xc+50,yc),vec2(xc+50,0))
    base.type=STATIC
end

function draw()
    background(0)
    stroke(0, 255, 0)
    strokeWidth(5)
-- drawing of the falling ball
    ellipse(ball.x,ball.y,ball.radius*2)
-- drawing of thw table's base    
    line(xc,0,xc,yc)
    line(xc,yc,xc+50,yc)
    line(xc+50,yc,xc+50,0)
-- table's angle
    tq=mesa.angle
-- rotation of the table's base
    rotate(tq)
-- drawing of the table after contact with the ball        
    rect(mesa.x+75,mesa.y+yc,600,50)
end

Change mesa.type to STATIC to stop the table top from moving. Change ball.restitution to .5 so that it doesn’t bounce as much. With the iPad in landscape orientation, tilt it a little to the right or left before restarting the program to get the ball to roll right or left. The more you tilt it, the more gravity will pull it in that direction when you restart the program.

Thanks @dave1707, I’ve improved it with a function that you used in one of your own examples.
Saludos, Victor ~O)

https://www.youtube.com/watch?v=7UUfRmB02cI


supportedOrientations(LANDSCAPE_ANY)

function setup()
    xc=WIDTH/2
    yc=HEIGHT/2
    physics.gravity(Gravity)
    
    ball = physics.body(CIRCLE, 50)
    ball.x = xc-200
    ball.y = yc+300
    ball.restitution = 0.5

    ball2 = physics.body(CIRCLE, 50)
    ball2.x = xc+200
    ball2.y = yc+200
    ball2.restitution = 0.
    
    base=physics.body(POLYGON,vec2(xc-25,0),vec2(xc-25,yc),vec2(xc+25,yc),vec2(xc+25,0))
    base.type=STATIC
    
    mesa=physics.body(POLYGON,vec2(xc-300,yc),vec2(xc-300,yc+50),vec2(xc+300,yc+50),
    vec2(xc+300,yc))
    mesa.type=DYNAMIC
end

function drawpoints(body)
    pushMatrix()
    translate(body.x, body.y)
    rotate(body.angle)
    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
    popMatrix()
end

function draw()
    background(0, 0, 0, 0)
    stroke(0, 255, 0)
    strokeWidth(5)

    ellipse(ball.x,ball.y,ball.radius*2)
    ellipse(ball2.x,ball2.y,ball2.radius*2)
    
    drawpoints(base)
    drawpoints(mesa)
end

I am learning the physics API by working through the Physics Lab example project. I’ve written up my progress so far (Test 1) as commented code in the tutorial section of the wiki, here and linked here.

@mpilgrem
Nice work commenting the code. I feel kind of silly for not including that when I wrote the physics example :confused:

Come to think of it, it might be good, with your permission, to include your commented version of the code in a future release of Codea

@mpilgrem, great job!

Thank you. I have completed a first pass of all of Tests 1 to 9.

@John, I am not sure your code provided needs more, but if you think any part of my wiki notes may be useful, feel free to use them.

I read the code quite closely and I did spot one or two things in passing in the code or in the in-app reference that I’ll add to the issue tracker.

I included in my notes the bug revealed by Test 9 that is being discussed here.