## [Verlet Integration] Cannot add collision in Rope and Ball situation.

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
nullset2
Prole
Posts: 2
Joined: Mon Sep 27, 2021 8:54 pm

### [Verlet Integration] Cannot add collision in Rope and Ball situation.

Hi! I've been playing around with the Verlet integration API and I have hit a snag.

Based off of the Fantastic Verlet example from this thread, I have setup a rope and ball with cup simulator.

Based on the positions of the first and last nodes, I have set up Love to create a body and a shape corresponding to the cup and ball, accordingly. My understanding is that this talks to the Love2D API and should automatically handle collision, like in the physics tutorial https://love2d.org/wiki/Tutorial:Physics

However, I haven't been able to make it so this registers collisions. I am very certain I am just missing just one little detail. What am I missing?
Attachments
verlet.love
pgimeno
Party member
Posts: 2817
Joined: Sun Oct 18, 2015 2:58 pm

### Re: [Verlet Integration] Cannot add collision in Rope and Ball situation.

There are several issues here.

First, love.physics.newPolygonShape has a limit of 8 points, and the polygons must be convex. Yours has more points and isn't convex. You can solve that by using four rectangles and four fixtures for the cup's body.

Second, you made a typo: you used self.objects.ball.body:setY when you should be using self.objects.cup.body:setY (i.e. you used ball instead of cup for the Y coordinate of the cup).

Third, you don't use anything from the love.physics world. You add some objects and move them but never query where they are or anything. You could as well not create the physical world and nothing would change.

Fourth, even if all that were fixed, you can't expect love.physics to react to the collisions if you don't let it move things according to physics. If you want proper collision reaction, you need to let the love.physics world do the movement.

In the thread you've linked, I wanted to avoid love.physics, but since that doesn't seem to be your case, note that you can make a rubber string (or a rigid-ish string) with love.physics.

I can't write an example right now and I'll be busy for about 24 hours, but I'll try to write a PoC as soon as I can.
pgimeno
Party member
Posts: 2817
Joined: Sun Oct 18, 2015 2:58 pm

### Re: [Verlet Integration] Cannot add collision in Rope and Ball situation.

And here it is:

Code: Select all

local metre = 64
local lp = love.physics
local lg = love.graphics

local nSegments = 20
local initialCupX = 400
local initialCupY = 0
local initialBallX = initialCupX
local initialBallY = 500

local function lerp(a, b, t)
return t < 0.5 and a + (b - a) * t or b + (a - b) * (1 - t)
end

local objs = {}

lp.setMeter(metre)
local world = lp.newWorld(0, 9.81*metre, true)

objs.cup = {}
objs.cup.body = lp.newBody(world, initialCupX, initialCupY, "dynamic")
objs.cup.body:setFixedRotation(true) -- don't rotate the cup
-- The position of the rectangle is the centre, not the top left, so we add
-- half the width/height to the top left of each rectangle to get the centre
objs.cup.shapes = {}
objs.cup.shapes[1] = lp.newRectangleShape(-60+20/2, -60+40/2,   20, 40)
objs.cup.shapes[2] = lp.newRectangleShape( 40+20/2, -60+40/2,   20, 40)
objs.cup.shapes[3] = lp.newRectangleShape(-60+120/2, -20+20/2,  120, 20)
objs.cup.shapes[4] = lp.newRectangleShape(-10+20/2,   0+60/2,   20, 60)

objs.cup.fixtures = {}
for i = 1, #objs.cup.shapes do
objs.cup.fixtures[i] = lp.newFixture(objs.cup.body, objs.cup.shapes[i])
-- Don't bounce too much.
objs.cup.fixtures[i]:setRestitution(0.5)
end

-- Add a mouse joint for the cup.
objs.cup.joint = lp.newMouseJoint(objs.cup.body, objs.cup.body:getPosition())

objs.ball = {}
objs.ball.body = lp.newBody(world, initialBallX, initialBallY, "dynamic")
objs.ball.shape = lp.newCircleShape(25)
objs.ball.fixture = lp.newFixture(objs.ball.body, objs.ball.shape)

objs.string = {}
-- Make the string from the bottom of the cup to the ball
local prevX, prevY = initialCupX, initialCupY+60
for i = 1, nSegments-1 do
local segment = {}
local x, y = lerp(initialCupX, initialBallX, i/nSegments),
lerp(initialCupY+60, initialBallY, i/nSegments)
segment.body = lp.newBody(world, x, y, "dynamic")
-- A distance joint has some spring effect already; you can play with
-- DistanceJoint:setFrequency to make it more elastic.
segment.joint = lp.newDistanceJoint(
i == 1 and objs.cup.body or objs.string[i-1].body, segment.body,
prevX, prevY, x, y
)
-- This causes issues, not sure why.
--  segment.shape = lp.newRectangleShape(1, 1)
--  segment.fixture = lp.newFixture(segment.body, segment.shape)

objs.string[i] = segment
prevX, prevY = x, y
end

do
-- Final segment goes from the last body to the ball
local x, y = objs.ball.body:getPosition()
objs.ball.joint = lp.newDistanceJoint(
objs.string[nSegments-1].body, objs.ball.body, prevX, prevY, x, y
)
end

function love.keypressed(k) return k == "escape" and love.event.quit() end

-- Avoid jerks before the mouse is moved for the first time
-- (at the cost of stealing the mouse once)
love.mouse.setPosition(0, 0)
love.event.pump()
love.mouse.setPosition(400, 300)
objs.cup.body:setPosition(400.5, 300.5)

function love.update(dt)
objs.cup.joint:setTarget(love.mouse.getPosition())
world:update(dt)
end

function love.draw()
for i = 1, #objs.cup.shapes do
lg.polygon("line", objs.cup.body:getWorldPoints(objs.cup.shapes[i]:getPoints()))
end
for i = 0, nSegments - 1 do
local x1, y1, x2, y2
if i == 0 then
x1, y1 = objs.cup.body:getPosition()
y1 = y1 + 60
else
x1, y1 = objs.string[i].body:getPosition()
end
if i == nSegments - 1 then
x2, y2 = objs.ball.body:getPosition()
else
x2, y2 = objs.string[i+1].body:getPosition()
end
lg.line(x1, y1, x2, y2)
end
end

Attachments
cup_and_ball.love
nullset2
Prole
Posts: 2
Joined: Mon Sep 27, 2021 8:54 pm

### Re: [Verlet Integration] Cannot add collision in Rope and Ball situation.

This is fantastic by the way. I would had liked to use the exact same physics I got from the verlet integration but this approach works, will just tinker some of the parameters to get the right kind of "feel" to it and finish building my game.