Howdy, Stranger!

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

In this Discussion

Tagged

Planet physics (Gravity)
  • juaxixjuaxix
    Posts: 435

    Hey all, this is a very simple example of my suggestion to use a set of planets with gravity , movers and attractors:

    --# 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
    
    
    
  • LuismiLuismi
    Posts: 350

    Is great =D>