Getting a 'nil' value when attaching an addEventListener method to a created Object

99 views Asked by At

I just started getting my feet wet with Corona and trying to work with OOP. This is just a simple Match Making Game to help me along with thinking like OOP. I have 2 classes, one class will be creating an instances of a Card (i will be making multiple objects of this type of Card Class) and the other is the MatchCardsManager Class - this creates the cards and applies the properties

The error I am getting is, after i have created the object "MatchCard" i tried to apply an "addEventListener" to the object. but when i do i receive an error of the following

     Support/Outlaw/Sandbox/5/MatchCardsManager.lua:53: 
attempt to call method 'addEventListener' (a nil value)
        stack traceback:

If i comment out the info on addEventListener, all objects are displayed accordingly to the constructor i created in MatchCard Class.

Below are my files - the error i am getting is in the MatchCardsManager class

mCard[i] = MatchCardsManager:displayPlacementCard(i, temp, x, y)
mCard[i]:addEventListener("touch", myTouch)

Any help or suggestions about fixing this or better approach would be greatly appreciated. Thank you.

The MatchCard Class will be just a simple constructor for now as this is not my issue

-- MatchCard Class
-- Meta Data
local sceneGroup = sceneGroup

local MatchCard = { }
local MatchCard_mt = { __index = MatchCard } -- metatable

------------------------------------------------
-- PRIVATE FUNCTION 
------------------------------------------------

------------------------------------------------
-- PUBLIC FUNCTION
------------------------------------------------
-- constructor
function MatchCard.new (id, animal, state, imageId, x, y)

    local newMCard = display.newRoundedRect( x, y, 59, 47, 5)
    newMCard.strokeWidth = 3
    newMCard:setFillColor( 0.5 )
    newMCard:setStrokeColor( 1, 0, 0 )
    newMCard.properties = {
        id = id or nil,
        animal = animal or nil,
        state = state or 0, 
        imageId = imageId,
    }

    return setmetatable ( newMCard, MatchCard_mt )

end

MatchCardsManager Class is there I plan to create an many instances of cards

-- require files
local MatchCard = require('MatchCard') --MatchCard

local sceneGroup = sceneGroup
local MatchCardsManager = {} -- originally we should use a displayGroup

-- TODO: insert group into scene

local animalPicsReference = { "dog", "dog", "cat", "cat", "pig", "pig" , "fish", "fish"} 

-- manager class properties
MatchCardsManager.totalCards = 8
MatchCardsManager.totalPairs = 4
MatchCardsManager.pairsFound = 0
MatchCardsManager.firstCardSelected = 0
MatchCardsManager.secondCardSelected = 0

-- lets create 6 MatchCardFiles
function MatchCardsManager:create()

    local animalPics = animalPicsReference
    local x = 108 - 85
    local y = 125
    print("do we go here never works")

    local mCard = {}

    for i=1, 4  
        do 
           x = x + 85 
           num = math.random(1, #animalPics)
           temp = animalPics[num]
           table.remove(animalPics, num) 
           mCard[i] = MatchCardsManager:displayPlacementCard(i, temp, x, y)
           mCard[i]:addEventListener("touch", myTouch)

    end

    x = 108 - 85
    y = 195 
    for j = 5, 8 do 
            x = x + 85          
           num = math.random(1, #animalPics)
           temp = animalPics[num]
           table.remove(animalPics, num) 
           mCard[j] = MatchCardsManager:displayPlacementCard(j, temp, x, y)
           print(type(mCard[j]))
           mCard[j]:addEventListener("touch", myTouch)
    end
    --mCards:addEventListener("touch", myTouch)
    return mCard
end

local function  myTouch( event )
    if event.phase == "began" then
            print( "You touched the object! "..event.target.imageId)
    end
end

function MatchCardsManager:displayPlacementCard(idx, animal, x, y)
    -- randomly place the cards in the object id

    local card = MatchCard.new(idx, animal, 0, animal, x, y)
    --card:show(x,y) -- displays card and that is it
    print("animal added is "..card.properties.imageId)
    return card
end

return MatchCardsManager
1

There are 1 answers

1
ryanpattison On

The problem is in the constructor. local newMCard = display.newRoundedRect(...) creates a display object, but the line: return setmetatable(newMCard, MatchCard_mt) overwrites the metatable that the display object had and so it no longer has access to display's __index metamethod that is used to find addEventListener.

To fix this, you need to look into how inheritance is added in Lua. See Inheritance Tutorial so you can inherit addEventListener. The solution will be something like: setmetatable(MatchCard, {__index=ShapeObject}) or =display.ShapeObject}---I can't be sure how Corona implements its classes.