Attempt to index local 'event' (a nil value) error

I’ve been following this tutorial as its the exact mechanic I am looking for, but I seem to be getting an event = nil value error. I can’t figure out why this is happening. 

I have 3 objects with listeners on them which go through the logical if statement to determine if its a 1st or 2nd tap, but the error comes when the whichTap function redirects. 

 castle = display.newRect(0,0,106,60) -- RED castle.anchorX = 0.0 castle.anchorY = 0.0 castle.x = 0 castle.y = display.contentHeight - 15 castle.name = "redCastle" castle:setFillColor(228/255,59/255,91/255) physics.addBody( castle, {isSensor = true} ) castle.touch = whichTap castle:addEventListener("touch") baseGroup:insert(castle) castle2 = display.newRect(0,0,106,60) castle2.anchorX = 0.0 castle2.anchorY = 0.0 castle2.x = castle.width castle2.y = display.contentHeight - 15 castle2.name = "greenCastle" castle2:setFillColor(170/255,220/255,84/255) --castle2.alpha = 0.1 physics.addBody( castle2, {isSensor = true} ) castle2.touch = whichTap castle2:addEventListener("touch") baseGroup:insert(castle2) castle3 = display.newRect(0,0,106,60) castle3.anchorX = 0.0 castle3.anchorY = 0.0 castle3.x = castle2.width+ 106 --212 castle3.y = display.contentHeight - 15 castle3.name = "blueCastle" castle3:setFillColor(103/255,211/255,248/255,248) physics.addBody( castle3, {isSensor = true} ) castle3.touch = whichTap castle3:addEventListener("touch") baseGroup:insert(castle3)

They direct to whichTap function 

function firstTapEventListener(event) firstX = event.target.x firstY = event.target.y firstName = event.target.name end function secondTapEventListener(event) secondX = event.target.x secondY = event.target.y secondName = event.target.name transition.to(secondName, {time = 1500, x = firstX, y = firstY}) transition.to(firstName, {time = 1500, x = secondX, y = secondY}) end function whichTap(event) if counter == 1 then firstTapEventListener() else secondTapEventListener() end end

pass ‘event’  to firstTapEvent and secondTapEvent

in the second code segment above :

line 18 firstTapEvent(event)

line 20 secondTapEvent(event)

shouldn’t it be:

object.touch = onObjectTouch object:addEventListener( "touch", object )

Hey @cyberparkstudios so that fixed the issue but I am now having another issue. The transition (swapping object1’ position with object2) isn’t firing.

@hasty: Im not sure, the event was firing but it seems I wasn’t passing in the event like cyberparkstudios mentioned, but my transition swap isn’t working, which is weird.

Maybe what I mentioned doesn’t matter. I’ve just seen it done that way so often…

Anyway, look carefullly at your transitions. You’re transitioning strings, not display objects.

I see. So how else would I be able to identify the actual display object and move it along. I tried using (baseGroup[firstName]) in the hop that it would find the display object for that name and move it, but it still didn’t work (its probably exactly the same as before). Ideally I would like to find out which castle (1,2, or 3) the players tapped, and then move them. 

dip,

hasty is correct about both things he mentions.

  1. your addEventListener(“touch”) needs a second field; that needs to be either a function handle or a table

  2. in the transition calls you have shown, you are using the .name field you assigned to each of the castles,which you have as a string, and that needs to be the object itself.  you can keep the .name field a string to help identify the unique castle for some other reason, but just not for the transition, which needs an object.  You really do not need to use that .name field to get done what you are trying to do.

If I could suggest (and keep in mind there are many ways to skin the cat),

  1. keep the .name field a string if you want, just don’t try to use that in the transition calls.

  2. eliminate the ‘firstTapEventListener’ and ‘secondTapEventListener’ functions.  Just handle everything in the one function ‘whichTap’

  3. create 2 handles at the top of your code:

local pick1

local pick2

then do the whichTap function like this :

function whichTap(self, event) if event.phase == "ended" then counter = counter + 1 if counter == 1 then pick1 = event.target else pick2 = event.target counter = 0 local firstX = pick1.x local firstY = pick1.y local secondX = pick2.x local secondY = pick2.y transition.to(pick2, {time = 1500, x = firstX, y = firstY}) transition.to(pick1, {time = 1500, x = secondX, y = secondY}) end end return true end

I added ‘return true’ at then end of that function, just in case when the castles are crossing over the top of each other and you tap the top one, the touch event will not pas thru down to the object under it.

also, here is how you might add the event listener to each object:

castle.touch = whichTap

castle:addEventListener(“touch”, castle)

castle2.touch = whichTap

castle2:addEventListener(“touch”, castle2)

castle3.touch = whichTap

castle3:addEventListener(“touch”, castle3)

Just suggestion, that I hope helps.  There are likely more efficient ways and certainly other ways to do the same thing, but this will work, for what it appears you are trying to do.

Good Luck.

Bob

Instead of using firstName = event.target.name, you could use firstObj = event.target.

Same for the second object. Then just transition firstObj and secondObj.

