[SOLVED] Angry Birds Physics

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
yegorf1
Prole
Posts: 19
Joined: Tue Dec 25, 2012 7:46 pm

[SOLVED] Angry Birds Physics

Post by yegorf1 »

Hi!
I tried to calculate impulse for body in order to body flew through the mouse coordinates, but my calculations were wrong. After many attempts I tried this:

Code: Select all

local x = self.target.x - self.position.x
local y = self.target.y - self.position.y

res.body:applyLinearImpulse(x * 10 ^ 10, y * 10 ^ 10)
I thought that error will be minimal, but it didn't work too. Body flew in, about, 30 pixels from target.
What am I doing wrong?

UPD:
When I changed love.physics.setMeter(1) to love.physics.setMeter(4) it worked better. Why?
Last edited by yegorf1 on Tue Jan 06, 2015 9:22 am, edited 1 time in total.
User avatar
nfey
Citizen
Posts: 63
Joined: Tue Feb 18, 2014 9:50 am
Location: Romania

Re: Angry Birds Physics

Post by nfey »

How are you calculating self.target and self.position? Are they correct?
Why are you using the distance to calculate the amount of impulse to be applied?
What's the mass of the object you're trying to push? (read the wiki entry for :applyLinearImpulse)

Also, it would be easier to help out if you upload the .love file.
yegorf1
Prole
Posts: 19
Joined: Tue Dec 25, 2012 7:46 pm

Re: Angry Birds Physics

Post by yegorf1 »

I solved this. My love file is really big and there are a lot of other stuff.
Solution is

Code: Select all

function Catapult:pushRock()
    local pos = getDrawPosition(self)
    --rock spawn position
    pos.x = pos.x + 3
    pos.y = pos.y - 3
    
    --distance on both axises
    local x = self.target.x - pos.x
    local y = self.target.y - pos.y
    
    local _, g = world:getGravity() --world:getGravity() returns gravity.x and gravity.y; gravity.x = 0
    
    local t = 6                    --time. Can be any, except zero
    local vx = x / t                --velocity on X
    local vy = y / t - g * t / 2    --velocity on Y
    
    Rock:new(pos.x, pos.y, vx + math.random(4) - 2, vy - math.random(4) + 2)
end
User avatar
ivan
Party member
Posts: 1915
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Angry Birds Physics

Post by ivan »

In Box2D, the trajectory of a moving body is affected by
1. gravity (including the gravity scale of the body)
2. linear damping
For starters, set the gravity to (0, 0) and the linear damping to 0 and see if it works.
Also, check out the following post.

Code: Select all

-- STEP ONE: figure out the velocity required to reach the target
-- vector to target:
local dx = self.target.x - self.position.x
local dy = self.target.y - self.position.y
-- distance to target:
local d = math.sqrt(dx*dx + dy*dy)
assert(d > 0, "target == position")
-- normalized vector to target:
local nx = dx/d
local ny = dy/d
-- velocity required to reach the target:
local vx = nx*desiredLV
local vy = ny*desiredLV
-- minimum time to reach the target:
local dt = d/desiredLV

-- STEP TWO: factor in gravity and linear damping
-- adjust the velocity to compensate for the effects of gravity and linear damping:
-- v = v - g
vx, vy = steering.compG(vx, vy, gx, gy, dt) -- ignore if "gx" and "gy" are 0
vx, vy = steering.compLD(vx, vy, damping, maxLV, dt) -- ignore if "damping" is 0 

-- STEP THREE: find the force based on the velocity: F = m*a, a = (fv - iv)/dt, dt = d/desiredLV
-- initial velocity, in this case 0, 0:
local ivx, ivy = 0, 0 -- body:GetLinearVelocity()
-- final velocity:
local fvx, fvy = vx, vy
-- force required to reach the final velocity:
local fx, fy = steering.force(ivx, ivy, fvx, fvy, mass, dt)
where:

Code: Select all

gx, gy: world gravity
damping: linear damping of the body
mass: mass of the body
maxLV: maximum linear velocity (Box2D constant)
desiredLV: desired linear velocity (0 < desired LV <= maxLV)
dt: time interval (> 0) in this case: dt = d/desiredLV
Once you know the force required to direct the body to a given target then you have to convert that to an impulse (from the Box2D forums):
p = F * s (where p is the change of impulse, F a force and s the time, here dt). That means applyImpulse(10) and 10 seconds applyForce(1) will result in the same velocity for the body
These calculations work assuming that the body is not attached to a joint and doesn't collides with other bodies.
Post Reply

Who is online

Users browsing this forum: Bing [Bot], Semrush [Bot] and 4 guests