Add event listener error

I am creating a game and going from the start screen into the game is no problem but when I go from restart into the game I get this error :

ERROR: Runtime error C:\Users\user\Documents\Corona Projects\app\game.lua:92: attempt to call method 'addEventListener' (a nil value)

This is my code :

 player = display.newImage("player.png") player.x = 100 player.y = 300 player.myName = "player" physics.addBody(player, "static", {density=.1, bounce=0.2, friction=.2, radius=12}) function player:collision(event) if event.phase == "began" then transition.cancel() composer.gotoScene("restart", options) end end function scene:show(event) local sceneGroup = self.view local phase = event.phase if ( phase == "will" ) then player:addEventListener("collision") Runtime:addEventListener("touch", onTouch) elseif ( phase == "did" ) then end end function scene:hide(event) local sceneGroup = self.view local phase = event.phase if ( phase == "will" ) then display.remove( player ) display.remove( ball ) composer.removeScene( "start" ) player:removeEventListener("collision") Runtime:removeEventListener("touch", onTouch) elseif ( phase == "did" ) then print("hide removing objects") end end

This is where the error is :

player:addEventListener("collision")

I tried putting the player image in the create scene but the same thing happened . I made sure my image has the proper name . Please help .

This is because you removed the object in phase == will when the screen disappears. And since you created the player in scene:create(), it will only be displayed once. The error is saying that it is trying to add an eventListener to an object that does not exist. 

EDIT: That was wrong, you need to have the player in scene:create().

Read this and it will help you fix it:

https://docs.coronalabs.com/guide/system/composer/index.html

No I have the player outside of create() . 

Still, this explains why your error is occurring.

I put the code into did and it’s still not working .

function scene:show(event) local sceneGroup = self.view local phase = event.phase if ( phase == "will" ) then elseif ( phase == "did" ) then player:addEventListener("collision") Runtime:addEventListener("touch", onTouch) end end function scene:hide(event) local sceneGroup = self.view local phase = event.phase if ( phase == "will" ) then elseif ( phase == "did" ) then print("hide removing objects") composer.removeScene( "start" ) player:removeEventListener("collision") Runtime:removeEventListener("touch", onTouch) display.remove( ball ) display.remove( player ) end end

Did you at least look at the tutorial?

Yes I read it about 5 times and I don’t see what’s wrong

You should move the player code back into scene:create(). 

This was in the tutorial:

"The scene’s view is initialized and, if the view does not already exist, a create event is dispatched to the scene’s scene:create() function. At this point, the scene still resides “off screen,” so this is an opportune time to create user interface objects and other display objects needed for the scene, including buttons, text, graphics, and other objects that should show when the scene comes on screen."

Are you going to be needing the player for multiple levels? If you are, you should create a module that contains your player and its corresponding functions:

--player.lua local M = {} function M:new() --make character here function player:collision() --handles collision end function player:finalize() --Occurs when player is no longer needed (removes listeners) end end return M --scene.lua local player = require "player" player:new() --creates the player and attaches all of its listeners, it's that simple!

If you are not, then don’t do this, it is just extra work. However, if you are, consider this method, and if you want I can help you implement it.

This is what I get when I put the player code in the create scene :

game.lua:67: attempt to index local 'player' (a nil value)

This is my code :

local ball local player -- background function scene:create(event) local screenGroup = self.view local background = display.newImageRect("terrain.jpg",display.contentWidth,display.contentHeight) background.x = display.contentCenterX background.y = display.contentCenterY screenGroup:insert(background) player = display.newImage("player.png") player.x = 100 player.y = 300 player.myName = "player" physics.addBody(player, "static", {density=.1, bounce=0.2, friction=.2, radius=12}) screenGroup:insert(background) ball = display.newImage("ball1.png") ball.x = 400 ball.y = 160 physics.addBody(ball, "dynamic") ball.myName = "ball" screenGroup:insert(background) end

function player:collision(event) if event.phase == "began" then transition.cancel() composer.gotoScene("restart", options) end end

You need to define player:collision after player has been created within the scene:create function.

Otherwise at the point player:collision is defined, player is still nil. Remember, code runs top to bottom but code inside functions will not run until that function is called. Scene:create is not run until the very end of the file, after you try to define player:function.

An alternative is to have a local function called playerCollision, defined above scene:create, that is then assigned to player.

[lua]

player:addEventListener(“collision”,playerCollision)

[/lua]

So change onCollision to player collision or just write a separate function ?

Personally I would have a separate local playerCollision function. It’s easier to find and debug than something buried in scene:create.

I put this

local function playerCollision( event ) if event.phase == "began" then player = display.newImage("player.png") player.x = 100 player.y = 300 player.myName = "player" physics.addBody(player, "static", {density=.1, bounce=0.2, friction=.2, radius=12}) end end function scene:create(event) local screenGroup = self.view local background = display.newImageRect("terrain.jpg",display.contentWidth,display.contentHeight) background.x = display.contentCenterX background.y = display.contentCenterY screenGroup:insert(background) ball = display.newImage("ball1.png") ball.x = 400 ball.y = 160 physics.addBody(ball, "dynamic") ball.myName = "ball" screenGroup:insert(background) end

and now I’m getting this error :

C:\Users\user\Documents\Corona Projects\app\game.lua:74: attempt to index local 'player' (a nil value)

line 74 :

function player:collision(event) -- line 74 if event.phase == "began" then transition.cancel() composer.gotoScene("restart", options) end end

No. I said to create your player as normal within scene:create. After that, either add the player:collision function within scene:create now that player is in scope, or use addEventListener to add a listener for playerCollision, which must be defined above scene:create for that to be in scope.

This is a good example of just trying random things until something works rather than understanding what you’re doing and why. If you think it through logically, why would you put the code to create the player inside its own collision function?

I just did what you told me to do and still got an error :

local function playerCollision( event ) if event.phase == "began" then end end function scene:create(event) local screenGroup = self.view local background = display.newImageRect("terrain.jpg",display.contentWidth,display.contentHeight) background.x = display.contentCenterX background.y = display.contentCenterY screenGroup:insert(background) ball = display.newImage("ball1.png") ball.x = 400 ball.y = 160 physics.addBody(ball, "dynamic") ball.myName = "ball" screenGroup:insert(ball) player = display.newImage("player.png") player.x = 100 player.y = 300 player.myName = "player" physics.addBody(player, "static", {density=.1, bounce=0.2, friction=.2, radius=12}) screenGroup:insert(player) function player:collision(event) if event.phase == "began" then transition.cancel() composer.gotoScene("restart", options) end end local function loopObject() local objectDown= function() transition.to(player, { time=600, y=20, onComplete=loopObject }) end transition.to(player, { time=600, y=300, onComplete=objectDown }) end loopObject() end

error :

game.lua:93: attempt to call method 'addEventListener' (a nil value)

The start screen goes into the game but then that problem shows up .

Where are you calling addEventListener?

Btw, you don’t need playerCollision and player:collision. Choose one or the other.