Creating a class with and image in corona - lua

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.

Related

LUA: Using multiple variables in an if-not then statement?

I'm working on a script for a garrysmod server and I'm completly blanking on this, I used to remember but now I can't.
I'm using this block of code,
if ent:IsVehicle() then
if ent:GetModel() ~= { "models/mafia2/shubert_taxi.mdl", "models/mafia2/parry_bus.mdl", "models/mafia2/smith_200_p_pha.mdl" } then
client:Freeze(true)
self.Owner:setAction("Chopping", time, function()
ent:Remove()
nut.item.spawn("carparts", self:GetPos() + Vector(math.Rand(1,20), math.Rand(1,20),20), nil, Angle(0, 0, 0 ))
client:Freeze(false)
self.Owner:notify("You've chopped a car.")
end)
end
originally it was if ent:GetModel() ~= "models/mafia2/shubert_taxi.mdl" and that worked fine, however I want to restrict 3 seperate models. Does anybody know how to do this?
You can use table.hasValue function:
if ent:IsVehicle() then
local models = { "models/mafia2/shubert_taxi.mdl", "models/mafia2/parry_bus.mdl", "models/mafia2/smith_200_p_pha.mdl" }
-- Notice the not keyword.
if not table.hasValue(models, ent:GetModel()) then
....

Passing data in functions, doing it wrong?

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 )

How can I access,or call a global function inside a function inside a External Library?

Well I have a class like this as an example:
--An External Library --UI.lua
UI = {}
function UI: new()
local Group = display.newGroup;
local inventory_frames = display.newImage("inventorybox.png") ;
Group :insert( inventory_frames) ;
function inventory_framesDown()
local tr_down = transition.to(inventory_frames,{time = 150,alpha = 0, x=0 ,y =8})
end
return Group
end
return UI
Now from my actual scene.lua (using storyboard API) from corona.
1.local ui= require"UI.lua"
After that in my create scene function()(The reason I have not put it in a group scene because I want to make it disappear manually)
local UI2 = UI:new()
Then inside my exit scene function.I want to call the function inventory_framesDown() from inside UI:new().
function scene:exitScene(e)
invent = UI:new() inventory_framesDown() --this dose not work
storyboard.purgeScene("scene2");
storyboard.removeAll()
end
So How can I call a global function inside a global function from a external library?
Thanks in advance:)
Basically ;
--An External Library --UI.lua
UI = {}
function UI:new()
local Group = display.newGroup;
local inventory_frames = display.newImage("inventorybox.png") ;
Group :insert( inventory_frames) ;
function Group: inventory_framesDown() -- I rewrite the code like this.
local tr_down = transition.to(inventory_frames,{time = 150,alpha = 0, x=0 ,y =8})
end
return Group
end
return UI
then In my Scene.lua after requiring the library.
In Creat scene function() I write local UI2 = UI:new() same as before
and then:
function scene:exitScene(e)
UI2.inventory_framesDown() --This Works
storyboard.purgeScene("scene2");
storyboard.removeAll()
end
I am still a bit confused why dose this work?Since there so many ways to create classes and objects.If you have a better solution I love to know Thanks again.

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