Page 1 of 1

Can't get accurate trajectory predictions with Box2d

Posted: Thu Jan 24, 2019 7:02 pm
by akopyl
As the title says the trajectories that I predict don't line up with the path that the body ends up taking.
I'd also like to note that the innacuracy is proportional to the gravity. (world.lua line 8)
I'm attaching the .love file but please note that it's for v0.10.2. Sorry for all the bad code, any feedback is appreciated.

Here's the code that sets the player flying. (player.lua line 60)

Code: Select all

function player.mousereleased(x, y, mb, istouch)
  obj.player.body:setLinearVelocity((player.onScreenX-x)*ui.pullStrength, (obj.player.body:getY()-y)*ui.pullStrength)
end
Here's the trajectory drawing chunk of code. (Starts at ui.lua line 55)

Code: Select all

function ui.drawBackground()
  love.graphics.setColor(230, 100, 60)
  love.graphics.setLineWidth(H*0.006)
  love.graphics.setPointSize(H*0.006)
  if love.mouse.isDown(1) then
    love.graphics.line(player.onScreenX, obj.player.body:getY(), love.mouse.getX(), love.mouse.getY())
    -- Per second approach
    for n = .01, .8, .02 do
      love.graphics.setColor(230, 100, 60, 255-255*n/.8)
      love.graphics.line(player.onScreenX+(player.onScreenX-love.mouse.getX())*ui.pullStrength*n,
      obj.player.body:getY()+(obj.player.body:getY()-love.mouse.getY())*ui.pullStrength*n+(world.g*world.meter*n^2)/2,
      player.onScreenX+(player.onScreenX-love.mouse.getX())*ui.pullStrength*(n+.01),
      obj.player.body:getY()+(obj.player.body:getY()-love.mouse.getY())*ui.pullStrength*(n+.01)+(world.g*world.meter*(n+.01)^2)/2)
    end
    -- Per timestep approach
    love.graphics.setColor(51, 244, 88)
    for n = 1, 60, 1 do
      love.graphics.points(player.onScreenX + (player.onScreenX-love.mouse.getX())*ui.pullStrength*n/60,
      obj.player.body:getY() + (obj.player.body:getY()-love.mouse.getY())*ui.pullStrength*n/60 + (n*n+n)*(world.g*world.meter)/(60*60)/2)
    end
  end
end
game.love
Love version 0.10.2
(251.06 KiB) Downloaded 135 times

Re: Can't get accurate trajectory predictions with Box2d

Posted: Fri Jan 25, 2019 12:17 am
by pgimeno
I haven't checked your units in detail, so there may be a bug there, but what I consider most likely is that you're hitting some internal Box2D clamping.

I've made this experiment:

Code: Select all

local lph, lg = love.physics, love.graphics

local metre = 10
local gravity = 40
local Vx, Vy = 40, -400

lph.setMeter(metre)

local world = lph.newWorld(0, metre * gravity)
local body = lph.newBody(world, 400, 300, "dynamic")
local shape = lph.newRectangleShape(20, 20)
local fixture = lph.newFixture(body, shape)
body:setLinearDamping(0)

body:setLinearVelocity(Vx, Vy)

local obj = {vx = Vx, vy = Vy, x = 400, y = 300}

function love.update(dt)
  dt = 1/60

  world:update(dt)

  local vx,vy = body:getLinearVelocity()
  obj.vy = obj.vy + gravity * metre * dt
  obj.x = obj.x + obj.vx * dt
  obj.y = obj.y + obj.vy * dt
end

local img = love.graphics.newImage(love.image.newImageData(1, 1, '\255\255\255\255'))

function love.draw()
  lg.setColor(255,255,255)
  lg.polygon("fill", body:getWorldPoints(shape:getPoints()))
  lg.setColor(0,255,0)
  lg.draw(img, obj.x, obj.y, 0, 10, 10, .5, .5)
end

function love.keypressed(k) return k == "escape" and love.event.quit() end
Most of the time, the green and the white squares are in sync, but for some values, things change. In particular, using the above parameters but changing metre to 3 or less causes a desync.

Adjusting your metre (and everything else accordingly) might help.

Besides that, I don't think the (n*n+n) you use in your formula is correct, but I guess that was some wild shot.

And while I'm here, it's a good idea to avoid defining functions inside other functions unless you specifically need it, e.g. when creating a closure for some upvalues. Each time you redefine the function, a new one needs to be created and the old one destroyed, which wastes CPU.

Re: Can't get accurate trajectory predictions with Box2d

Posted: Fri Jan 25, 2019 12:42 am
by akopyl
Thanks! Turns out the bigger the meter the more accurate my prediction will be up to a certain extent.