addEventListener: listener cannot be nil: nil

Hi All

I thought I was doing really good!  LOL.  But I am stopped by errors.  I am working on Chapter 5 — Converting the Game to Composer.

I just added the code per the tutorial:

physics.start()
Runtime:addEventListener( “collision”, onCollision )
gameLoopTimer = timer.performWithDelay( 500, gameLoop, 0 )

into the game.lua file.  The tutorial says it should look like this:

function scene:show( event )

local sceneGroup = self.view
local phase = event.phase

if ( phase == “will” ) then
– Code here runs when the scene is still off screen (but is about to come on screen)

elseif ( phase == “did” ) then
– Code here runs when the scene is entirely on screen
physics.start()
Runtime:addEventListener( “collision”, onCollision )
gameLoopTimer = timer.performWithDelay( 500, gameLoop, 0 )
end
end

As soon as I add those 3 lines of code, the game crashes when I click the Play button.  Here is the error(s)

11:27:46.008  ERROR: Runtime error
11:27:46.008  addEventListener: listener cannot be nil: nil
11:27:46.008  stack traceback:
11:27:46.008      [C]: in function ‘error’
11:27:46.008      ?: in function ‘getOrCreateTable’
11:27:46.008      ?: in function ‘addEventListener’
11:27:46.008      ?: in function ‘addEventListener’
11:27:46.008      ?: in function ‘addEventListener’
11:27:46.008      C:\Users\Andy\Documents\Corona Projects\StarExplorer\menu.lua:76: in function <C:\Users\Andy\Documents\Corona Projects\StarExplorer\menu.lua:65>
11:27:46.008      ?: in function ‘dispatchEvent’
11:27:46.008      ?: in function <?:865>
11:27:46.008      (tail call): ?
11:27:46.008      ?: in function <?:504>
11:27:46.008      ?: in function <?:169>
 

the strange thing about it is, those three lines of code are NOT in the source code file!

Any ideas?

Thanks

Have you created onCollision function???.. if not, then that is the cause of your error

Hi

I have one.  Here it is:

local function onCollision( event )

    if ( event.phase == “began” ) then

        local obj1 = event.object1
        local obj2 = event.object2

        if ( ( obj1.myName == “laser” and obj2.myName == “asteroid” ) or
             ( obj1.myName == “asteroid” and obj2.myName == “laser” ) )
        then
            – Remove both the laser and asteroid
            display.remove( obj1 )
            display.remove( obj2 )

            for i = #asteroidsTable, 1, -1 do
                if ( asteroidsTable[i] == obj1 or asteroidsTable[i] == obj2 ) then
                    table.remove( asteroidsTable, i )
                    break
                end
            end

Is it above scene:show() in the listing?

Yes…

function scene:show( event )

local sceneGroup = self.view
local phase = event.phase

 

if ( phase == “will” ) then
– Code here runs when the scene is still off screen (but is about to come on screen)

elseif ( phase == “did” ) then
– Code here runs when the scene is entirely on screen
physics.start()
Runtime:addEventListener( “collision”, onCollision )
gameLoopTimer = timer.performWithDelay( 500, gameLoop, 0 )
end
end

are you sure that’s actually where your error lies? the message would tend to indicate it’s a problem in menu.lua, nothing to do with game.lua.

Assuming that’s not the case, it really does have to be an issue of scope as previously mentioned. The onCollision function must exist prior to adding the event listener, or at least a forward reference to it.

e.g.

you can either do:

local function onCollision(event) ... end Runtime:addEventListener( "collision", onCollision )

or you can do

local onCollision Runtime:addEventListener("collision", onCollision) function onCollision(event) ... end

First things first. @beyond2K it is super helpful when  you post code for it to remain formatted. The forums love to munge your code. There are two ways to properly post code. The first is to type in

[lua]

then paste your code in then type in:

[/lua]

Or simply click the blue <> button in the bar with Bold, Italics etc. and paste your code into the window that pops up. Then your code will display like @Jwiow’s. It’s really important that you do this.

Next, it would be helpful to see your collision function also.  But let me provide a little explainer on why the order of code in your file matters.

Compilers are known as either “one-pass” or “two-pass” compilers. Languages like C are two-pass. The first pass it finds all variable, object and functions and assigns memory addresses to all of them. At that point the compiler knows about everything in the file. In the second pass, it compiles all of the other things, +, -, for loops, if statements into machine code and substitutes the know memory addresses for all of the variables. This lets you have the flexibility of not really paying attention to the order of things. It also lets you group code in a more logical manner. There are also times where you run into cart-horse problems where you need to know about the cart before you know about the horse, but you can’t code the cart until the horse exists.

Lua is a one-pass interpreter. It starts at the top and goes to the bottom. When it hits a variable or function name and its a point where the variable can be defined:

local function doSomething() local someNumber = 10

