Hey all, this is a very simple example of my suggestion to use a set of planets with gravity , movers and attractors:
http://www.youtube.com/watch?v=Z1fI7pF5Ii4
--# Main
-- PlanetGravity
-- Use this function to perform your initial setup
function setup()
physics.gravity(0,0)
mainPlanet = Planet({
x = WIDTH/2,
y = HEIGHT/2,
radius = 60,
mass = 10,
type = ATTRACTOR,
img = "SpaceCute:Planet"
})
redPlanet = Planet({
x = WIDTH - 100,
y = HEIGHT/3,
radius = 30,
mass = 8,
type = ATTRACTOR,
img = "Space Art:UFO"
})
asteroid = Planet({
x = WIDTH/4,
y = 100,
sizex = 66,
sizey = 55,
radius = 30,
mass = 2,
type = MOVER,
img = "Space Art:Asteroid Large"
})
small_asteroid = Planet({
x = WIDTH/1.2,
y = HEIGHT - 100,
sizex = 50,
sizey = 50,
radius = 25,
mass = 1,
type = MOVER,
img = "Space Art:Asteroid Small"
})
rockPlanet = Planet({
x = 100,
y = HEIGHT - 100,
radius = 40,
mass = 18,
type = ATTRACTOR,
img = "Tyrian Remastered:Rock 3"
})
-- set the attractors
mainPlanet:addAttractor(asteroid)
redPlanet:addAttractor(asteroid)
mainPlanet:addAttractor(small_asteroid)
rockPlanet:addAttractor(small_asteroid)
rockPlanet:addAttractor(asteroid)
-- controls of the masses :D
parameter.number("Red Planet Mass", 8, 150, 8, function(newMass)
redPlanet.mass = newMass
end
)
parameter.number("Green Planet Mass",10,200,10,function(newMass)
mainPlanet.mass= newMass
end
)
parameter.number("Rock Planet Mass",8,200,18,function(newMass)
rockPlanet.mass= newMass
end
)
createUniverseLimit()
end
function createUniverseLimit()
top = physics.body(EDGE, vec2(0,HEIGHT), vec2(WIDTH,HEIGHT))
left = physics.body(EDGE, vec2(0,HEIGHT), vec2(0,0))
right = physics.body(EDGE, vec2(WIDTH,HEIGHT), vec2(WIDTH,0))
bottom= physics.body(EDGE, vec2(0,0) , vec2(WIDTH,0))
end
function draw()
background(0)
strokeWidth(2)
mainPlanet:draw()
rockPlanet:draw()
redPlanet:draw()
asteroid:draw()
small_asteroid:draw()
end
function touched(touch)
if asteroid:touched(touch) then return end
if small_asteroid:touched(touch) then return end
end
--# Planet
Planet = class()
ATTRACTOR = 1
MOVER = 2
GRAVITY = 1000
function Planet:init(args)
-- create the planet body
self.body = physics.body(CIRCLE, args.radius)
self.body.x = args.x
self.body.y = args.y
self.type = args.type
self.body.mass = args.mass
self.mass = args.mass -- when static, body.mass is 0
self.sizex = args.sizex or args.radius*2.5
self.sizey = args.sizey or args.radius*2.5
self.dragOffset= vec2(0,0)
self.img = readImage(args.img)
self.body.restitution = .05
self.body.friction = .6
self.touchId = 0
if args.type == ATTRACTOR then
self.attracted = {}
self.body.type = STATIC
elseif args.type == MOVER then
self.attractors= {}
end
end
function Planet:addAttractor(attractor)
if self.type == ATTRACTOR then
table.insert(self.attracted, attractor)
table.insert(attractor.attractors, self)
elseif self.type == MOVER then
table.insert(self.attractors, attractor)
table.insert(attractor.attracted, self)
end
end
function Planet:attract(m)
-- Direction of the force
local force = self.body.position - m.body.position
local d = force:len() -- = m.body.position:dist(self.body.position)
force = force:normalize()
local dir = vec2(self.mass/m.body.mass, self.mass/m.body.mass)
-- Magnitude of the force
local strength = (GRAVITY * self.mass * m.body.mass)/(d*d)
force = force * strength
m.body:applyForce(force)
stroke((1+math.floor(force.y))*110, (1+math.floor(force.x))*110, 10, 255)
-- draw line between attractor/mover
line(m.body.x+force.x, m.body.y+force.y, (self.body.x), (self.body.y))
end
function Planet:updateForces()
if self.type == ATTRACTOR then
self.body.angle = self.body.angle - 0.1
for i,a in ipairs(self.attracted) do
self:attract(a)
end
elseif self.type == MOVER then
-- check for planets?
-- TODO
end
end
function Planet:draw()
self:updateForces()
pushMatrix()
translate(self.body.x, self.body.y)
rotate(self.body.angle)
sprite(self.img, 0, 0, self.sizex, self.sizey)
popMatrix()
end
function Planet:touched(touch)
if touch.state == BEGAN then
if self.touchId == 0 then
if self.body:testPoint(vec2(touch.x,touch.y)) then
self.touchId = touch.id
else
-- not touching this body
return false
end
else
-- this body has another touch
return false
end
else
if self.touchId ~= touch.id then
return false
end
end
self.body.x = touch.x
self.body.y = touch.y
if touch.state == ENDED then
self.touchId = 0
end
return true
end