attempt to call method 'draw' a nil value

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
RonanZero
Citizen
Posts: 90
Joined: Mon Oct 20, 2014 3:33 am

attempt to call method 'draw' a nil value

Post by RonanZero »

In my unit code, I have this:

Code: Select all

function unit:draw()
	love.graphics.draw(unit.img, unit.x, unit.y)
end
And I call it in love.draw() like this:

Code: Select all

for i, unit in ipairs(units) do
			unit:draw()
		end
It says attempt to call method 'draw' a nil value

Oh and, yes, unit code is being loaded, obviously. And unit is a table with x, y, hp, stuff like that in it.

EDIT: Might as well put the whole unit code, since I get an error on unit:draw func anyway, about x/y being tables not numbers... here it is... help me fix dis too :P

Code: Select all

units = {}
unit = {
	x = {},
	y = {},
	speed = 100,
	color = "255, 255, 255",
	hp = 40,
	img = love.graphics.newImage("resource/unit_green.png"),
	laserdmg = 10
}

function unit.create(xpos, ypos)
table.insert(unit.x, xpos)
table.insert(unit.y, ypos)
units[#units+1] = {x=xpos, y=ypos}
end

function unit:draw()
	love.graphics.draw(unit.img, unit.x, unit.y)
end

function unit:update(dt)

end
while true do end;
User avatar
ArchAngel075
Party member
Posts: 319
Joined: Mon Jun 24, 2013 5:16 am

Re: attempt to call method 'draw' a nil value

Post by ArchAngel075 »

instead try

Code: Select all

    
 for i, unit in pairs(units) do
  unit:draw()
 end
(Ive only really worked with pairs() and not ipairs)


next im not sure about how you instantiate your units with unit.Create, ive only ever used:

Code: Select all

 object:new()
  local o = {}
  setmetatable(o, self)
  self.__index = self
  return o
 end
and more recently a larger function to allow inheritance....
User avatar
zorg
Party member
Posts: 3444
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: attempt to call method 'draw' a nil value

Post by zorg »

Love complains because unit.x and unit.y are tables, not numbers.
The thing is, you don't even need those tables since you save the x and y in the units table anyway. The code

Code: Select all

function unit:draw()
    love.graphics.draw(unit.img, units.x, units.y
would work, but you don't iterate over all the units with that, so:

Code: Select all

function unit:draw()
    for i,v in ipairs(units) do
        love.graphics.draw(unit.img, v.x, v.y)
    end
end
I did assume that you wanted to use the same image for all of them.
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.
davisdude
Party member
Posts: 1154
Joined: Sun Apr 28, 2013 3:29 am
Location: North Carolina

Re: attempt to call method 'draw' a nil value

Post by davisdude »

You could use pairs, but ipairs would work better because of how the table is made.
Also, don't forget things like:

Code: Select all

units = {}
unit = {}
unit.__index = unit
setmetatable( unit, units )

function unit.create(x, y)
	local new = {x=x, y=y}
	new.__index = new
	setmetatable( new, unit )
	return new
end
	
function unit:draw()
	love.graphics.circle( 'fill', self.x, self.y, 2 )
end

-- Example:
function love.load()
	new = unit.create( 32, 32 )
end

function love.draw()
	new:draw()
end
GitHub | MLib - Math and shape intersections library | Walt - Animation library | Brady - Camera library with parallax scrolling | Vim-love-docs - Help files and syntax coloring for Vim
User avatar
zorg
Party member
Posts: 3444
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: attempt to call method 'draw' a nil value

Post by zorg »

of course, you do not need to use metatables for something simple:

Code: Select all

local units = {}

local draw = function(self)
    love.graphics.circle( 'fill', self.x, self.y, 2 )
end

local update = function(self,dt)
    -- meh
end

local unit = {}

function unit.create(x, y)
   local new = {x=x, y=y}
   new.draw = draw
   new.update = update
   units[#units+1] = new
   return new
end

-- Example:
function love.load()
   new = unit.create( 32, 32 )
end

function love.draw()
   --new:draw() -- this would work too
   for i,v in ipairs(units) do
      v:draw()
   end
end

function love.update(dt)
   --new:update(dt) -- this would work too
   for i,v in ipairs(units) do
      v:update(dt)
   end
end
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.
davisdude
Party member
Posts: 1154
Joined: Sun Apr 28, 2013 3:29 am
Location: North Carolina

Re: attempt to call method 'draw' a nil value

Post by davisdude »

True. You don't have to use metatables, they have their pros and cons:
Pros:
- Less typing (if you have lots of functions, you don't need to make a value for them each time).
- Less memory (since the table variables are created each time, it takes more memory. Probably not substantial, but when it matters, it could help).

Cons:
- Makes code a bit more complicated.
- Possible confusion due to multiple functions with the same name.

Can't think of any others, but I'm sure there are more. In general, in my opinion, it's a good practice to use metatables.
GitHub | MLib - Math and shape intersections library | Walt - Animation library | Brady - Camera library with parallax scrolling | Vim-love-docs - Help files and syntax coloring for Vim
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot] and 195 guests