Getting Started with Lua + LÖVE: Part 5

Series:

Object-Oriented (-ish)

Lua is not an object-oriented programming language. It can replicate parts, but most techniques for doing this are complicated. Fortunately, most of the functionality that is commonly associated with object-oriented programming can be easily emulated in Lua through using a “classic” library.

Note: This example assumes that “classic.lua” is in the same directory as the other files. For larger projects, it is recommended to move it, and change the require() line(s), to something like “libs/classic.lua” and only require it once across the whole project.

Combined with the existing require() function, “classic.lua” can be used a module in Lua.

GitHub Gist:

Object = require("classic")
Player = Object:extend()

view raw
object.lua
hosted with ❤ by GitHub

Pre-formatted:

Object = require("classic")

Player = Object:extend()

Once the Player object is now extended (using the Object:extend() function), it can be treated like an object in other programming languages. Using the “self” keyword (which acts like “this” in other programming languages) connects the key-value pair to the name of object, allowing things like Player.body to access an internal key-value pair and Player:draw() to access the function call.

Note: The use of the colon to make function calls in Lua is part of the structure of the language. It is the accessing of the self as part of the function call.

With that change, all previous “player” table names get converted into “self” references within the new object.

GitHib Gist:

Object = require("classic")
Player = Object:extend()
function Player:new(world)
Add an image from the filename "player.png"
self.image = love.graphics.newImage( "player.png" )
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()
self.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.image:getWidth()
a height of player.image.getHeight()
self.shape = love.physics.newRectangleShape(
self.body:getX(),
self.body:getY(),
self.image:getWidth( ),
self.image:getHeight( )
)
Attach the shape to the body
self.fixture = love.physics.newFixture(self.body, self.shape, 1);
end
function Player:update()
if love.keyboard.isDown("up") then
self.body:applyForce(0, 40)
end
if love.keyboard.isDown("down") then
self.body:applyForce(0, 40)
end
if love.keyboard.isDown("left") then
self.body:applyForce(40, 0)
end
if love.keyboard.isDown("right") then
self.body:applyForce(40, 0)
end
end
function Player:draw()
Draw the player.image texture at the coordinates of getX() and getY()
love.graphics.draw(self.image, self.body:getX(), self.body:getY() )
end

view raw
player.lua
hosted with ❤ by GitHub

Pre-formatted:

Object = require("classic")

Player = Object:extend()

function Player:new(world)
  
  self.image = love.graphics.newImage( "player.png" )
  
  self.body = love.physics.newBody( world, 100, 100, "dynamic" )
  
  self.shape = love.physics.newRectangleShape(
    self.body:getX(),
    self.body:getY(),
    self.image:getWidth( ),
    self.image:getHeight( )
  ) 
  
  self.fixture = love.physics.newFixture(self.body, self.shape, 1);

end

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

end

function Player:draw()

  love.graphics.draw(self.image, self.body:getX(), self.body:getY() )

end

With the functionality moved into the “player.lua” object, the original “main.lua” is also changed.

Updated “main.lua” Example:

GitHub Gist:

require("player")
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 )
Send the world to the player so that it will be also be in the "world"
player = Player(world)
end
function love.update(dt)
Feed the world the current delta time (dt)
world:update(dt)
Update the player object
player:update()
end
function love.draw()
Draw the player object
player:draw()
end

view raw
main.lua
hosted with ❤ by GitHub

Pre-Formatted:

require("player")

function love.load()
  
  love.physics.setMeter(64) 
  world = love.physics.newWorld( 0, 0, true )
  player = Player(world)
  
end

function love.update(dt)
  
  world:update(dt)
  player:update()
  
end

function love.draw()
  
  player:draw()
  
end