Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Unusual gravity settings

edited July 2013 in Questions Posts: 277

Hello there,

Your help was very valuable yesterday, and I'm moving right along in my first little project. I'm having a lot of fun with codea, I must say.

I'm now trying to change gravity setting so it fits my (special) needs. I'm trying to get my bodies not to be attracted out at the bottom of the screen, but rather outward from the centre of the screen.

I've been looking, with no success, at a way to set the general attraction point to the middle of the screen, to then, I hoped, multiply the force by -1 to have objects be repelled from the centre.

Is there a straight forward way to achieve this?

Also, I'd like my bodies to repel each other. Again, I haven't got a good idea on how to achieve this, any help would be very welcome!

Cheers!

Ps. Next move, camera!

Tagged:

Comments

  • dave1707dave1707 Mod
    Posts: 7,657

    Gravity is always towards the bottom of the screen, no option to change it to the middle.

  • edited July 2013 Posts: 391

    Just do a simple test. If pos.x > width/2 then pos.x + 1 else pos.x - 1 end and the same for y coord of an object, If pos.y > height/2 then pos.y + 1 else pos.y - 1 end

    No need to use gravity necessarily.

  • Posts: 277

    Oh ok, thanks. I kind of wanted a force field effect, but I'll try to work around it. Cheers!

  • dave1707dave1707 Mod
    edited July 2013 Posts: 7,657

    @Rodolphe Maybe something like this might be of interest. I'm not sure what you're really after, but I thought I'd post this anyways.


    displayMode(FULLSCREEN) supportedOrientations(PORTRAIT_ANY) function setup()     force=physics.body(CIRCLE,75)     force.x=WIDTH/2     force.y=HEIGHT/2     force.type=STATIC         force.sleepingAllowed=false       object1 = {}     for z=1,40 do         a=physics.body(CIRCLE,30)         a.x=math.random(WIDTH)         a.y=math.random(HEIGHT)         a.gravityScale=0         a.sleepingAllowed=false           table.insert(object1,a)     end     end function draw()     background(255, 167, 0, 38)     if not moveToCenter then         fill(255)         text("tap screen",WIDTH/2,HEIGHT/2)     else         fill(255)         text("force field up",WIDTH/2,HEIGHT/2)         noFill()         stroke(255)         strokeWidth(3)         ellipse(force.x,force.y,150)     end     for i,v in ipairs(object1) do         if moveToCenter then             move=center - vec2(v.x, v.y)                if move:len() > 10 then                 move = move:normalize()             end             v.x = v.x + move.x             v.y = v.y + move.y         end         sprite("Planet Cute:Character Boy", v.x, v.y, 30)     end end function touched(touch)     if touch.state==BEGAN then         moveToCenter=true         center=vec2(WIDTH/2,HEIGHT/2)     end end
  • Jmv38Jmv38 Mod
    Posts: 3,295

    Hello @rodolphe.
    I have tweeked Dave's code above to add a gravity source to the center (and walls around).
    The gravity is correct (within the limits of physics engine: too much propulsion when the planet commes too close to the center).


    displayMode(FULLSCREEN) function setup()     edges = {}     edges[1] = physics.body(EDGE,vec2(WIDTH,HEIGHT),vec2(0,HEIGHT))     edges[2] = physics.body(EDGE,vec2(WIDTH,HEIGHT),vec2(WIDTH,0))     edges[3] = physics.body(EDGE,vec2(0,0),vec2(0,HEIGHT))     edges[4] = physics.body(EDGE,vec2(0,0),vec2(WIDTH,0))     for i,v in pairs(edges) do v.restitution = 0.9 end     object1 = {}     for z=1,40 do         a=physics.body(CIRCLE,30)         a.x=math.random(WIDTH)         a.y=math.random(HEIGHT)         a.gravityScale=0         a.sleepingAllowed=false           table.insert(object1,a)     end     end function draw()     background(255, 167, 0, 38)     if not moveToCenter then         fill(255)         text("tap screen",WIDTH/2,HEIGHT/2)     else         fill(255)         text("force field up",WIDTH/2,HEIGHT/2)         noFill()         stroke(255)         strokeWidth(3)     end     local grav,dist     for i,v in ipairs(object1) do         if moveToCenter then             grav=center - vec2(v.x, v.y)                dist = grav:len()             if dist < 1 then dist = 1 end             grav = grav / (dist*dist*dist) * 100000             v:applyForce(grav)         end         sprite("Planet Cute:Character Boy", v.x, v.y, 30)     end end function touched(touch)     if touch.state==BEGAN and not(moveToCenter) then         moveToCenter=true         center=vec2(WIDTH/2,HEIGHT/2)         for i,v in ipairs(object1) do             v.linearVelocity = vec2(math.random(100)-50, math.random(100)-50)            end     end end
  • Jmv38Jmv38 Mod
    Posts: 3,295

    And here is another progam i found on the forum (cant remember who posted it, sorry).
    There are more explanations.


    --# Main displayMode(FULLSCREEN) --supportedOrientations(PORTRAIT) function setup() leaveTrails = false if leaveTrails then backingMode(RETAINED) end bodies = {} setup = 1 if setup == 1 then --solar system --gravitation constant for scaling G = .005 --initial planets --sun bodies[1] = { m= 40000, x = WIDTH/2, y= HEIGHT/2, dx=0, dy=0 } --planets bodies[2] = { m= 15, x = WIDTH/2, y= HEIGHT/2 - 65, dx= 1.8, dy = 0 } bodies[3] = { m= 20, x = WIDTH/2, y= HEIGHT/2 - 100, dx=1.5, dy=0 } bodies[4] = { m= 30, x = WIDTH/2, y= HEIGHT/2 - 150, dx=1.3, dy=0 } bodies[5] = { m= 40, x = WIDTH/2, y= HEIGHT/2 - 180, dx=1.2, dy= 0} bodies[6] = { m= 60, x = WIDTH/2, y= HEIGHT/2 - 300, dx=0.85, dy= 0 } --moons bodies[7] = { m= 0.1, x = WIDTH/2, y= HEIGHT/2 - 155, dx= 1.47, dy= 0 } end if setup == 2 then --2 planets and a moon G = 1 --initial planets bodies[1] = { m = 400, x= 300, y= 500, dx = 1.4, dy = .4 } bodies[2] = { m = 400, x= 300, y= 600, dx = -1.4, dy = -.4 } bodies[3] = { m = 4, x = 300, y= 480, dx = -3.1, dy = .4 } end selectedBody = 1 end function touched(touch) if touch.state == BEGAN then if touch.x > WIDTH - 100 and touch.y < HEIGHT - 85 and touch.y > HEIGHT - 125 then --touched slower bodies[selectedBody].dx = bodies[selectedBody].dx * .9 bodies[selectedBody].dy = bodies[selectedBody].dy * .9 elseif touch.x > WIDTH - 100 and touch.y < HEIGHT - 140 and touch.y > HEIGHT - 180 then --touched faster bodies[selectedBody].dx = bodies[selectedBody].dx * 1.1 bodies[selectedBody].dy = bodies[selectedBody].dy * 1.1 else --change slected planet if touch is with 100 of it closest = nil dist = 100 for k,v in pairs(bodies) do calcDist = math.sqrt((touch.x - v.x)^2+(touch.y - v.y)^2) if calcDist < dist then dist = calcDist closest = k end end if closest ~= nil then selectedBody = closest end end end end function draw() if leaveTrails == false then background(40,40,50) end strokeWidth(0) fill(255) applyGravity() moveBodies() -- plot bodies for k,v in pairs(bodies) do if selectedBody == k then fill(255, 9, 0, 255) else fill(255,255,255,255) end ellipse(v.x, v.y, math.pow(v.m, .2)*2 + 2) end drawControl() end function drawControl() fill(255,255,255,255) text(string.format("Body: %d", selectedBody), WIDTH - 50, HEIGHT - 50) fill(150,150,150,255) rect(WIDTH - 100, HEIGHT - 125, 100, 40) rect(WIDTH - 100, HEIGHT - 180, 100, 40) fill(255,255,255,255) text("slower", WIDTH - 50, HEIGHT - 105) text("faster", WIDTH - 50, HEIGHT - 160) v = math.sqrt(bodies[selectedBody].dx^2+bodies[selectedBody].dy^2) text(string.format("Velocity: %f", v), WIDTH - 100, HEIGHT - 200) end function applyGravity() for k,v in pairs(bodies) do for k2,v2 in pairs(bodies) do if k2 > k then --gravity factor - this is distance facotring for gravity and trigonometry d = 1 / math.pow(( (v.x - v2.x)^2 + (v.y - v2.y)^2), 1.5) --adjust v velocity v.dx = v.dx - (v.x - v2.x) * d * v2.m * G v.dy = v.dy - (v.y - v2.y) * d * v2.m * G --adjust v2 velocity v2.dx = v2.dx - (v2.x - v.x) * d * v.m * G v2.dy = v2.dy - (v2.y - v.y) * d * v.m * G end end end end function moveBodies() for k,v in pairs(bodies) do v.x = v.x + v.dx v.y = v.y + v.dy end end
  • dave1707dave1707 Mod
    Posts: 7,657

    I was one of the posters, here's a link to the post. There were other links I had also on orbit simulations. http://www.twolivesleft.com/Codea/Talk/discussion/2018/using-physics-to-simulate-moon-in-orbit-around-planet/p1

  • Posts: 277

    This is all excellent, thanks a lot! From all this great code, I'm pretty sure I can manage to invert the force field in order to gently repel objects from the centre of the screen. Cheers !

  • Posts: 277

    Oops, codea crashes consistantly when I try to set the gravity to zero (see main in physics lab examples, I just force 0 gravity), as such :

    defaultGravity = physics.gravity(0,0) (or even defaultGravity = physics.gravity(0,0,0))

    What am I doing wrong?

  • IgnatzIgnatz Mod
    Posts: 5,396

    Just write gravity(0,0)

  • Posts: 277

    This consistently crashes my system, does codea behave like this for anyone else? should I post an entry in the bug section?

  • IgnatzIgnatz Mod
    Posts: 5,396

    Post more of your code, most likely there is a coding error

  • Posts: 277

    Actually, even easier for you guys : in the "main" file of the physics lab, in codea's latest version, simply changing "physics.gravity()" by "physics.gravity(0,0)" crashes on my ipad retina. There's most likely something I am missing...

  • Posts: 1,976

    Maybe physics.gravity(vec2(0, 0))?

  • Posts: 277

    Oops, i can't remember if I tried this!

    ...

    (Trying)

    ...

    No, still crashing :(

  • dave1707dave1707 Mod
    edited July 2013 Posts: 7,657

    Looking at the code in the physics lab example and at the documentation, this is basically all the code that's needed to show it doesnt work. Variable a is (0,-313.600006), variable b is nil. Variable b should be the same as a.

    EDIT: physics.gravity doesn't return a value if there are values in the (). The second function setup of my example works. So in the above example defaultGravity=physics.gravity(0,0) will set defaultGravity to nil.

        
    function setup()
        a=physics.gravity()
        print(a)
        b=physics.gravity(a)
        print(b)   
    end
    
    function setup()
        a=physics.gravity()
        print(a)
        physics.gravity(a)
        b=physics.gravity()
        print(b)   
    end
    
    
  • Posts: 277

    Sorry, I feel really slow, does that mean this is actually a bug?

  • dave1707dave1707 Mod
    Posts: 7,657

    No, it's not a bug. It's working the way it was written. At first I thought it was a bug also until I looked at the documentation and realized that it only returned a value when no parameters were passed in the function. I guess it could have been written to return a value even if there were parameters passed, but it doesn't.

  • Posts: 277

    Alright, that's clearer now. I still find it a little counter intuitive, but it now works for me thanks to you!

Sign In or Register to comment.