In other words, I wish I could set the gravity location.
Thx. [import]uid: 9328 topic_id: 25678 reply_id: 325678[/import]
In other words, I wish I could set the gravity location.
Thx. [import]uid: 9328 topic_id: 25678 reply_id: 325678[/import]
What you’re really asking for is radial gravity. Gravity which centres on a certain position and either pushes toward or away from that point.
Ansca’s problem is really that gravity is not provided by them but Box2D, which they didn’t write.
If you want to have more complex forms of gravity then you will need to implement it yourself, which you can do by using the applyForce function. I have a number of examples here:
http://springboardpillow.blogspot.co.uk/2012/04/sample-code.html
But the one you would want to look for is here:
https://developer.anscamobile.com/code/simple-draggable-fan-demo-2 [import]uid: 8271 topic_id: 25678 reply_id: 103846[/import]
Ok, thx fo all the info
A chance to see it one day, either from box2D or ansca ? [import]uid: 9328 topic_id: 25678 reply_id: 103865[/import]
Well, I don’t really follow developments in the Box2D world (I’m absolutely certain Ansca do) but it won’t be Ansca implementing it - it would be Ansca providing their build of Box2D. But, based on the intent of Box2D so far, I doubt it would happen. It’s not difficult to build a radial gravity field and the best thing about doing it yourself is that you can move them, have multiples and have them affect things in different ways - all of which would be very complex to implement from the SDK level, IMHO. I would say that I could write you a short demo, but to be honest, I’ve done that a number of times in the samples linked from my blog in the Code Exchange. [import]uid: 8271 topic_id: 25678 reply_id: 103889[/import]
Thx, I’ll check the samples [import]uid: 9328 topic_id: 25678 reply_id: 104366[/import]
Btw, it occurs to me that radial gravity would only accept 3 parameters: x,y (location) and f (+ve or -ve force value)
This is because the x,y values of the current setGravity function allow the gravity to be defined for any angle but gravity centred on a single point would not have that.
Of course, a fourth parameter could be provided to apply rotation, but then that would not really be gravity any more but a force - which is exactly what the applyForce function is for and possibly why the Box2D engine doesn’t provide anything but linear gravity. [import]uid: 8271 topic_id: 25678 reply_id: 104375[/import]
Thought I’d demo it for you:
[lua]-- radial gravity example
display.setStatusBar(display.HiddenStatusBar)
physics = require(“physics”)
physics.start()
physics.setGravity(0,5) – regular gravity applied
physics.setDrawMode(“hybrid”) – debug, hybrid, normal
–[[taken from my mathlib]]–
function lengthOf( a, b )
local width, height = b.x-a.x, b.y-a.y
return (width*width + height*height)^0.5 – math.sqrt(width*width + height*height)
end
– Extends the point away from or towards the origin to the length of len
function extrudeToLen( origin, point, len )
local length = lengthOf( origin, point )
local factor = len / length
local x, y = (point.x - origin.x) * factor, (point.y - origin.y) * factor
return x, y
end
–[[end mathlib]]–
local scenary, gravityfields, objects = display.newGroup(), display.newGroup(), display.newGroup()
local floor = display.newRect( scenary, 0, 0, display.contentWidth, 10 )
floor.x, floor.y = display.contentCenterX, display.contentHeight
physics.addBody( floor, “static” )
– drop things
function dropThing()
local obj = nil
local x, y = math.random(100,display.contentWidth-100), 10 – randomly choose where to start a falling object
if (math.random(1,2) == 1) then
– drop circle
obj = display.newCircle( 0, 0, 30 )
physics.addBody( obj, “dynamic”, { radius=30 } )
else
– drop square
obj = display.newRect( 0, 0, 100, 100 )
physics.addBody( obj, “dynamic” )
end
obj.x, obj.y = x, y
obj:setFillColor( math.random(150,255), math.random(150,255), math.random(150,255) )
objects:insert( obj )
return obj
end
timer.performWithDelay( 3000, dropThing, 0 )
– create radial gravity field
– param x: x of the field’s centre
– param y: y of the field’s centre
– param radius: radius of the field (as applied to a circle display object)
– param strength: force to apply each second
function newRadialGravityField( x, y, radius, strength )
local field = display.newCircle( x, y, radius )
physics.addBody( field, “static”, {radius=radius} )
field.isSensor = true
field.alpha = .3
field.isFieldActive = true
field.radius = radius
field.strength = strength
field.applicablestrength = strength / 30
local affected = {}
field.affected = affected
– adds objects to those affect by the gravity of this field
function field:collision( event )
if (event.phase == “began”) then
affected[#affected+1] = event.other
else
for i=1, #affected do
if (affected[i] == event.other) then
table.remove( affected, i )
break
end
end
end
end
field:addEventListener( “collision”, field )
gravityfields:insert( field )
return field
end
– this function applies the “Box2D applyForce” gravity effect to each object within each field’s radius
function applyGravity()
for g=1, gravityfields.numChildren do
if (gravityfields[g].isFieldActive) then
local field = gravityfields[g]
local strength = field.applicablestrength
local affected = field.affected
for i=1, #affected do
local object = affected[i]
local x, y = extrudeToLen( object, field, strength )
object:applyForce( x, y, object.x, object.y )
end
end
end
end
local fieldtimer = timer.performWithDelay( 1000/30, applyGravity, 0 )
function tap( event )
newRadialGravityField( event.x, event.y, 150, 10 )
end
Runtime:addEventListener( “tap”, tap )[/lua] [import]uid: 8271 topic_id: 25678 reply_id: 104401[/import]
You’re a boss ! [import]uid: 9328 topic_id: 25678 reply_id: 104406[/import]
No, just a manager. [import]uid: 8271 topic_id: 25678 reply_id: 104412[/import]
I’m doing something like this atm: (I think it’s somewhat similar to the demo above, except it’s stripped down to the bare bone)
[lua]–Apply gravitational force to objects of a group. The force will be centered on origin. The force is scaled by strength.
local function applyGravity(group, originX, originY, strength)
for i = 1, group.numChildren do
local obj = group[i]
local m = obj.approxMass or 1
local dx = originX - obj.x
local dy = originY - obj.y
local distsqr = dx * dx + dy * dy
local dist = math.sqrt(distsqr)
local divisor = distsqr
if divisor < 1 then divisor = 1 end
local F = m * strength / divisor
obj:applyForce(dx / dist * F, dy / dist * F, obj.x, obj.y)
end
end[/lua]
This applies a constant gravitational field to a group of objects. This works surprisingly well since the force is (within a limit) inversely proportional to the square of the distance, so the force will be quite strong close by and extremely weak far away. As you can see, I constrain the minimum divisor (you can constrain it even further) because one does not want insane forces close to the origin.
approxMass can be set to the expected relative mass of the object, IIRC there’s no way to get the mass of an object in Corona, which is somewhat unfortunate.
You’ll have to call applyGravity every frame. You can also try to scale force by the time delta since the last frame, but assuming somewhat constant frame rate the above is good enough. [import]uid: 58849 topic_id: 25678 reply_id: 104413[/import]
That’s a very good implementation and surprisingly similar to how particle candy does it. I was going to implement proportional gravity but can never decide how best to do it.
Funny how people expect it to be proportional with radial gravity but that’s not how it’s applied in Box2D. Probably something to do with the “planet slingshot” type of game being the genre defining standard. [import]uid: 8271 topic_id: 25678 reply_id: 104417[/import]