How to set friction between objects??

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
milkbomb11
Prole
Posts: 21
Joined: Mon Jan 07, 2019 12:38 pm

How to set friction between objects??

Post by milkbomb11 »


I was testing out the tutorial in the love.physic wiki page.
Then I wanted to add friction to the ball so that the ball can slow down naturally when it's on the ground.
So I used Fixture:setFriction() at the ball and tested the program again but the ball didn't seem to slow down naturally(It just kept on moving)
Is setFriction() broken or am I doing something wrong?


The Fixture:setFriction() is at line 19(Inside love.load and inside the block of code that creates the ball)

Code: Select all

function love.load()
  love.physics.setMeter(64) --the height of a meter our worlds will be 64px
  world = love.physics.newWorld(0, 9.81*64, true) --create a world for the bodies to exist in with horizontal gravity of 0 and vertical gravity of 9.81

  objects = {} -- table to hold all our physical objects

  --let's create the ground
  objects.ground = {}
  objects.ground.body = love.physics.newBody(world, 650/2, 650-50/2) --remember, the shape (the rectangle we create next) anchors to the body from its center, so we have to move it to (650/2, 650-50/2)
  objects.ground.shape = love.physics.newRectangleShape(650, 50) --make a rectangle with a width of 650 and a height of 50
  objects.ground.fixture = love.physics.newFixture(objects.ground.body, objects.ground.shape); --attach shape to body

  --let's create a ball
  objects.ball = {}
  objects.ball.body = love.physics.newBody(world, 650/2, 650/2, "dynamic") --place the body in the center of the world and make it dynamic, so it can move around
  objects.ball.shape = love.physics.newCircleShape(20) --the ball's shape has a radius of 20
  objects.ball.fixture = love.physics.newFixture(objects.ball.body, objects.ball.shape, 10) -- Attach fixture to body and give it a density of 1.
  --objects.ball.fixture:setRestitution(0.9) --let the ball bounce
  objects.ball.fixture:setFriction(1) -- Here is the  setFriction() which isn't working

  --let's create a couple blocks to play around with
  objects.block1 = {}
  objects.block1.body = love.physics.newBody(world, 200, 550, "dynamic")
  objects.block1.shape = love.physics.newRectangleShape(0, 0, 50, 100)
  objects.block1.fixture = love.physics.newFixture(objects.block1.body, objects.block1.shape, 5) -- A higher density gives it more mass.

  objects.block2 = {}
  objects.block2.body = love.physics.newBody(world, 200, 400, "dynamic")
  objects.block2.shape = love.physics.newRectangleShape(0, 0, 100, 50)
  objects.block2.fixture = love.physics.newFixture(objects.block2.body, objects.block2.shape, 2)

  --initial graphics setup
  love.graphics.setBackgroundColor(0.41, 0.53, 0.97) --set the background color to a nice blue
  love.window.setMode(650, 650) --set the window dimensions to 650 by 650
end


function love.update(dt)
  world:update(dt) --this puts the world into motion

  --here we are going to create some keyboard events
  if love.keyboard.isDown("right") then --press the right arrow key to push the ball to the right
    objects.ball.body:applyForce(400, 0)
  elseif love.keyboard.isDown("left") then --press the left arrow key to push the ball to the left
    objects.ball.body:applyForce(-400, 0)
  elseif love.keyboard.isDown("up") then --press the up arrow key to set the ball in the air
    objects.ball.body:setPosition(650/2, 650/2)
    objects.ball.body:setLinearVelocity(0, 0) --we must set the velocity to zero to prevent a potentially large velocity generated by the change in position
  end

end

function love.draw()
  love.graphics.setColor(0.28, 0.63, 0.05) -- set the drawing color to green for the ground
  love.graphics.polygon("fill", objects.ground.body:getWorldPoints(objects.ground.shape:getPoints())) -- draw a "filled in" polygon using the ground's coordinates

  love.graphics.setColor(0.76, 0.18, 0.05) --set the drawing color to red for the ball
  love.graphics.circle("fill", objects.ball.body:getX(), objects.ball.body:getY(), objects.ball.shape:getRadius())

  love.graphics.setColor(0.20, 0.20, 0.20) -- set the drawing color to grey for the blocks
  love.graphics.polygon("fill", objects.block1.body:getWorldPoints(objects.block1.shape:getPoints()))
  love.graphics.polygon("fill", objects.block2.body:getWorldPoints(objects.block2.shape:getPoints()))
end
P.S: Sorry if my grammar sucks: my native tongue is not English
Ross
Citizen
Posts: 98
Joined: Tue Mar 13, 2018 12:12 pm
Contact:

Re: How to set friction between objects??

Post by Ross »

You will need to set some friction on both objects: ball and the ground.

The physics engine combines friction coefficients with the formula:

Code: Select all

friction = sqrt(friction_a * friction_b)
So if the friction setting of either fixture is zero, the final friction for their contact will be zero.
User avatar
ivan
Party member
Posts: 1911
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: How to set friction between objects??

Post by ivan »

Yes, Ross is correct.
You need to set the friction for both objects so that it's greater than 0.
Alternatively, there is:
https://love2d.org/wiki/Contact:setFriction
milkbomb11
Prole
Posts: 21
Joined: Mon Jan 07, 2019 12:38 pm

Re: How to set friction between objects??

Post by milkbomb11 »

Ross wrote: Tue Jan 08, 2019 2:42 pm You will need to set some friction on both objects: ball and the ground.

The physics engine combines friction coefficients with the formula:

Code: Select all

friction = sqrt(friction_a * friction_b)
So if the friction setting of either fixture is zero, the final friction for their contact will be zero.
I set the friction of the ground too like this (In love.load and inside the declaration of objects.ground and objects.ball):

