NoreoAlles wrote: ↑Mon Jan 03, 2022 5:58 pm
Hello, i have just recently started using Lua and Löve and i cant grasp the concept of using more then the main.lua file. I am working on a game where i want to make multiple enemies fall from the ceeling and in this example i would like to know how to create multiple cubes of the same script and how to correctly use self.x, self.y, self.sx and self.sy in cube.lua in love.draw().
That's a wide topic! You're basically asking how to do OOP in Lua. Here are the basics.
The first thing you have to understand is the separation between a class an an object, also called instance. The class contains the functions (called methods in OOP jargon) that operate on instances; it rarely contains data. The instances contain the data of each particular object. Using your example, you would have a class Cube (it's customary to capitalize the first letter for classes) and then many instances, each with the position/size of its cube and possibly other data. Inside the class, there are methods that receive an instance as parameter (that's where self comes into play) and do stuff with it.
Inside the class, you add a constructor method. This constructor creates an instance. A constructor is special because it's a "class method": unlike basically every other method in the class, you don't call it with an instance! Depending on your organization, you call it with a class or without any parameter.
In OOP, it's customary that instances contain (or pretend to contain) the methods of the class they belong to. This can be done by either copying the methods from the class to the instance, or by using a metatable. Copying has the advantage of speed, and the disadvantage of bigger memory consumption, with respect to using a metatable.
Here's how your cube.lua might look like:
Code: Select all
-- Define Cube class
local Cube = {}
-- Define Cube metatable
local CubeMT = {__index = Cube}
function Cube:new(x, y, sx, sy)
-- This is the constructor. It doesn't use 'self' in this case.
local obj = {x = x, y = y, sx = sx, sy = sy}
-- Set the metatable of the object. With this, we will pretend that
-- the functions of Cube are also inside the object, without actually
-- having them there.
setmetatable(obj, CubeMT)
-- Return the object
return obj
end
function Cube:update(dt)
-- for example, move each cube at 60 px/s
self.y = self.y + 60 * dt
end
function Cube:draw()
-- Draw self
love.graphics.rectangle("fill", self.x, self.y, self.sx, self.sy)
end
return Cube
That defines the basics of the cube, ready to use. Note that I have made Cube local, not global. This means that every file that needs Cube needs to require it. That's not a problem because the file will be loaded just once anyway, and it's cleaner because then anyone who reads your code will see where it comes from.
Now for main.lua. Imagine we want three falling cubes; we would do something like this:
Code: Select all
local Cube = require 'cube'
local cubes = {} -- this will be an array of instances
function love.load()
cubes[1] = Cube:new(100, 0, 10, 10)
cubes[2] = Cube:new(200, 0, 10, 10)
cubes[3] = Cube:new(300, 0, 10, 10)
end
function love.update(dt)
for i = 1, #cubes do
cubes[i]:update(dt)
end
end
function love.draw()
for i = 1, #cubes do
cubes[i]:draw()
end
end
Note how we use the class for calling Cube:new(), but we use the instances for calling cubes[
i]:update() and :draw() and basically any other method if we had more.
I hope this is enough to get you started.