Passing data in functions, doing it wrong? - lua

I'm using Corona SDK to create an Android/iOS app. And I'm trying to pass two different parameters in a function. The function is called like this:
function onCollision( self, event )
The problem is, when the function is called, it returns this error: attempt to index local "event" a nil value. I know why, I think it's because of the comma. But I've read documentation and that's how you're supposed to do it, any help?

If you give a table object and reference your function as part of the table it should work:
local object = display.newImage( "object.png" )
physics.addBody( object , { ... } )
local function onCollision( self, event )
...
end
object.collision = onCollision
object:addEventListener( "collision", object)

Your function should be function onCollision(event), self isn't needed.
If you actually want to pass another parameter to this function, you can do it using a closure like that:
local myParam = 1
Runtime:addEventListener ( "collision", function(event)
return onCollision(event, myParam)
end )

Related

Metatables, attempt to call method 'rename' (a nil value)

This is my first time using metatables, I did a simple script to test in Lua demo but it always give me "attempt to call method 'rename' (a nil value)", why?
peds = {}
function peds.new ( name )
local tb = { name = name }
setmetatable ( tb, { __index = peds } )
return tb
end
function peds.rename ( name )
self.name = name
return self.name == name
end
local ped = peds.new ( "max" )
ped:rename ( "randomname" )
There's two (possible) problems in your code, depending on how you are setting things up.
If you are just typing the above into a REPL, then when you declare local ped = ... it immediately goes out of scope and becomes inaccessible. So the expression ped:rename is invalid, although it should report "ped is nil" not "rename is nil".
If you are saving the above to a script and loading it using load_file or something, you will still get a problem, because this function signature isn't right:
function peds.rename ( name )
should be:
function peds.rename ( self, name )
Similar to how it works in C++, in lua, when you make an object method, you have to take the hidden self parameter first, and when you call ped:rename( "random name" ) that's just syntactic sugar for ped.rename(ped, "random_name"). If the self parameter doesn't exist then it's not going to work, or may even say "function not found / rename is nil" because the signatures don't match up.

accessing lua self member got nil

I was trying to access a member of 'self', see following:
function BasePlayer:blah()
--do blah
end
function BasePlayer:ctor(tape) --constructor.
self.tape = tape --'tape' is a lua table, and assigned to 'self.tape'.
dump(self.tape) --i can dump table 'self.tape',obviously it's not nil.
self.coreLogic = function(dt) --callback function called every frame.
echoInfo("%s",self) --prints self 'userdata: 0x11640d20'.
echoInfo("%s",self.tape) -- Here is my question: why self.tape is nil??
self:blah() --even function too??
end
end
So my question is, in my callback function 'coreLogic', why 'self.tape' is nil but self is
vaild?
And functions can't be called either.
I'm really confused:S
When you define a function using the :, the implicit parameter is created on its own. When you are defining the function coreLogic, you'd need to pass it as the first argument:
self.coreLogic = function( self, dt )
and that would be the same as:
function self:coreLogic(dt)
self in itself doesn't exist.
Basically,
function BasePlayer:blah()
is same as writing:
function BasePlayer.blah( BasePlayer )

Creating a class with and image in corona

I'm trying to create my own class in corona based on this example
It looks like:
local car={};
local car_mt = { __index=car };
function car.new()
local ncar=
{
img=display:newImage("test_car.png");
}
return setmetatable(ncar,car_mt);
end
return car;
And it's called at level by this:
local pcar=require("car")
...
function scene:enterScene( event )
local group = self.view
physics.start();
local car1=pcar.new();
end
The image exists in the same folder, but i get:
bad argument #-2 to newImage (Proxy expected, got nil)
I saw some similar issues in the Net, and it seems to me that newImage() doesn't know where to place a picture. But how can I say it if the class it made to be used for any stage?
Oh, the error is because you're calling newImage function as:
display:newImage( "test_car.png" )
which is the wrong syntax. The above statement actually means:
display.newImage( display, "test_car.png" )
which, obviously is wrong.
The correct method would be:
display.newImage( "test_car.png" )
Read more about the corona API here.

Trying to add a event listener fo a object which is part of an array in lua using corona

