Getter/setters and listeners using classes

I’ve read a lot of content about using classes in Lua, and I’m still having some trouble to mak it 100% work.

After a lot of research, these two pages (awesome pages) lead me to some code:

http://www.coronalabs.com/blog/2011/09/29/tutorial-modular-classes-in-corona/
http://jessewarden.com/2011/10/lua-classes-and-packages-in-corona.html

I’ve made a class to represent a single block (like a gems swapping game), but I can’t understand some things. Here is the code block:

[lua]module(…, package.seeall)


– block.lua

– Block object to use as pieces


local block = {}

function block.new( blockType, xPos, yPos ) – constructor

local block = display.newGroup()

local blockImage = display.newImage(“0” … blockType … “.png”)
blockImage:setReferencePoint(display.TopLeftReferencePoint)
block:insert(blockImage)

block.x = xPos;
block.y = yPos;

return block
end
function block:toString()
print( "x = " … block.x … ", y = " … block.y);
end

function block:touch(event)
print(“touch”)
if event.phase == “began” then
self:toString()
return true
end
end

return block[/lua]

and the code of game testing it:

[lua]local block = require( “block” )

local background = display.newRect( 0, 0, 480, 800 ); background:setFillColor(0, 50, 0);
local blocks = {}

– makes a 7x10 matrix and fill with boxes
for i = 1, 7 do
blocks[i] = {}
for j = 1, 10 do
blocks[i][j] = block.new( math.random( 1, 6 ), (i-1)*64+16, (j-1)*64+84 )
blocks[i][j]:addEventListener(“touch”, block)
end
end[/lua]

After the execution, I have a functional matrix filled with boxes. The listeners seems to work (it prints “touch”), but the function toString() did not return the x and y values. Its trows an error or in some modifications nil.

Can anyone give me a tip?
Thanks in advance!

[import]uid: 54349 topic_id: 30372 reply_id: 330372[/import]

I think your event listener should be:

blocks[i][j]:addEventListener(“touch”, blocks[i][j])

This block:

function block:touch(event)  
 print("touch")  
 if event.phase == "began" then  
 self:toString()  
 return true  
 end  
end  

probably should be:

function block:touch(event)  
 print("touch")  
 if event.phase == "began" then  
 self:toString()  
 end  
 return true  
end  

While this has nothing to do with your problem, the ended phase will also call this function and not return true, which means the ended phase will get passed to other objects behind it. [import]uid: 19626 topic_id: 30372 reply_id: 121674[/import]

I’ve done these changes. The game runs, but tere’s no response of any touch. Your logic seems very correct. I can’t understand this problem. My background is C/C# and I’m a little lost with the transition to Lua.

Thanks [import]uid: 54349 topic_id: 30372 reply_id: 121700[/import]

I’d think we would need to see the code, perhaps in context instead of just snippets.
[import]uid: 19626 topic_id: 30372 reply_id: 121758[/import]

There’s nothing more in my code. It’s just that a single test of getting/setting values and listeners.
I’ll make some modifications and try to figure out what I’m doing wrong. Of course I’ll post later the results.

Thanks anyway, Robmiracle! [import]uid: 54349 topic_id: 30372 reply_id: 121760[/import]

I think the issue is that you have the displayGroup ‘block’ declared ‘local’ in that function. Even though the function returns it to main when you create the ‘block objects’, I don’t believe the function block:toString sees it, so when it goes to print it is getting nil values.

I have read a variety of articles on OOP or Classes with Corona/Lua, and settled on this approach I show below (because it works for me)… not saying it is better, or that it doesn’t have some apparent repetitive typing involved… but I have been using it and have had no apparent issues. It is not pure OOP, as I do not see how it can ‘easily’ do inheritance. It is not perfect, like most options it has it’s tradeoffs. I apologize for I can not recall who the original author was that laid this method out somewhere in the corona forums.
I will try to keep as much of your code in tact and hope you can see how it works. I have tested it and it works! I used displayRects instead of displayImages, but it is the same as far as this code is concerned.
I don’t use “module(…, package.seeall)” take that out. Not needed.

SO CODE THE FOLLOWING IN YOUR ‘block.lua’ file

local M = {}

function M.new(_blockType, _xPos, _yPos )

local self = { blockType = _blockType, xPos = _xPos, yPos = _yPos,
blockGroup, blockImage}

– each field in the ‘self’ table will be unique to each block object you create

– note the use of ‘self’ in front of any of the members of the self table above.
– if you forget to use self there will be errors

self.blockGroup = display.newGroup()
self.blockImage = display.newImage(“0” … self.blockType … “.png”)
self.blockImage:setReferencePoint(display.TopLeftReferencePoint)
self.blockGroup:insert(self.blockImage)
self.blockGroup.x = xPos;
self.blockGroup.y = yPos;

local function toString()
print( "x = " … self.blockGroup.x … ", y = " … self.blockGroup.y);

– you can also print the block type here if you want
print("block type = " … self.blockType)
end

local function onTouch(event)
print(“touch”)
if event.phase == “began” then
toString()
return true
end
end

– add the event listener right here in this file
self.blockGroup:addEventListener(“touch”, onTouch)

– for instructional purposes I added a ‘getter’ type function that will allow you to
– read a variable of this block object from the main module

local function getBlockType()
return self.blockType
end

return { getBlockType = getBlockType }
– I know it is ‘repetitive’ to type this for each setter/getter property type you might need
– but it works and it is consistent.
end
return M
IN YOUR MAIN, HERE IS THE CODE (still the same with one line removed)

local block = require( “block” )