It will assign the memory address at that point. If it’s something that’s being used and it’s not hit a piece of code that creates it, Lua will assign nil to the address.

local function doSomething() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doSomethingElse()&nbsp;&nbsp; --\<-------- This is "nil" right now and will generate an error when it tries to run end local function doSomethingElse() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print("Hi!") end doSomething()

You have to declare it before you use it. To fix this block of code:

local function doSomethingElse() print("Hi!") end local function doSomething() doSomethingElse() --\<-------- This is "nil" right now and will generate an error when it tries to run end doSomething()

Even though this may not feel like the right order to do things in, you have to do that. If you get stuck and have a cart/horse problem, then you might want to do:

local doSomethingElse --\<-------- pre declare the function (also known as "forward declare") local function doSomething() doSomethingElse() --\<-------- This is "nil" right now and will generate an error when it tries to run end doSomethingElse = function() print("Hi!") end doSomething()

This way of declaring a function is known as an Anonymous function.

Have you created onCollision function???.. if not, then that is the cause of your error

Hi

I have one.  Here it is:

local function onCollision( event )

    if ( event.phase == “began” ) then

        local obj1 = event.object1
        local obj2 = event.object2

        if ( ( obj1.myName == “laser” and obj2.myName == “asteroid” ) or
             ( obj1.myName == “asteroid” and obj2.myName == “laser” ) )
        then
            – Remove both the laser and asteroid
            display.remove( obj1 )
            display.remove( obj2 )

            for i = #asteroidsTable, 1, -1 do
                if ( asteroidsTable[i] == obj1 or asteroidsTable[i] == obj2 ) then
                    table.remove( asteroidsTable, i )
                    break
                end
            end

Is it above scene:show() in the listing?

Yes…

function scene:show( event )

local sceneGroup = self.view
local phase = event.phase

 

if ( phase == “will” ) then
– Code here runs when the scene is still off screen (but is about to come on screen)

elseif ( phase == “did” ) then
– Code here runs when the scene is entirely on screen
physics.start()
Runtime:addEventListener( “collision”, onCollision )
gameLoopTimer = timer.performWithDelay( 500, gameLoop, 0 )
end
end

are you sure that’s actually where your error lies? the message would tend to indicate it’s a problem in menu.lua, nothing to do with game.lua.

Assuming that’s not the case, it really does have to be an issue of scope as previously mentioned. The onCollision function must exist prior to adding the event listener, or at least a forward reference to it.

e.g.

you can either do:

local function onCollision(event) ... end Runtime:addEventListener( "collision", onCollision )

or you can do

local onCollision Runtime:addEventListener("collision", onCollision) function onCollision(event) ... end

First things first. @beyond2K it is super helpful when  you post code for it to remain formatted. The forums love to munge your code. There are two ways to properly post code. The first is to type in

[lua]

then paste your code in then type in:

[/lua]

Or simply click the blue <> button in the bar with Bold, Italics etc. and paste your code into the window that pops up. Then your code will display like @Jwiow’s. It’s really important that you do this.

Next, it would be helpful to see your collision function also.  But let me provide a little explainer on why the order of code in your file matters.

Compilers are known as either “one-pass” or “two-pass” compilers. Languages like C are two-pass. The first pass it finds all variable, object and functions and assigns memory addresses to all of them. At that point the compiler knows about everything in the file. In the second pass, it compiles all of the other things, +, -, for loops, if statements into machine code and substitutes the know memory addresses for all of the variables. This lets you have the flexibility of not really paying attention to the order of things. It also lets you group code in a more logical manner. There are also times where you run into cart-horse problems where you need to know about the cart before you know about the horse, but you can’t code the cart until the horse exists.

Lua is a one-pass interpreter. It starts at the top and goes to the bottom. When it hits a variable or function name and its a point where the variable can be defined:

local function doSomething() local someNumber = 10

It will assign the memory address at that point. If it’s something that’s being used and it’s not hit a piece of code that creates it, Lua will assign nil to the address.

local function doSomething() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doSomethingElse()&nbsp;&nbsp; --\<-------- This is "nil" right now and will generate an error when it tries to run end local function doSomethingElse() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print("Hi!") end doSomething()

You have to declare it before you use it. To fix this block of code:

local function doSomethingElse() print("Hi!") end local function doSomething() doSomethingElse() --\<-------- This is "nil" right now and will generate an error when it tries to run end doSomething()

Even though this may not feel like the right order to do things in, you have to do that. If you get stuck and have a cart/horse problem, then you might want to do:

local doSomethingElse --\<-------- pre declare the function (also known as "forward declare") local function doSomething() doSomethingElse() --\<-------- This is "nil" right now and will generate an error when it tries to run end doSomethingElse = function() print("Hi!") end doSomething()

This way of declaring a function is known as an Anonymous function.