How to use self. and how to run a script multiple times

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
User avatar
NoreoAlles
Party member
Posts: 107
Joined: Mon Jan 03, 2022 5:42 pm

How to use self. and how to run a script multiple times

Post by NoreoAlles »

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().
main.lua

Code: Select all

function love.load()
    require"cube"
end

function love.update()
    cube:update(dt)
end

function love.draw()
    cube:draw()
end
cube.lua

Code: Select all

cube = {}
function cube:load()
self.x = 0
self.y = 0
self.sx = 50
self.sy = 50
end

function cube:update(dt)
end 

function cube:draw()
    love.graphics.rectangle("fill", self.x, self.y, self.sx, self.sy)
end
"Why do they call it oven when you of in the cold food of out hot eat the food?" - Jon Arbuckle
User avatar
pgimeno
Party member
Posts: 3550
Joined: Sun Oct 18, 2015 2:58 pm

Re: How to use self. and how to run a script multiple times

Post by pgimeno »

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.
User avatar
NoreoAlles
Party member
Posts: 107
Joined: Mon Jan 03, 2022 5:42 pm

Re: How to use self. and how to run a script multiple times

Post by NoreoAlles »

Thank you!
"Why do they call it oven when you of in the cold food of out hot eat the food?" - Jon Arbuckle
Post Reply

Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 223 guests