local background = display.newRect( 0, 0, 480, 800 ); background:setFillColor(0, 50, 0);
local blocks = {}

– makes a 7x10 matrix and fill with boxes
for i = 1, 7 do
blocks[i] = {}
for j = 1, 10 do
blocks[i][j] = block.new( math.random( 1, 6 ), (i-1)*64+16, (j-1)*64+84 )
– I took out the event listener that was here

– I add this code here so you can see how to access variable of the object
print( blocks[i][j].getBlockType() )
end
end
Hope this helps. [import]uid: 148857 topic_id: 30372 reply_id: 121791[/import]

sorry for lack of indenting on the code… I had all the functions and such indented, but it must have re-fromated it when it posted… but it still should be readable. [import]uid: 148857 topic_id: 30372 reply_id: 121792[/import]

Thanks cyberparkstudios!

It helps a lot. I’ve done some changes, but is exactly what I need to understand!

[import]uid: 54349 topic_id: 30372 reply_id: 121986[/import]

I think your event listener should be:

blocks[i][j]:addEventListener(“touch”, blocks[i][j])

This block:

function block:touch(event)  
 print("touch")  
 if event.phase == "began" then  
 self:toString()  
 return true  
 end  
end  

probably should be:

function block:touch(event)  
 print("touch")  
 if event.phase == "began" then  
 self:toString()  
 end  
 return true  
end  

While this has nothing to do with your problem, the ended phase will also call this function and not return true, which means the ended phase will get passed to other objects behind it. [import]uid: 19626 topic_id: 30372 reply_id: 121674[/import]

I’ve done these changes. The game runs, but tere’s no response of any touch. Your logic seems very correct. I can’t understand this problem. My background is C/C# and I’m a little lost with the transition to Lua.

Thanks [import]uid: 54349 topic_id: 30372 reply_id: 121700[/import]

I’d think we would need to see the code, perhaps in context instead of just snippets.
[import]uid: 19626 topic_id: 30372 reply_id: 121758[/import]

There’s nothing more in my code. It’s just that a single test of getting/setting values and listeners.
I’ll make some modifications and try to figure out what I’m doing wrong. Of course I’ll post later the results.

Thanks anyway, Robmiracle! [import]uid: 54349 topic_id: 30372 reply_id: 121760[/import]

I think the issue is that you have the displayGroup ‘block’ declared ‘local’ in that function. Even though the function returns it to main when you create the ‘block objects’, I don’t believe the function block:toString sees it, so when it goes to print it is getting nil values.

I have read a variety of articles on OOP or Classes with Corona/Lua, and settled on this approach I show below (because it works for me)… not saying it is better, or that it doesn’t have some apparent repetitive typing involved… but I have been using it and have had no apparent issues. It is not pure OOP, as I do not see how it can ‘easily’ do inheritance. It is not perfect, like most options it has it’s tradeoffs. I apologize for I can not recall who the original author was that laid this method out somewhere in the corona forums.
I will try to keep as much of your code in tact and hope you can see how it works. I have tested it and it works! I used displayRects instead of displayImages, but it is the same as far as this code is concerned.
I don’t use “module(…, package.seeall)” take that out. Not needed.

SO CODE THE FOLLOWING IN YOUR ‘block.lua’ file

local M = {}

function M.new(_blockType, _xPos, _yPos )

local self = { blockType = _blockType, xPos = _xPos, yPos = _yPos,
blockGroup, blockImage}

– each field in the ‘self’ table will be unique to each block object you create

– note the use of ‘self’ in front of any of the members of the self table above.
– if you forget to use self there will be errors

self.blockGroup = display.newGroup()
self.blockImage = display.newImage(“0” … self.blockType … “.png”)
self.blockImage:setReferencePoint(display.TopLeftReferencePoint)
self.blockGroup:insert(self.blockImage)
self.blockGroup.x = xPos;
self.blockGroup.y = yPos;

local function toString()
print( "x = " … self.blockGroup.x … ", y = " … self.blockGroup.y);

– you can also print the block type here if you want
print("block type = " … self.blockType)
end

local function onTouch(event)
print(“touch”)
if event.phase == “began” then
toString()
return true
end
end

– add the event listener right here in this file
self.blockGroup:addEventListener(“touch”, onTouch)

– for instructional purposes I added a ‘getter’ type function that will allow you to
– read a variable of this block object from the main module

local function getBlockType()
return self.blockType
end

return { getBlockType = getBlockType }
– I know it is ‘repetitive’ to type this for each setter/getter property type you might need
– but it works and it is consistent.
end
return M
IN YOUR MAIN, HERE IS THE CODE (still the same with one line removed)

local block = require( “block” )

local background = display.newRect( 0, 0, 480, 800 ); background:setFillColor(0, 50, 0);
local blocks = {}

– makes a 7x10 matrix and fill with boxes
for i = 1, 7 do
blocks[i] = {}
for j = 1, 10 do
blocks[i][j] = block.new( math.random( 1, 6 ), (i-1)*64+16, (j-1)*64+84 )
– I took out the event listener that was here

– I add this code here so you can see how to access variable of the object
print( blocks[i][j].getBlockType() )
end
end
Hope this helps. [import]uid: 148857 topic_id: 30372 reply_id: 121791[/import]

sorry for lack of indenting on the code… I had all the functions and such indented, but it must have re-fromated it when it posted… but it still should be readable. [import]uid: 148857 topic_id: 30372 reply_id: 121792[/import]

Thanks cyberparkstudios!

It helps a lot. I’ve done some changes, but is exactly what I need to understand!

[import]uid: 54349 topic_id: 30372 reply_id: 121986[/import]