# Unusual gravity settings

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!

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

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.

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

@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

``````

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

``````

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)

v.dx = v.dx - (v.x - v2.x) * d * v2.m * G
v.dy = v.dy - (v.y - v2.y) * d * v2.m * G

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
``````

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

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 !

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?

Just write gravity(0,0)

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

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

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…

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

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

(Trying)

No, still crashing

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

``````

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

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.

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