OOP in Love2D

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
jthistle
Prole
Posts: 5
Joined: Mon Sep 05, 2016 7:47 pm

OOP in Love2D

Post by jthistle »

I'm having some trouble with writing a class in Lua with Love2D. I use the following code for my class:

Code: Select all

Planet = {
	bgColour = {0,0,0},
	landColour = {0,0,0},
	size = 100,
	landPoints = {
		
	}
} -- the class table


function Planet:new()
	self = setmetatable({}, self)
	
	self.__index = self -- failed table lookups on the instances should fallback to the class table, to get methods
	
	self.bgColour = {love.math.random(0,255), love.math.random(0,255), love.math.random(0,255)}
	self.landColour = {love.math.random(0,255), love.math.random(0,255), love.math.random(0,255)}
	self.size = 100
	self.landPoints = {}
	
	-- create the terrain
	for j=1,love.math.random(1,10) do
		tempPoints = {}
		
		-- start point
		table.insert(tempPoints, love.math.random(-self.size, self.size))
		table.insert(tempPoints, love.math.random(-self.size, self.size))
	
		-- each continent has a set of points for drawing
		for i=1,love.math.random(5,8) do
			lastPoint = {tempPoints[tableLength(tempPoints)-1], tempPoints[tableLength(tempPoints)]}
			
			sizeCoef = 2
			
			table.insert(tempPoints, love.math.random(lastPoint[1]-(self.size/sizeCoef), lastPoint[1]+(self.size/sizeCoef)))
			table.insert(tempPoints, love.math.random(lastPoint[2]-(self.size/sizeCoef), lastPoint[2]+(self.size/sizeCoef)))
		end

		
		table.insert(self.landPoints, tempPoints)
	end
	
	
	
	
	return self
end

function Planet:getSize()
	return self.size
end

function Planet:draw(centre)
	-- Draw the planet (table centre as {x=number, y=number})
	
	love.graphics.push()
	love.graphics.translate(centre.x, centre.y)
	love.graphics.setColor(self.bgColour)
	love.graphics.circle("fill", 0,0, self.size)
	love.graphics.setColor(self.landColour)
	love.graphics.stencil(function () love.graphics.circle("fill", 0,0, self.size) end , "replace", 1, false)
	love.graphics.setStencilTest("greater", 0)
	
	for ind, points in pairs(self.landPoints) do
		love.graphics.polygon("fill", points)
	end
	
	love.graphics.setStencilTest()
	love.graphics.pop()
end
However, when I create a new instance:

Code: Select all

planet = Planet:new()
and then try to run a method:

Code: Select all

print(planet:getSize())
I get the error:

Code: Select all

Attempt to call method getSize (a nil value)
I've tried rewriting it again and again, in different ways, but this error has always come up. The class constructor is stored in a separate file which I require at the start of the main.lua file. Any help? Thanks in advance.
User avatar
Azhukar
Party member
Posts: 478
Joined: Fri Oct 26, 2012 11:54 am

Re: OOP in Love2D

Post by Azhukar »

Here's how you can implement a class:

Code: Select all

local classMeta = {
	__call = function(self,...) --creates a new class instance
		local new = setmetatable({},self)
		if (self.init ~= nil) then
			new:init(...) --constructor
		end
		return new
	end,
}
local function newClass() --creates a new class
	local class = setmetatable({},classMeta) --allows new class to be called as a function
	class.__index = class
	return class
end

classPlanet = newClass()

classPlanet.size = 100 --default class value

function classPlanet:init()
	self.bgColour = {love.math.random(0,255), love.math.random(0,255), love.math.random(0,255)}
	self.landColour = {love.math.random(0,255), love.math.random(0,255), love.math.random(0,255)}
	self.landPoints = {}
end

function classPlanet:getSize()
	return self.size
end

planet = classPlanet()
print(planet:getSize())
There's many class libraries to pick from if you look.
User avatar
bartbes
Sex machine
Posts: 4946
Joined: Fri Aug 29, 2008 10:35 am
Location: The Netherlands
Contact:

Re: OOP in Love2D

Post by bartbes »

The problem is fairly simple, and is caused by these lines:

Code: Select all

function Planet:new()
	self = setmetatable({}, self)
	
	self.__index = self -- failed table lookups on the instances should fallback to the class table, to get methods
The problem is that in the last line self points to the object you're constructing, but not the class. I've got to say, replacing self is a fairly confusing thing to do in the first place. The easiest way to solve this is to not try to set __index every time you create an instance (everybody seems to be doing this lately, is there some tutorial that tells people to do this?), but to set it once beforehand. So replacing those lines with the following should work.

Code: Select all

Planet.__index = Planet

function Planet:new()
    self = setmetatable({}, self)
Of course I should recommend not replacing self, so you don't confuse yourself or any future readers.
User avatar
jthistle
Prole
Posts: 5
Joined: Mon Sep 05, 2016 7:47 pm

Re: OOP in Love2D

Post by jthistle »

Ah, thanks bartbes, that worked great. Yes, you're right, I got it from a tutorial - evidently not a very good one. Thanks!
User avatar
zorg
Party member
Posts: 3465
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: OOP in Love2D

Post by zorg »

jthistle wrote: Sat Oct 21, 2017 5:47 pm Ah, thanks bartbes, that worked great. Yes, you're right, I got it from a tutorial - evidently not a very good one. Thanks!
Could you share which tut you got the info from? maybe they can fix it or something.
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
User avatar
jthistle
Prole
Posts: 5
Joined: Mon Sep 05, 2016 7:47 pm

Re: OOP in Love2D

Post by jthistle »

Sorry zorg, I can't seem to find it. It was quite an old non Love-related OOP tutorial in Lua though, so I doubt it would be changed now.
Post Reply

Who is online

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