attempt to index local 'self' (a nil value)

The problem is in the function name "bullet Collision) I cannot remove the bullet after collision. If the line self:removeSelf() is removed then the code runs. The error shows just after the bullet collide with the enemy.

–Physics world creation

local physics = require (“physics”)

physics.start()

physics.setGravity(1,1)

–screen

local width=display.contentWidth

local height=display.contentHeight

–game characters

local enemy

local hero

local bullet

local background

local score

local counter

–backGround

background= display.newImage(“night_sky.png”,width/2,height/2,true)

–collision filters

local heroCollisionFilter = { categoryBits=1, maskBits=2 }

local enemyCollisionFilter = { categoryBits=2, maskBits=7 }

local bulletCollisionFilter = { categoryBits=4, maskBits=2 }

–hero’s death

function heroCollision(event)

end

–bullet heat

function bulletCollision(event, self)

print(“bullet collided”)

if event.other.name == “enemy” then

self:removeSelf()

event.other:removeSelf()

event.other= nil

end

end

–fire

function fireBullet(event)

bullet=display.newImage(“bullet.png”,hero.x,hero.y )

physics.addBody(bullet,{filter=bulletCollisionFilter})

bullet.name=bullet

local gx = event.x-bullet.x

local gy = event.y-bullet.y

physics.setGravity(gx/10,gy/10)

bullet.collision= bulletCollision

bullet:addEventListener(“collision”, bulletCollision)

end

function addEnemy()

    local enemy = display.newImage(“ball.png”,40,50)

physics.addBody(enemy,{filter=enemyCollisionFilter})

enemy.gravityScale=0

enemy:addEventListener(“tap”,fireBullet)

enemy.name= “enemy”

end

addEnemy()

background:addEventListener(“tap”, fireBullet)

hero = display.newImage(“pearl1.png”,width/2,height/2,true)

Hey nirmalbuet,

first of all, you should put your code in code-tags, so it’s more readable.

It seems, like you are missunderstanding the usage of “self”.

To use “self” you need to fullfill two conditions:

  1. you need a table which contains a field with the key of the event ( “collsion” in your case ) and that point to the function that should be called ( in your case “bulletCollision” )

  2. the called function must be aatached to the table using colons ( bullet:collision(event) ) or needs “self” as it’s first parameter ( bulletCollision(self, event) )

Let’s apply this to a specific part of your code:

--bullet heat function bulletCollision(self, event) print("bullet collided") if event.other.name == "bullet" then timer.performWithDelay(10, function() display.remove(self) display.remove(event.other) end) end end --fire function fireBullet(event) bullet = display.newImage("bullet.png",hero.x,hero.y ) physics.addBody(bullet,{filter = bulletCollisionFilter}) bullet.name = "bullet" bullet.collision = bulletCollision bullet:addEventListener("collision", bullet) local gx = event.x - bullet.x local gy = event.y - bullet.y physics.setGravity(gx/10,gy/10) end

With this, the collision wth the bullet should work.

But I wonder, if you are using a single local variable, that hold the bullet, why whould you even want to use the “self” parameter (which is used for a more object oriented use of lua) ?

Anyways, I also added a delay to the removal of the colliding objects, as you can’t delete physic bodys emideatly after a collision happend. You should check out some guides concerning collision: https://docs.coronalabs.com/daily/guide/physics/collisionDetection/index.html

Hope that helps you dive deeper into Corona :slight_smile:

Greetings

Torben

Hey nirmalbuet,

first of all, you should put your code in code-tags, so it’s more readable.

It seems, like you are missunderstanding the usage of “self”.

To use “self” you need to fullfill two conditions:

  1. you need a table which contains a field with the key of the event ( “collsion” in your case ) and that point to the function that should be called ( in your case “bulletCollision” )

  2. the called function must be aatached to the table using colons ( bullet:collision(event) ) or needs “self” as it’s first parameter ( bulletCollision(self, event) )

Let’s apply this to a specific part of your code:

--bullet heat function bulletCollision(self, event) print("bullet collided") if event.other.name == "bullet" then timer.performWithDelay(10, function() display.remove(self) display.remove(event.other) end) end end --fire function fireBullet(event) bullet = display.newImage("bullet.png",hero.x,hero.y ) physics.addBody(bullet,{filter = bulletCollisionFilter}) bullet.name = "bullet" bullet.collision = bulletCollision bullet:addEventListener("collision", bullet) local gx = event.x - bullet.x local gy = event.y - bullet.y physics.setGravity(gx/10,gy/10) end

With this, the collision wth the bullet should work.

But I wonder, if you are using a single local variable, that hold the bullet, why whould you even want to use the “self” parameter (which is used for a more object oriented use of lua) ?

Anyways, I also added a delay to the removal of the colliding objects, as you can’t delete physic bodys emideatly after a collision happend. You should check out some guides concerning collision: https://docs.coronalabs.com/daily/guide/physics/collisionDetection/index.html

Hope that helps you dive deeper into Corona :slight_smile:

Greetings

Torben