Attempted to index "self" a nil value - lua

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

Related

Error ball.lua:21: attempt to call global 'checkcollision' (a nil value)

Having this problem with my code and i don't get it
basically trying to make a small game as an excercise, but failing when trying the ecollision part
from my beginners knowledge, there is a problem in line 21 (if checkcollision()) inside the "Ball" file, but don't know what thee problem is
This is my "Ball" code
Ball = {}
function Ball:load()
self.x = love.graphics.getWidth() / 2
self.y = love.graphics.getHeight() / 2
self.width = 20
self.height = 20
self.speed = 200
self.xvel = -self.speed
self.yvel = 0
end
function Ball:update(dt)
self:move(dt)
self:collide()
end
function Ball:collide()
if checkcollision(self, Player) then
self.xvel = self.speed
local middleBall = self.y + self.height / 2
local middlePlayer = Player.y + Player.height / 2
local CollisionPosition = middleBall - middlePlayer
self.yvel = CollisionPosition * 5
end
end
function Ball:move(dt)
self.x = self.x + self.xvel * dt
self.y = self.y + self.yvel * dt
end
function Ball:draw()
love.graphics.rectangle("fill",self.x, self.y, self.width, self.height)
end
This is my "main" code
require("player")
require("ball")
function love.load()
Player:load()
Ball:load()
end
function love.update(dt)
Player:update(dt)
Ball:update(dt)
end
function love.draw()
Player:draw()
Ball:draw()
end
function checkcollision(a, b)
if a.x + a.width > b.x and a.x < b.x + b.width and a.y + a.height > b.y and a.y < b.height then
return true
else
return false
end
end
My "player" code
Player = {}
function Player:load()
self.x = 50
self.y = love.graphics.getHeight() / 2
self.width = 25
self.height = 100
self.speed = 500
end
function Player:update(dt)
self:move(dt)
self:checkbounderies()
end
function Player:move(dt)
if love.keyboard.isDown("w") then
self.y = self.y - self.speed * dt
elseif love.keyboard.isDown("s") then
self.y = self.y + self.speed * dt
end
end
function Player:checkbounderies()
if self.y < 0 then
self.y = 0
elseif self.y + self.height > love.graphics.getHeight() then
self.y = love.graphics.getHeight() - self.height
end
end
function Player:draw()
love.graphics.rectangle("fill", self.x, self.y, self.width, self.height)
end
can someone point me to the right direction
You require Ball code which uses checkcollision function as upvalue before defining checkcollision function.
Basically you need to define checkcollision before using it anywhere; just reorder your imports.
But to solve it the right way, it would be better to move the checkcollision function to a separate file:
-- checkcollision.lua
local function checkcollision(a, b) ....... end
return checkcollision
and then require it in any file you want:
-- Ball.lua
local checkcollision = require "checkcollision"
function Ball:collide()
if checkcollision(self, Player) then
.......

Collision Detection in love2d(lua)

I am doing a game development course by cs50 where Colton Ogden teaches love2d which is in lua. I am facing a problem in collision detection. The below code/logic works fine when the object is not rotating example love.graphics.draw(texture, x, y, r).
Here x and y is some value and r(rotation is 0). Value of x and y keeps on changing.
function Projectile: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
But the above code doesn't work for target which is rotating i.e., r has some value which keeps on changing.
Below is how i am rotating an object.
function Meteor:init(speed)
self.r = math.random(-1, 1)
end
function Meteor:update(dt)
if self.r > 0 then
self.r = self.r + math.pi/9 * dt
elseif self.r < 0 then
self.r = self.r - math.pi/9 * dt
else
self.r = self.r
end
if self.y < VIRTUAL_HEIGHT + 110 then
self.y = self.y + self.speed * dt
else
self.remove = true
end
end
function Meteor:render()
love.graphics.drawLayer(self.meteor, self.type, self.x, self.y, self.r)
end
Sometimes it is easier and sufficient to just approximate an object's collision. In LÖVE you can specify the texture offset in love.graphics.draw(). Let the texture rotate at its center and see if an approximation works.
If you really need rectangles, which are not axis aligned, you may want to use a collision library. HardonCollider works perfect.
If you plan on adding physics too, then the LÖVE physics module makes more sense.
As #Luke100000 wrote LÖVE has already a collision detection in love.physics implemented.
Read and try: https://love2d.org/wiki/Tutorial:PhysicsCollisionCallbacks
For a zero gravity world i use for example...
function love.load()
local meter=4.5
love.physics.setMeter(meter)
ZeroGravity=love.physics.newWorld(0,0,true)
ZeroGravity:setCallbacks(Hit,Release,preSolve,postSolve) -- <Collision Callbacks>
end
And for example the "Hit" callback function...
-- <Collision Callback Functions>
Hit=function(a,b)
a:getBody():setUserData(os.date('%H:%M:%S'))
b:getBody():setUserData(os.date('%H:%M:%S'))
a:getUserData():emit(256)
b:getUserData():emit(256)
return true
end
The particlesystem that emitting 256 parts at "Hit" is assigned to the fixture in userdata of an physics body at creation...
function addAsteroid(x,y,r,kind)
local body=love.physics.newBody(ZeroGravity,x,y,kind)
local shape=love.physics.newCircleShape(r)
local fixture=love.physics.newFixture(body,shape,.01)
fixture:setUserData(psystem:clone()) -- Particlesystem for emitting
fixture:setDensity(1)
fixture:setFriction(1)
fixture:setRestitution(1)
--fixture:setFilterData(1,1,-1)
fixture:getUserData():start()
return body
end
A particle system can be very complex but it is worth for learning it.
Here i give you an example of mine that works with quads...
-- planets.lua
fields=1
quads={love.graphics.newImage("planets.png")
}
local assets={x=0,y=0,size=.1,time=-1,
[1]=love.graphics.newQuad(138,33,300,300,quads[1]:getDimensions()),
[2]=love.graphics.newQuad(505,37,300,300,quads[1]:getDimensions()),
[3]=love.graphics.newQuad(871,21,300,300,quads[1]:getDimensions()),
[4]=love.graphics.newQuad(1238,22,300,300,quads[1]:getDimensions()),
[5]=love.graphics.newQuad(1606,15,300,300,quads[1]:getDimensions()),
[6]=love.graphics.newQuad(1974,11,300,300,quads[1]:getDimensions()),
[7]=love.graphics.newQuad(1976,349,300,300,quads[1]:getDimensions()),
[8]=love.graphics.newQuad(136,382,300,300,quads[1]:getDimensions()),
[9]=love.graphics.newQuad(504,379,300,300,quads[1]:getDimensions()),
[10]=love.graphics.newQuad(871,366,300,300,quads[1]:getDimensions()),
[11]=love.graphics.newQuad(1236,362,300,300,quads[1]:getDimensions()),
[12]=love.graphics.newQuad(19,724,300,300,quads[1]:getDimensions()),
[13]=love.graphics.newQuad(1047,698,300,300,quads[1]:getDimensions()),
[14]=love.graphics.newQuad(1376,687,300,300,quads[1]:getDimensions()),
[15]=love.graphics.newQuad(1721,686,300,300,quads[1]:getDimensions()),
[16]=love.graphics.newQuad(2042,684,300,300,quads[1]:getDimensions()),
[17]=love.graphics.newQuad(347,704,660,300,quads[1]:getDimensions())
}
pquads={x=0,y=0,size=1,time=-1}
for i=12,12 do table.insert(pquads,assets[i]) end -- recall
assets=empty
psystem=love.graphics.newParticleSystem(quads[1],72)
psystem:setBufferSize(4096)
psystem:setLinearAcceleration(-150,-150,150,150) -- Random movement in all directions.
psystem:setEmissionArea('ellipse',145,145,math.rad(math.random(360)),false)
psystem:setQuads(pquads)
psystem:setSpread(75)
--[[psystem:setColors({love.math.random(),
love.math.random(),
love.math.random(),
0.3},{love.math.random(),
love.math.random(),
love.math.random(),
0.6},{love.math.random(),
love.math.random(),
love.math.random(),
0.3})]]--
--psystem:setColors({1,0,0,1},{0,0,1,1},{1,0,0,1})
--psystem:setColors({0,0,1,1},{1,1,1,1},{1,1,0,1},{1,0,0,1})
psystem:setSizes(math.random()*.05,0)
--psystem:setSizes(.1,.2,.3,.4,.3,.2,.1)
psystem:setSizeVariation(0)
psystem:setEmitterLifetime(pquads.time)
psystem:setParticleLifetime(pquads.size*11)
psystem:setEmissionRate(pquads.size*.11)
psystem:setInsertMode('top')
-- psystem:setPosition(-150,-150)
The assets i am using i get from...
https://opengameart.org/art-search?keys=planets

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

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

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.

attempt to index A nil Value in LUA for CS50 in a PONG game

I've trying to run this program, well, the main works just fine but when I try to run the reset function It says that Ball.lua:14: attempt to index global 'self'(a nil value)
I'm really new to LUA so I'm not sure how to fix it.
Thanks in advance.
Ball = Class{}
function Ball:init(x, y, width, height)
self.x = x
self.y = y
self.width = width
self.height = height
self.dx = math.random(2) == 1 and -100 or 100
self.dy = math.random(-50, 50)
end
function Ball.reset()
--start ball's position in middle
self.x = VIRTUAL_WIDTH / 2 - 2
self.y = VIRTUAL_HEIGHT / 2 - 2
self.dx = math.random(2) == 1 and -100 or 100
self.dy = math.random(-50, 50) * 1.5
end
function Ball:update(dt)
self.x = self.x + self.dx * dt
self.y = self.y + self.dy * dt
end
function Ball:render()
love.graphics.rectangle('fill', self.x, self.y, self.width, self.height)
end

Resources