Physics object movement q

General discussion about LÖVE, Lua, game development, puns, and unicorns.
Coder567
Prole
Posts: 42
Joined: Sun Apr 07, 2019 12:32 pm

Re: Physics object movement q

Post by Coder567 » Sat Sep 28, 2019 8:30 am

ivan wrote:
Sat Sep 28, 2019 5:07 am
The slow down effect of the ball would be nice, not just applying more force
Your body already has damping so it should "ease" to a stop by itself.
One hacky approach could be to make the force proportional to the distance:
force = min(easing/distance, 1) * force
where "easing" is the distance you want the object to slow down.
You may have to adjusting the damping too.
Not sure what variables I should put to your formula. I only got so far:

Code: Select all

force = math.min(1000/testTravelDist, 1) * 1000
ball.body:applyForce(-force, 0)

User avatar
ivan
Party member
Posts: 1520
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Physics object movement q

Post by ivan » Sun Sep 29, 2019 5:12 pm

You want to apply less force when closer to the target right?
force = math.min(distanceToTarget/easingDistance, 1)*force
where both distances are in meters.

Coder567
Prole
Posts: 42
Joined: Sun Apr 07, 2019 12:32 pm

Re: Physics object movement q

Post by Coder567 » Mon Sep 30, 2019 1:09 pm

@Ivan thanks that probably works but ideally I would like to know how much force to apply so the ball stops moving let's say at 2 seconds

User avatar
ivan
Party member
Posts: 1520
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Physics object movement q

Post by ivan » Mon Sep 30, 2019 4:14 pm

You really don't want to get into the inverse kinematics of Box2d - it's way too complicated for such a simple problem.
Just use a mouse joint and you'll be fine.

Coder567
Prole
Posts: 42
Joined: Sun Apr 07, 2019 12:32 pm

Re: Physics object movement q

Post by Coder567 » Mon Sep 30, 2019 4:34 pm

ivan wrote:
Mon Sep 30, 2019 4:14 pm
You really don't want to get into the inverse kinematics of Box2d - it's way too complicated for such a simple problem.
Just use a mouse joint and you'll be fine.
Mouse joint is for user input right? I'm making AI based game, where AI throws passes..

User avatar
ivan
Party member
Posts: 1520
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Physics object movement q

Post by ivan » Mon Sep 30, 2019 5:16 pm

No. The mouse joint drags objects to a target position.
It won't work for throwing/projectiles though.

User avatar
pgimeno
Party member
Posts: 1873
Joined: Sun Oct 18, 2015 2:58 pm
Location: Valencia, ES

Re: Physics object movement q

Post by pgimeno » Mon Sep 30, 2019 6:39 pm

For such precise timing requirements, my recommendation would be to use a tweening library to operate a mouse joint. That way you control the duration, position, and the acceleration profile.

Here's an example with a very basic tweening function (no library), save as main.lua and press space to activate:

Code: Select all

local orig_x, orig_y = 200, 300
local dest_x, dest_y = 600, 300
local radius = 80
local platform_w = radius * 4 + dest_x - orig_x
local platform_h = radius / 4

local time_str = ""
local tween_timer = false
local tween_max
local tween_func


local world = love.physics.newWorld(0, 98, false)

local platform_b = love.physics.newBody(world, (orig_x + dest_x) / 2, orig_y + radius + platform_h/2, "static")
local platform_s = love.physics.newRectangleShape(0, 0, platform_w, platform_h)
local platform_f = love.physics.newFixture(platform_b, platform_s)

local ball_b = love.physics.newBody(world, orig_x, orig_y, "dynamic");
local ball_s = love.physics.newCircleShape(0, 0, radius);
local ball_f = love.physics.newFixture(ball_b, ball_s)

local ball_j = love.physics.newMouseJoint(ball_b, orig_x, orig_y)


local function tween(time, func)
  tween_timer = 0
  tween_time = time
  tween_func = func
end


-- Linear interpolation between a and b by fraction t (with t between 0 and 1)
local function lerp(a, b, t)
  return t < 0.5 and a + (b - a) * t or b - (b - a) * (1 - t)
end


-- Easing function: apply a curve to 't' to make movement slower at both ends,
-- when calling lerp()
local function ease(a, b, t)
  return lerp(a, b,
    -- smoothstep https://en.wikipedia.org/wiki/Smoothstep
--    t * t * (3 - 2 * t)
    -- smootherstep https://en.wikipedia.org/wiki/Smoothstep#Variations
    t * t * t * (t * (t * 6 - 15) + 10)
    -- linear
--    t
  )
end


-- Move ball from origin to destination with easing. This function receives
-- the fraction of the time interval from 0 to 1 as the 't' parameter.
local function ltr(t)
  ball_j:setTarget(ease(orig_x, dest_x, t), ease(orig_y, dest_y, t))
end


-- Move ball from destination to origin with easing
local function rtl(t)
  ball_j:setTarget(ease(dest_x, orig_x, t), ease(dest_y, orig_y, t))
end


function love.update(dt)
  -- Update tween timer
  if tween_timer then
    tween_timer = tween_timer + dt
    -- calculate t from 0 to 1
    local t = math.min(tween_timer / tween_time, 1)
    -- call tween function (ltr or rtl), passing t to it
    tween_func(t)

    -- update time string with current tween duration
    time_str = tostring(tween_time * t)

    -- if t is 1, the tween has finished
    if t == 1 then tween_timer = false end
  end
  world:update(dt)
end


function love.draw()
  -- draw ball
  love.graphics.setColor(1, 1, 1)
  local x, y = ball_b:getPosition()
  love.graphics.circle("fill", x, y, radius)
  love.graphics.setColor(0, 0, 0)
  local angle = ball_b:getAngle()
  love.graphics.line(x, y, x + radius * math.cos(angle) * 0.9,
                           y + radius * math.sin(angle) * 0.9)

  -- draw origin and destination
  love.graphics.setColor(1, 0, 0)
  love.graphics.circle("line", orig_x, orig_y, radius)
  love.graphics.setColor(0, 1, 0)
  love.graphics.circle("line", dest_x, dest_y, radius)

  -- draw platform
  love.graphics.setColor(1, 1, 1)
  love.graphics.polygon("fill", platform_b:getWorldPoints(platform_s:getPoints()))

  -- draw time
  love.graphics.setColor(1, 1, 1)
  love.graphics.print(time_str, 0, 0)
end


function love.keypressed(k)
  if k == "escape" then return love.event.quit() end
  if k == "space" then
    -- if we're left of the middle point, go left-to-right, else right-to-left
    if ball_j:getTarget() < (orig_x + dest_x) / 2 then
      tween(2, ltr)
    else
      tween(2, rtl)
    end
  end
end

Coder567
Prole
Posts: 42
Joined: Sun Apr 07, 2019 12:32 pm

Re: Physics object movement q

Post by Coder567 » Tue Oct 01, 2019 8:41 am

@pgimeno ok thanks! will try that later when I get the time

Coder567
Prole
Posts: 42
Joined: Sun Apr 07, 2019 12:32 pm

Re: Physics object movement q

Post by Coder567 » Tue Oct 01, 2019 10:12 am

@pgimeno ok that definitely works. The math is way over my head though :)

User avatar
pgimeno
Party member
Posts: 1873
Joined: Sun Oct 18, 2015 2:58 pm
Location: Valencia, ES

Re: Physics object movement q

Post by pgimeno » Tue Oct 01, 2019 3:15 pm

Use a tweening library like https://github.com/kikito/tween.lua, it does the math for you.

Post Reply

Who is online

Users browsing this forum: No registered users and 7 guests