Another way, though less elegant, would be to loop through baseGroup and check the names:

for i = 1, baseGroup.numChildren do if baseGroup[i].name == firstName then -- transition elseif -- etc... end end

Thanks for the help guys, this forum has a great members. Both of your help was very helpful and I should be able to work with all the suggestions now.  

Cheers guys.

Guys sorry to keep coming back to this, Ive had a go at both suggestions but they don’t seem to work 

Both have upValue errors. For cyberparkstudios suggestion I get the up value for ‘pick1’ and ‘pick2’ event though I have forward declared them at the top of my code. 

@hasty, the firstObj and secondObj get up values errors too. 

I’ve add to CPSs example a little and tested, and it definitely works:

local pick1, pick2 local counter = 0 function whichTap(self, event) if event.phase == "ended" then counter = counter + 1 if counter == 1 then pick1 = event.target else pick2 = event.target counter = 0 local firstX = pick1.x local firstY = pick1.y local secondX = pick2.x local secondY = pick2.y transition.to(pick2, {time = 1500, x = firstX, y = firstY}) transition.to(pick1, {time = 1500, x = secondX, y = secondY}) end end return true end local x = display.newRect( 100, 160, 50, 50) x:setFillColor(1, 0, 0) local y = display.newRect( 220, 160, 50, 50) y:setFillColor(0, 0, 1) x.touch = whichTap y.touch = whichTap x:addEventListener("touch", x) y:addEventListener("touch", y)

I know I’ve gotten upvalue errors like this before despite having forward-declared, and endured much frustration over it, only for it to be something simple. Alas, I can’t recall any examples.

haha I know what you mean about them errors. Funny thing is I changed something with the firstObj and secondObj code above and, what didn’t work before, all of a sudden works perfectly now. Strange but oh well. I will try CPS’ code again too. Thanks again, learnt a lot there. 

pass ‘event’  to firstTapEvent and secondTapEvent

in the second code segment above :

line 18 firstTapEvent(event)

line 20 secondTapEvent(event)

shouldn’t it be:

object.touch = onObjectTouch object:addEventListener( "touch", object )

Hey @cyberparkstudios so that fixed the issue but I am now having another issue. The transition (swapping object1’ position with object2) isn’t firing.

@hasty: Im not sure, the event was firing but it seems I wasn’t passing in the event like cyberparkstudios mentioned, but my transition swap isn’t working, which is weird.

Maybe what I mentioned doesn’t matter. I’ve just seen it done that way so often…

Anyway, look carefullly at your transitions. You’re transitioning strings, not display objects.

I see. So how else would I be able to identify the actual display object and move it along. I tried using (baseGroup[firstName]) in the hop that it would find the display object for that name and move it, but it still didn’t work (its probably exactly the same as before). Ideally I would like to find out which castle (1,2, or 3) the players tapped, and then move them. 

dip,

hasty is correct about both things he mentions.

  1. your addEventListener(“touch”) needs a second field; that needs to be either a function handle or a table

  2. in the transition calls you have shown, you are using the .name field you assigned to each of the castles,which you have as a string, and that needs to be the object itself.  you can keep the .name field a string to help identify the unique castle for some other reason, but just not for the transition, which needs an object.  You really do not need to use that .name field to get done what you are trying to do.

If I could suggest (and keep in mind there are many ways to skin the cat),

  1. keep the .name field a string if you want, just don’t try to use that in the transition calls.

  2. eliminate the ‘firstTapEventListener’ and ‘secondTapEventListener’ functions.  Just handle everything in the one function ‘whichTap’

  3. create 2 handles at the top of your code:

local pick1

local pick2

then do the whichTap function like this :

function whichTap(self, event) if event.phase == "ended" then counter = counter + 1 if counter == 1 then pick1 = event.target else pick2 = event.target counter = 0 local firstX = pick1.x local firstY = pick1.y local secondX = pick2.x local secondY = pick2.y transition.to(pick2, {time = 1500, x = firstX, y = firstY}) transition.to(pick1, {time = 1500, x = secondX, y = secondY}) end end return true end

I added ‘return true’ at then end of that function, just in case when the castles are crossing over the top of each other and you tap the top one, the touch event will not pas thru down to the object under it.

also, here is how you might add the event listener to each object:

castle.touch = whichTap

castle:addEventListener(“touch”, castle)

castle2.touch = whichTap

castle2:addEventListener(“touch”, castle2)

castle3.touch = whichTap

castle3:addEventListener(“touch”, castle3)

Just suggestion, that I hope helps.  There are likely more efficient ways and certainly other ways to do the same thing, but this will work, for what it appears you are trying to do.

Good Luck.

Bob

Instead of using firstName = event.target.name, you could use firstObj = event.target.

Same for the second object. Then just transition firstObj and secondObj.

Another way, though less elegant, would be to loop through baseGroup and check the names:

for i = 1, baseGroup.numChildren do if baseGroup[i].name == firstName then -- transition elseif -- etc... end end

Thanks for the help guys, this forum has a great members. Both of your help was very helpful and I should be able to work with all the suggestions now.  

Cheers guys.