The main creates a simple 2d array. Now i want to create a addeventlistener for each object in the table. I presume i do this in the class? Although i have created a taps function and then defined addeventlistener but i ma getting errors.
--main.lua--
grid={}
for i =1,5 do
grid[i]= {}
for j =1,5 do
grid[i][j]=diceClass.new( ((i+2)/10),((j+2)/10))
end
end
--dice class--
local dice = {}
local dice_mt = { __index = dice } -- metatable
function dice.new( posx, posy) -- constructor
local a=math.random(1,6)
local b= true
local newdice = display.newText(a, display.contentWidth*posx,
display.contentHeight*posy, nil, 60)
--newdice:addEventListener("tap", taps(event))
return setmetatable( newdice, dice_mt )
end
function dice:taps(event)
self.b = false
print("works")
end
function dice:addEventListener("tap", taps(event))
This stumped me till today. The main problem is that you're making newdice a Corona display.newText object and then reassigning it to be a dice object. All the Corona objects act like ordinary tables, but they're actually special objects. So you have two options:
A. Don't use classes and OOP. As your code is now, there's no reason to have dice be a class. This is the option I'd go with unless you have some compelling reason to make dice a class. Here's how you would implement this option
--dice not a class--
local dice = {}
local function taps(event)
event.target.b = false
print("works")
end
function dice.new( posx, posy) -- constructor
local a=math.random(1,6)
--local b= true
local newdice = {}
newdice = display.newText(a, display.contentWidth*posx,
display.contentHeight*posy, nil, 60)
newdice:addEventListener("tap", taps)
newdice.b = true
return newdice
end
or B. Use a "has a" relationship instead of an "is a" relationship for the display object. Since you can't make them both a dice object and a display object, your dice object could contain a display object. Here's how that would look.
--dice class--
local dice = {}
local dice_mt = { __index = dice } -- metatable
local function taps(event)
event.target.b = false
print("works")
end
function dice.new( posx, posy) -- constructor
local a=math.random(1,6)
--local b= true
local newdice = {}
newdice.image = display.newText(a, display.contentWidth*posx,
display.contentHeight*posy, nil, 60)
newdice.image:addEventListener("tap", taps)
newdice.b = true
return setmetatable( newdice, dice_mt )
end
There were some other problems as well. In your taps function event handler you have to use event.target.b instead of self.b. Also, in dice.new b is a local variable so it's not a member of your dice class.
Remove the last line.
The addEventListener function should be called like this
newdice:addEventListener("tap", taps)

Corona SDK - Call an instance method or class method from an eventListener

I've got a Foo class (well, a pseudo-class) set up as follows:
--in foo.lua
Foo = {}
--constructor
function Foo:new(x, y)
--the new instance
local foo = display.newImage("foo.png")
-- set some instance vars
foo.x = x
foo.y = y
foo.name = 'foo'
--instance method
function foo:speak()
print("I am an instance and my name is " .. self.name)
end
--another instance method
function foo:moveLeft()
self.x = self.x - 1
end
function foo:drag(event)
self.x = event.x
self.y = event.y
end
foo:addEventListener("touch", drag)
return foo
end
--class method
function Foo:speak()
print("I am the class Foo")
end
return Foo
I want the event listener on the foo object to call foo:drag on that same instance. I can't work out how, though: at the moment it's calling a local function called "drag" in my main.lua, which i'm then passing back to the instance. Can i call the instance method directly from the listener? I'm reading about listeners here http://developer.anscamobile.com/reference/index/objectaddeventlistener but am kind of confused :/
thanks, max
There are 2 different types of event listeners in Corona, function listeners and table listeners. The local function you mention works because that function is called directly when the event triggers. Corona doesn't support passing table functions, so passing drag in this instance won't work.
To get this working, you need to use the table listener like this:
function foo:touch(event)
self.x = event.x
self.y = event.y
end
foo:addEventListener("touch", foo)
This works because the event listener will try to call the function within table foo with the same name as the event - in this example "touch".
If you need to keep the function name as drag, you can work around this limitation by adding this after the function definition:
player.touch = player.drag
This basically redirects the touch call to your drag function.
I've had a similar issue with event listeners. I solved it with something like this:
foo:addEventListener("touch", function(e) { self:drag(e); });
I use Middle Class for OOP programing in Lua (which I really recommend)...so I'm not sure if this will work in your scenario. Hope it helps.

Resources