Love2d "bad argument #2 to 'draw' (Quad expected, got nil)" - lua

I am currently trying to make a flappy bird copy and I am having trouble when attempting to spawn in pipes (when a pipe should spawn I get the following error: "bad argument #2 to 'draw' (Quad expected, got nil)").
The functions that are causing the problem are the following (they are located in three different classes):
Pipe = Class{}
local PIPE_IMAGE = love.graphics.newImage('FlappyBirdPipe.png')
PIPE_SCROLL = -60
PIPE_WIDTH = 20
PIPE_HEIGHT = 160
function Pipe:init(orientation, y)
self.x = VIRTUAL_WIDTH
self.y = y
self.width = PIPE_IMAGE:getWidth()
self.height = PIPE_HEIGHT
self.orientation = orientation
end
function Pipe:render()
love.graphics.draw(PIPE_IMAGE, self.x,
(self.orientation == 'top' and self.y + PIPE_HEIGHT or self.y),
0, 1, (self.orientation == 'top' and -1 or 1))
end
function PipePair:update(dt)
if self.x > -PIPE_WIDTH then
self.x = self.x - PIPE_SCROLL * dt
self.pipes['lower'].x = self.X
self.pipes['upper'].x = self.x
else
self.remove = true
end
end
If anything is unclear or I have left out some vital information I am more than glad to give more information (I am new to Stack Overflow so I am not really sure how everything here works).
(I am using love2d version 11.3 in vscode)
Edit: I pinpointed the error to how I update the self.x in the Pipe class from the PipePair class' update function. Somehow this altering of self.x seems to make it nil.

I just figured it out!
function PipePair:update(dt)
if self.x > -PIPE_WIDTH then
self.x = self.x - PIPE_SCROLL * dt
self.pipes['lower'].x = self.X
self.pipes['upper'].x = self.x
else
self.remove = true
end
end
There is a capital X on self.pipes['lower'].x = self.X. For so long I have been trying to figure it out and it was all due to an X. Wow, I feel so stupid.

the error is saying that a variable is nil, this might have been caused by a typo. and the problem is being caused because of a capital X in self.X
try:
function PipePair:update(dt)
if self.x > -PIPE_WIDTH then
self.x = self.x - PIPE_SCROLL * dt
self.pipes['lower'].x = self.x -- typo was here
self.pipes['upper'].x = self.x
else
self.remove = true
end
end

Related

Unable to declare a new function in lua, compiler tells me to include an '=' sign near the name of the function

