Series:
- Getting Started with Lua + LÖVE: Part 1 (Building, Installing, and Testing)
- Getting Started with Lua + LÖVE: Part 2 (Loading, Updating, and Drawing)
- Getting Started with Lua + LÖVE: Part 3 (Basic Physics)
- Getting Started with Lua + LÖVE: Part 4 (Using Images)
- Getting Started with Lua + LÖVE: Part 5 (Object-Oriented)
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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
— 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 ) |
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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
— 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); |
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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Pre-formatted:
function love.draw() love.graphics.rectangle("fill", player.body:getX(), player.body:getY(), player.width, player.height ) end
Updated “main.lua” Example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |