Getting Started with Lua + LÖVE: Part 3

Series:

Notes on this guide:

This part is written under the assumption of using  ZeroBrane Studio, an IDE introduced in the first part. However, and assuming LÖVE is installed on the system, all examples will work when run from within the current working directory of the “main.lua” file using “love ./” to execute on the entire current directory.

Box2D Physics

LÖVE uses Box2D as the underlining physics system. This means that LÖVE supports rigid body calculations and can support multiple body shapes.

The first step toward changing the initial pixel-based movement to incorporating a physics systems is to create a world and set the unit measurement.

GitHb Gist:

A meter will be 64px
love.physics.setMeter(64)
Set the X gravity, Y gravity, and if objects can sleep
world = love.physics.newWorld( 0, 0, true )

view raw
physics.lua
hosted with ❤ by GitHub

Pre-Formatted:

  love.physics.setMeter(64)
  world = love.physics.newWorld( 0, 0, true )

Once a world has been created, bodies can be added to the world. From bodies, shapes can be added through fixtures.

In LÖVE, a body can dictate where one or more shapes start. Through using fixtures, shapes and bodies are combined.

In order to move, a body needs to be set to the type “dynamic”.

Changing the “player” table into this new model results in the following:

GitHub Gist:

Create a player table
player = {}
Create a width (for later drawing)
player.width = 20
Create a height (for later drawing)
player.height = 20
Create a new physics body in the world and make it "dynamic"
The new coordinates will be where the 'body' is going forward.
Any time (like for drawing) the x,y is needed use getX() and getY()
player.body = love.physics.newBody( world, 100, 100, "dynamic" )
Make a rectangle shape with:
Starting at 100, 100 (player.body:getX() and player.body:getY() )
a width of player.width
a height of player.height
player.shape = love.physics.newRectangleShape(player.body:getX(), player.body:getY(), player.width, player.height)
Attach the shape to the body
player.fixture = love.physics.newFixture(player.body, player.shape, 1);

view raw
player.lua
hosted with ❤ by GitHub

Pre-Formatted:

  player = {}
  player.width = 20
  player.height = 20
  
  player.body = love.physics.newBody( world, 100, 100, "dynamic" )
  
  player.shape = love.physics.newRectangleShape(player.body:getX(), player.body:getY(), player.width, player.height) 
  
  player.fixture = love.physics.newFixture(player.body, player.shape, 1)

With the love.load section changed, the love.update function also needs to use the new physics system. Instead of moving by pixels like in the second part, forces will be applied to the new body.

GitHub Gist:

function love.update(dt)
Feed the world the current delta time (dt)
world:update(dt)
if love.keyboard.isDown("up") then
player.body:applyForce(0, 40)
end
if love.keyboard.isDown("down") then
player.body:applyForce(0, 40)
end
if love.keyboard.isDown("left") then
player.body:applyForce(40, 0)
end
if love.keyboard.isDown("right") then
player.body:applyForce(40, 0)
end
end

view raw
update.lua
hosted with ❤ by GitHub

Pre-formatted:

function love.update(dt)
  
  world:update(dt)
  
  if love.keyboard.isDown("up") then
    player.body:applyForce(0, -40)
  end
  
  if love.keyboard.isDown("down") then
    player.body:applyForce(0, 40)
  end
  
  if love.keyboard.isDown("left") then
    player.body:applyForce(-40, 0)
  end
  
  if love.keyboard.isDown("right") then
    player.body:applyForce(40, 0)
  end
  
end

Finally, the love.draw function needs to be changed. As pixel-by-pixel moving is no longer used, the draw functions cannot use the player.x and player.y coordinates. Instead, the position of the physics body will be used.

GitHub Gist:

function love.draw()
Draw the rectangle using:
"fill" (fill in the shape)
Using the X of player.body
Using the Y of player.body
Using the player.width
Using the player.height
love.graphics.rectangle("fill", player.body:getX(), player.body:getY(), player.width, player.height )
end

view raw
draw.lua
hosted with ❤ by GitHub

Pre-formatted:

function love.draw()
love.graphics.rectangle("fill", player.body:getX(), player.body:getY(), player.width, player.height )

end

Updated “main.lua” Example

function love.load()
A meter will be 64px
love.physics.setMeter(64)
Set the X gravity, Y gravity, and if objects can sleep
world = love.physics.newWorld( 0, 0, true )
Create a table table
player = {}
Create a width (for later drawing)
player.width = 20
Create a height (for later drawing)
player.height = 20
Create a new physics body in the world and make it "dynamic"
The new coordinates will be where the 'body' is going forward.
Any time (like for drawing) the x,y is neededm use getX() and getY()
player.body = love.physics.newBody( world, 100, 100, "dynamic" )
Make a rectangle shape with:
Starting at 100, 100 (player.body:getX() and player.body:getY() )
a width of player.width
a height of player.height
player.shape = love.physics.newRectangleShape(player.body:getX(), player.body:getY(), player.width, player.height)
Attach the shape to the body
player.fixture = love.physics.newFixture(player.body, player.shape, 1);
end
function love.update(dt)
Feed the world the current delta time (dt)
world:update(dt)
if love.keyboard.isDown("up") then
player.body:applyForce(0, 40)
end
if love.keyboard.isDown("down") then
player.body:applyForce(0, 40)
end
if love.keyboard.isDown("left") then
player.body:applyForce(40, 0)
end
if love.keyboard.isDown("right") then
player.body:applyForce(40, 0)
end
end
function love.draw()
Draw the rectangle using:
"fill" (fill in the shape)
Using the X of player.body
Using the Y of player.body
Using the player.width
Using the player.height
love.graphics.rectangle("fill", player.body:getX(), player.body:getY(), player.width, player.height )
end

view raw
main.lua
hosted with ❤ by GitHub