howto, teaching

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:

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:

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:

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