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)
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:
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
Object = require("classic") | |
Player = Object:extend() |
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:
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
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 |
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:
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
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 |
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