Code: Select all

function love.load()
  love.physics.setMeter(64) --the height of a meter our worlds will be 64px
  world = love.physics.newWorld(0, 9.81*64, true) --create a world for the bodies to exist in with horizontal gravity of 0 and vertical gravity of 9.81

  objects = {} -- table to hold all our physical objects

  --let's create the ground
  objects.ground = {}
  objects.ground.body = love.physics.newBody(world, 650/2, 650-50/2) --remember, the shape (the rectangle we create next) anchors to the body from its center, so we have to move it to (650/2, 650-50/2)
  objects.ground.shape = love.physics.newRectangleShape(650, 50) --make a rectangle with a width of 650 and a height of 50
  objects.ground.fixture = love.physics.newFixture(objects.ground.body, objects.ground.shape); --attach shape to body
  objects.ground.fixture:setFriction(50000000000)

  --let's create a ball
  objects.ball = {}
  objects.ball.body = love.physics.newBody(world, 650/2, 650/2, "dynamic") --place the body in the center of the world and make it dynamic, so it can move around
  objects.ball.shape = love.physics.newCircleShape(20) --the ball's shape has a radius of 20
  objects.ball.fixture = love.physics.newFixture(objects.ball.body, objects.ball.shape, 1) 
  --objects.ball.fixture:setRestitution(0.9) --let the ball bounce
  objects.ball.fixture:setFriction(50000000000)

  --let's create a couple blocks to play around with
  objects.block1 = {}
  objects.block1.body = love.physics.newBody(world, 200, 550, "dynamic")
  objects.block1.shape = love.physics.newRectangleShape(0, 0, 50, 100)
  objects.block1.fixture = love.physics.newFixture(objects.block1.body, objects.block1.shape, 5) -- A higher density gives it more mass.

  objects.block2 = {}
  objects.block2.body = love.physics.newBody(world, 200, 400, "dynamic")
  objects.block2.shape = love.physics.newRectangleShape(0, 0, 100, 50)
  objects.block2.fixture = love.physics.newFixture(objects.block2.body, objects.block2.shape, 2)



  --initial graphics setup
  love.graphics.setBackgroundColor(0.41, 0.53, 0.97) --set the background color to a nice blue
  love.window.setMode(650, 650) --set the window dimensions to 650 by 650
end


function love.update(dt)
  world:update(dt) --this puts the world into motion

  --here we are going to create some keyboard events
  if love.keyboard.isDown("right") then --press the right arrow key to push the ball to the right
    objects.ball.body:applyForce(400, 0)
  elseif love.keyboard.isDown("left") then --press the left arrow key to push the ball to the left
    objects.ball.body:applyForce(-400, 0)
  elseif love.keyboard.isDown("up") then --press the up arrow key to set the ball in the air
    objects.ball.body:setPosition(650/2, 650/2)
    objects.ball.body:setLinearVelocity(0, 0) --we must set the velocity to zero to prevent a potentially large velocity generated by the change in position
  end

end

function love.draw()
  love.graphics.setColor(0.28, 0.63, 0.05) -- set the drawing color to green for the ground
  love.graphics.polygon("fill", objects.ground.body:getWorldPoints(objects.ground.shape:getPoints())) -- draw a "filled in" polygon using the ground's coordinates

  love.graphics.setColor(0.76, 0.18, 0.05) --set the drawing color to red for the ball
  love.graphics.circle("fill", objects.ball.body:getX(), objects.ball.body:getY(), objects.ball.shape:getRadius())

  love.graphics.setColor(0.20, 0.20, 0.20) -- set the drawing color to grey for the blocks
  love.graphics.polygon("fill", objects.block1.body:getWorldPoints(objects.block1.shape:getPoints()))
  love.graphics.polygon("fill", objects.block2.body:getWorldPoints(objects.block2.shape:getPoints()))
end
But it didn't work: The ball still slides without a change of velocity until it collides with the blocks
Ross
Citizen
Posts: 98
Joined: Tue Mar 13, 2018 12:12 pm
Contact:

Re: How to set friction between objects??

Post by Ross »

Haha. Well, I actually had to ask someone else to look at this to figure it out. There's nothing wrong with the friction or your setup, it's just that . . . it's a ball, it's rolling.

If you add this bit of code to your draw function you will be able to see it:

Code: Select all

  local x, y = objects.ball.body:getX(), objects.ball.body:getY()
  local angle = objects.ball.body:getAngle()
  local dx, dy = math.cos(angle) * 20, math.sin(angle) * 20
  love.graphics.setColor(1, 1, 1, 1)
  love.graphics.line(x, y, x + dx, y + dy)
If you don't want it to roll you can use Body:setFixedRotation.

Also, FYI, friction is generally between 0 and 1.
milkbomb11
Prole
Posts: 21
Joined: Mon Jan 07, 2019 12:38 pm

Re: How to set friction between objects??

Post by milkbomb11 »

Ross wrote: Wed Jan 09, 2019 2:27 pm Haha. Well, I actually had to ask someone else to look at this to figure it out. There's nothing wrong with the friction or your setup, it's just that . . . it's a ball, it's rolling.

If you add this bit of code to your draw function you will be able to see it:

Code: Select all

  local x, y = objects.ball.body:getX(), objects.ball.body:getY()
  local angle = objects.ball.body:getAngle()
  local dx, dy = math.cos(angle) * 20, math.sin(angle) * 20
  love.graphics.setColor(1, 1, 1, 1)
  love.graphics.line(x, y, x + dx, y + dy)
If you don't want it to roll you can use Body:setFixedRotation.

Also, FYI, friction is generally between 0 and 1.
Thanks Ross! setFixedRotation worked! :D
Post Reply

Who is online

Users browsing this forum: Bing [Bot] and 145 guests