So i have this Util.lua file in which i am making all the functions which will be used across all the states of my game.
This is what my Util File is like
function GenerateQuads(atlas, tilewidth, tileheight)
local sheetWidth = atlas:getWidth() / tilewidth
local sheetHeight = atlas:getHeight() / tileheight
local sheetCounter = 1
local spritesheet = {}
for y = 0, sheetHeight - 1 do
for x = 0, sheetWidth - 1 do
spritesheet[sheetCounter] =
love.graphics.newQuad(x * tilewidth, y * tileheight, tilewidth,
tileheight, atlas:getDimensions())
sheetCounter = sheetCounter + 1
end
end
return spritesheet
end
function table.slice(tbl, first, last, step)
local sliced = {}
for i = first or 1, last or #tbl, step or 1 do
sliced[#sliced+1] = tbl[i]
end
return sliced
end
funtion GenerateQuadsPowerups()
local counter = 1
local quads = {}
return counter
end
note that the last function didn't work at all so i just returned counter for testing, the error message given is :
'=' expected near 'GenerateQuadsPowerups'
"Powerup" is a class i declared using a library class.lua. When i removed the problematic function from Util.lua, the same error was given on the first function i made in the Powerup.lua file.
Here's the class in case it is needed for reference
Powerup = Class{}
funtion Powerup:init()
self.x = VIRTUAL_WIDTH
self.y = VIRTUAL_HEIGHT
self.dx = 0
self.dy = -10
end
-- we only need to check collision with the paddle as only that collisionis relevant to this class
function Powerup:collides()
if self.x > paddle.x or paddle.x > self.x then
return false
end
if self.y > paddle.y or self.y > paddle.y then
return false
end
return true
end
funtion Powerup:update(dt)
self.y = self.y + self.dy * dt
if self.y <= 0 then
gSounds['wall-hit']:play()
self = nil
end
end
I can't understand what's going on here
Typo 1
funtion GenerateQuadsPowerups()
Typo 2
funtion Powerup:init()
Typo 3
funtion Powerup:update(dt)
self = nil achieves nothing btw. I guess you thought you could somehow destroy your PowerUp that way but it will only assign nil to self which is just a variable local to Powerup:update. It will go out of scope anyway.

Attempted to index "self" a nil value

I am working on a powerup class for a project and when I try to run it I get an error saying "attempted to index "self" a nil value. I would really appreciate if somebody helped me. Thanks for reading!
PS: Yes, I am using colons and not dots for my Render, Init, Update functions.
function Powerup:init()
-- simple positional and dimensional variables
self.x = x
self.y = y
self.width = 11
self.height = 11
self.dy = 0
self.dx = 0
self.inPlay = true
end
--[[
Expects an argument with a bounding box, be that a paddle or a brick,
and returns true if the bounding boxes of this and the argument overlap.
]]
function Powerup:collides(target)
if self.x > target.x + target.width or target.x > self.x + self.width then
return false
end
if self.y > target.y + target.height or target.y > self.y + self.height then
return false
end
return true
end
function Powerup.trigger(paddle)
if self.inPlay then
self.inPlay = false
end
end
function Powerup:update(dt)
self.x = self.x
self.y = self.y + self.dy * dt
if self.y <= 0 then
self.y = 0
self.dy = -self.dy
gSounds['wall-hit']:play()
end
end
function Powerup:render()
if self.inPlay then
love.graphics.draw('zucc.png', self.x, self.y)
end
end```
table.method(self) is equal to table:method(), both are given self as the first parameter, which means that if you are using the colon :, you do not need to declare self as a parameter.
If that doesn't solve your problem, could you be more detailed and tell us exactly which line is calling for the error?
EDIT:
the reason the error is being caused is because you did not declare the variable x and y as parameters. The error is saying that "you are trying to insert the index x of self the value x, but the variable X does not exist, that is, you are trying to insert nil into the variable"
you can solve this problem by declaring the parameters in the function:
Powerup:init(x, y)
and then call the function, giving the values x and y, example:
Powerup:init(3,5)
now self.x is 3, and self.y is 5

Expected table. got nil error?

In the following code
for k, smoke in pairs(self.smokes) do
smoke.time = smoke.time - dt
if smoke.time <= 0 then
table.remove( self.smokes, k )
end
end
It's telling me that self.smokes is a nil value, although later in the code I declare
function ent:Smoke()
table.insert( self.smokes, {time = 3, x = self.x, y = self.y} )
end
Anyone know my error? Thanks guys!
Because the function ent:Smoke is run later in the code.
Place it up at the top and it will work.
Perhaps you want this:
function ent:Smoke()
self.smokes = {time = 3, x = self.x, y = self.y}
end
And you would need to change the other code too:
if self.smokes then
self.smokes.time = self.smokes.time - dt
if self.smoke.time <= 0 then
self.smokes = nil
end
end
The function table.insert() is for inserting into array type tables.

Love2D Lua error: attempt to call field 'isDown' (a nil value)

This is my code in Love2D:
function love.load()
ninja = love.graphics.newImage("Ninja.png")
x = 0
y = 0
speed = 256
end
function love.update(dt)
if love.keyboard.isDown("right") then
ninja = love.graphics.newImage("NinjaRight.png")
x = x + (speed * dt)
end
if love.keyboard.isDown("left") then
ninja = love.graphics.newImage("NinjaLeft.png")
x = x - (speed * dt)
end
if love.keyboard.isDown("down") then
y = y + (speed * dt)
end
if love.keyboard.isDown("up") then
y = y - (speed * dt)
end
if love.joystick.isDown(joystick, 1, 2, 3, 4) then
a = 5
end
end
function love.draw()
love.graphics.draw(ninja, x, y)
end
I want to make the game to recognize a controller when connected.
But when I run the game, I receive the error:
attempt to call field 'isDown'(a nil value)
Where is the problem?
Since LÖVE 0.9.0 Joystick related isDown() function is moved to another namespace/table/You name ir or more "object" like structure. [1]
So, in Your code You should use it something like this:
--Get table of all connected Joysticks:
local joysticks = love.joystick.getJoysticks()
--Pick first one:
local joystick = joysticks[1]
if joystick:isDown(1, 2, 3, 4) then
a = 5
end
Where joystick is Your Joystick object. [2]
Be aware, love.keyboard.isDown() usage haven't changed yet. But, I guess, it's about to too. Sooner or later.
[1] https://love2d.org/wiki/Joystick:isDown
[2] https://love2d.org/wiki/love.joystick.getJoysticks

My Lua maze builder that is braiding

I am building a Lua script that generates a maze using a version of the Recursive Backtracker implemented with a stack rather than recursion. Presently the maze is coming out braided and I can't seem to figure out where in my logic this is happening. The function below takes in x and y as a starting point for generating the maze which is a 2d structure (table of tables):
local function buildMazeInternal(x,y,maze)
local stack = {}
local directions = {'North','East','South','West'}
table.insert(stack,{x=x,y=y})
while #stack > 0 do
local index = 1
local nextX = x
local nextY = y
local braid = false
for i = #directions, 2, -1 do -- backwards
local r = calc:Roll(1,i) -- select a random number between 1 and i
directions[i], directions[r] = directions[r], directions[i] -- swap the randomly selected item to position i
end
while index <= #directions and nextX == x and nextY == y do
if directions[index] == 'North' and y > 1 and not maze[y-1][x].Visited then
maze[y][x].North = true
maze[y-1][x].South = true
nextY = y-1
elseif directions[index] == 'East' and x < width and not maze[y][x+1].Visited then
maze[y][x].East = true
maze[y][x+1].West = true
nextX = x+1
elseif directions[index] == 'South' and y < height and not maze[y+1][x].Visited then
maze[y][x].South = true
maze[y+1][x].North = true
nextY = y+1
elseif directions[index] == 'West' and x > 1 and not maze[y][x-1].Visited then
maze[y][x].West = true
maze[y][x-1].East = true
nextX = x-1
else
index = index + 1
end
end
if nextX ~= x or nextY ~= y then
x = nextX
y = nextY
maze[y][x].Visited = true
table.insert(stack,{x=x,y=y})
else
x = stack[#stack].x
y = stack[#stack].y
table.remove(stack)
end
end
end
I know I'm overlooking something but I can't seem to nail it down. Note that the calc:Roll(1,100) method is a .net method in my app used to simulate rolling dice, in this case 1 * 100 sided die, it could be replaced with a call to math.Random(1,100) for use outside of my application.
I see at least one problem. When you go "want to go up", you check whether the "cell which is up" was visited, and if it is, you "skip" going up.
This does not seem to be correct IMHO. If you want to go up, but the cell which is "up" from the current cell was visited but has a "down" exit, you should still be able to go up (instead of skipping because it is visited).
The same applies to the other directions.
That's all I got.
I found the answer after posting on Reddit. I wasn't setting the initial cell to visited allowing it to be passed through twice. The correction was to add maze[y][x].Visited = true immediately before table.insert(stack,{x=x,y=y}).

Resources