how to condense, or simplify, a function help

Hi everyone.

Maybe this is not so newbie question, but I put it here anyway.

I have a game that needs 12 functions –

or I should say, 1 function repeat it 12 times.

it just changes a little bit here and there.


I got the error that I have more than 60 upvalues. so I can not keep writting more code.


I guess I need to make just one function and use it for all the 12 objects.

I do need some help. thanks.


this is the function

cloud = display.newImage("cloud4.png")     group:insert(cloud)     cloud.x = 900; cloud.y = 180     cloud:scale (1.6, 1.6)     cloud.name = "cloud"         local function cloudListener (event)             addToScore(10)             audio.play(win)             cloud:removeEventListener("tap", cloudListener)             blancoEspanol.isVisible = true -- las nubes son blancas             blancoEnglish.isVisible = true -- the clouds are white             coinCloud.isVisible = true             transition.to(coinCloud, {time=1000, x=glowCoin.x, y=glowCoin.y})             transition.to(blancoEspanol, {time=100, delay=3000, x=-300})                 local function showPink ()                     txBlanco.isVisible = false                     txWhite.isVisible = false                     txRosa.isVisible = true                     txPink.isVisible = true                     airplane.isVisible = true                     transition.to(airplane, {time=1000, x=300, y=120})                     imageScoreLabel:toFront()                     imageScoreObject:toFront()                     scoreObject:toFront()                 end             transition.to(blancoEnglish, {time=100, delay=3000, x=1300, onComplete=showPink})             return true         end     cloud:addEventListener("tap", cloudListener)     cloud.isVisible = false

I have an idea but I need a little extra.

I guess I have to put a – local object = event.target

so instead of – airplane.isVisible

I write – object.isVisible

I have an idea but I don’t really know what to do. Please help me out

First make cloud to be local variable in your function and return it. Create function which constructs new cloud when called this way.

I did not understand what you mean by “return it”

but the idea is that I have 12 objects (cloud, airplane, tree, sky, and so on…)

so for each object I have a function – so I have 12 functions in the code – it’s too much, long code.

I think there is a way to make only 1 function and substitute, just the name for obj.

like – coinCloud for coinObject or something like that

kind of like this function, that someone else made for me

notice that I just have obj

– objScore

–obj.coin

–obj.txtEn

–obj.isFocus

this is the idea, but I don’t know how.

local function objTouch( event )     local obj = event.target     local objScore = granjaData[tostring(obj.name)]          if "began" == event.phase then         audio.play (obj.sound)         obj.isFocus = true         obj.txtEs.isVisible = true         local function resetEn()             obj.txtEs.isVisible = false             obj.txtEs.y = 730         end         transition.to(obj.txtEs, {time=2000, y=680, onComplete=resetEn})                  obj.txtEn.isVisible = true         local function resetEs()             obj.txtEn.isVisible = false             obj.txtEn.y = obj.txtEs.y + 40         end         transition.to(obj.txtEn, {time=2000, y=(680 + 40), onComplete=resetEs})                  obj.x0 = event.x - obj.x         obj.y0 = event.y - obj.y     elseif obj.isFocus then         if "moved" == event.phase then             obj.x = event.x - obj.x0             obj.y = event.y - obj.y0                          if obj.x == obj.finalX then                 transition.to(obj, {time=100, x=obj.finalX, y=obj.finalY})                 obj:removeEventListener ("touch", objTouch)                 audio.play(obj.sfx)                 audio.play(snap)                 imageScoreLabel:toFront()                 imageScoreObject:toFront()                 scoreObject:toFront()                 if objScore == 0 then                           -- test to see if coins have already been rewarded for this object                     granjaData[tostring(obj.name)] = 10       -- if not, add 10 and save                     granjaData:save()                     addToScore(10)                     audio.play(win)                     obj.coin.isVisible = true                     transition.to(obj.coin, {time=1000, x=glowCoin.x, y=40, onComplete=glow})                 else                     print("Coins already rewarded for this item") -- if coins have previously been rewarded, you can show a message here if you like                     print("Perform other action here")                 end             end                      elseif "ended" == phase or "cancelled" == phase then             obj.isFocus = false         end     end     -- Return true if the touch event has been handled.     return true end

If you can help me, please let me know.

This is how you would have the same listener for multiple objects. 

[lua]

local airplane

local cloud

local tree

local touchObject = function (event)

    local obj = event.target

    if event.phase == “ended” then

            – do something to all objects

        if obj.name == “airplane” then

            – do something when airplane is touched

        end

        if obj.name == “cloud” then

            – do something when cloud is touched

        end

         if obj.name == “tree” then

            – do something when tree is touched

        end

    end

    return true

end

airplane.name = “airplane”

cloud.name = “cloud”

tree.name = “tree”

airplane:addEventListener(“touch”,touchObject)

cloud:addEventListener(“touch”,touchObject)

tree:addEventListener(“touch”,touchObject)

[/lua]

Then, to make multiple objects using one re-usable function (and as piotrz55 says, ‘return’ the object):

[lua]

local boxes = {}

local createBox = function (x, y, height, width, r,g,b )

    local i = display.newRect(0,0,height,width)

    i.x = x

    i.y = y

    i:setFillColor(r,g,b)

    i.id = #boxes+1

    return i   –  the i object is sent to the boxes array when function called as shown below

end

boxes[#boxes+1] = createBox(240, 160, 50,100, 255, 0, 0)

boxes[#boxes+1] = createBox(100, 400, 40,40, 0, 255, 0)

[/lua]

I understand the local airplane more or less

I’m going to try that

but the local boxes, I think it’s too advanced for me.

in line 20 I don’t see the – i – anywhere.

I understand that in line 20 the – createBox( ) it’s when you call a function, and “inside” you just pass all the numbers.

is the key, when you say – i.id = #boxes+1 ?

#boxes+1 is it a variable name,?

or is part of the table?

 :)

in line 20 I don’t see the – i – anywhere.

hmmm… what is ‘i’ ? it is nothing specific. You mean variable used when looping through table? If so, this ‘i’ can be called ‘a’, ‘b’ or whatever you want.

Imagine table as bar of chcocolate. It is created from pieces. To get one piece from chocolate you must say which piece you want so

​myPiece = chocolate[2] -- we got 2nd piece

but we can also do 

local myPieceNumber = 2 myPiece = chocolate[myPieceNumber]

as you see the most important part is to give number inside [] brackets.

#boxes+1 is it a variable name

+, -, /, ., <, > etc cannot be variables

It is some arithmetic operation, let’s break it down

we add to ‘#boxes’ value of 1

So what is ‘#boxes’? As you see we have ‘#’ and ‘boxes’ - ‘boxes’ is our table. ‘#’ sign before table will get us number of elements inside. So if be have 5 elements in boxes table then ‘#boxes’ will give us 5 so we have: 5 + 1 = 6

Second issue, why we didn’t write number there? Problem is as folows

we have empty table and we want to add somethig, so we write 

boxes[1] = "new box 1" -- put text here instead object for simplicity&nbsp;

if we want to add second object we will do:

boxes[2] = "new box 2" -- easy, right?&nbsp;

But what if we would like to add next elements but we do not know how many elemets are in table during this proces? We have to add element to table at it’s end, but how?

local boxes = {} print(#boxes) -- we will get '0' and this is right because it is empty -- let's add something at the end print(#boxes + 1) -- will give '1' boxes[#boxes + 1] = &nbsp;"new box 1" -- now there is 1 element in table print(#boxes) -- will now give us '1', so there is 1 element -- let's add something &nbsp;again at the end print(#boxes + 1) -- will give '2' boxes[#boxes + 1] = &nbsp;"new box 2" -- now there is 1 element in table print(#boxes) -- will now give us '2', so there are 2 elements inside table -- and so on &nbsp;

Hope it helps  :slight_smile:

[to removal]

Thank you for the class.

– I open a brand new main.lua

– I created a new box, and I saw 3 rectangles, on screen – one red, one, green and the yellow one I made.

but this is where I get confuse.

I have 3 objects, how do I make a transition, or apply scale or rotation

I have this

local background = display.newImage ("bg.png") local boxes = {} local createBox = function (x, y, height, width, r,g,b ) &nbsp; &nbsp;&nbsp;&nbsp; local i = display.newRect(0,0,height,width) &nbsp;&nbsp;&nbsp; i.x = x &nbsp;&nbsp;&nbsp; i.y = y &nbsp;&nbsp;&nbsp; i:setFillColor(r,g,b) &nbsp;&nbsp;&nbsp; i.id = #boxes+1 &nbsp; &nbsp;&nbsp;&nbsp; return i&nbsp;&nbsp; --&nbsp; the i object is sent to the boxes array when function called as shown below end boxes[#boxes+1] = createBox(240, 160, 50,100, 255, 0, 0) boxes[#boxes+1] = createBox(100, 400, 40,40, 0, 255, 0) boxes[#boxes+1] = createBox(900, 700, 100, 500, 255, 255, 0) -- this is the new box I made transition.to(boxes[#boxes+1], {time=100, x=300})

did not worked.

transition.to(createBox, {time=100, x=300})

did not worked

you see? that’s what I don’t understand

Read once again my post and then once again

when you do transition on boxes[#boxes+1] then you are refering to not existing object. If chocolate has 5 pieces and you add 1 then you ask for 6th piece of chocolate when there are only 5 pieces.

Should be

local background = display.newImage ("bg.png") local boxes = {} local function createBox(x, y, height, width, r,g,b ) local myNewBox = display.newRect(0,0,height,width) myNewBox.x = x myNewBox.y = y myNewBox:setFillColor(r,g,b) myNewBox.id = #boxes+1 -- clever here, you give id of value box size + 1, so if there is 0 then your id is 1 :) return myNewBox end boxes[#boxes+1] = createBox(240, 160, 50,100, 255, 0, 0) -- boxes[1] = ... boxes[#boxes+1] = createBox(100, 400, 40,40, 0, 255, 0) -- boxes[2] = ... boxes[#boxes+1] = createBox(900, 700, 100, 500, 255, 255, 0) -- boxes[3] = ... transition.to(boxes[1], {time=100, x=300}) transition.to(boxes[2], {time=100, x=300}) transition.to(boxes[3], {time=100, x=300}) transition.to(boxes[#boxes], {time=100, x=300}) -- equal to line above because there are 3 elements transition.to(boxes[#boxes+1], {time=100, x=300})) -- nothing happens because you want to move non existing object (fourth one)

I think I got the other function to work.

the airplane one.

Thanks

First make cloud to be local variable in your function and return it. Create function which constructs new cloud when called this way.

I did not understand what you mean by “return it”

but the idea is that I have 12 objects (cloud, airplane, tree, sky, and so on…)

so for each object I have a function – so I have 12 functions in the code – it’s too much, long code.

I think there is a way to make only 1 function and substitute, just the name for obj.

like – coinCloud for coinObject or something like that

kind of like this function, that someone else made for me

notice that I just have obj

– objScore

–obj.coin

–obj.txtEn

–obj.isFocus

this is the idea, but I don’t know how.

local function objTouch( event ) &nbsp;&nbsp;&nbsp; local obj = event.target &nbsp;&nbsp;&nbsp; local objScore = granjaData[tostring(obj.name)] &nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; if "began" == event.phase then &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;audio.play (obj.sound) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.isFocus = true &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.txtEs.isVisible = true &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local function resetEn() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.txtEs.isVisible = false &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.txtEs.y = 730 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; transition.to(obj.txtEs, {time=2000, y=680, onComplete=resetEn}) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.txtEn.isVisible = true &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local function resetEs() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.txtEn.isVisible = false &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.txtEn.y = obj.txtEs.y + 40 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; transition.to(obj.txtEn, {time=2000, y=(680 + 40), onComplete=resetEs}) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.x0 = event.x - obj.x &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.y0 = event.y - obj.y &nbsp;&nbsp;&nbsp; elseif obj.isFocus then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if "moved" == event.phase then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.x = event.x - obj.x0 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.y = event.y - obj.y0 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if obj.x == obj.finalX then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; transition.to(obj, {time=100, x=obj.finalX, y=obj.finalY}) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj:removeEventListener ("touch", objTouch) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; audio.play(obj.sfx) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; audio.play(snap) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; imageScoreLabel:toFront() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; imageScoreObject:toFront() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; scoreObject:toFront() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if objScore == 0 then&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- test to see if coins have already been rewarded for this object &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; granjaData[tostring(obj.name)] = 10&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- if not, add 10 and save &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; granjaData:save() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; addToScore(10) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; audio.play(win) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.coin.isVisible = true &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; transition.to(obj.coin, {time=1000, x=glowCoin.x, y=40, onComplete=glow}) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print("Coins already rewarded for this item") -- if coins have previously been rewarded, you can show a message here if you like &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print("Perform other action here") &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elseif "ended" == phase or "cancelled" == phase then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.isFocus = false &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp; -- Return true if the touch event has been handled. &nbsp;&nbsp;&nbsp; return true end

If you can help me, please let me know.

This is how you would have the same listener for multiple objects. 

[lua]

local airplane

local cloud

local tree

local touchObject = function (event)

    local obj = event.target

    if event.phase == “ended” then

            – do something to all objects

        if obj.name == “airplane” then

            – do something when airplane is touched

        end

        if obj.name == “cloud” then

            – do something when cloud is touched

        end

         if obj.name == “tree” then

            – do something when tree is touched

        end

    end

    return true

end

airplane.name = “airplane”

cloud.name = “cloud”

tree.name = “tree”

airplane:addEventListener(“touch”,touchObject)

cloud:addEventListener(“touch”,touchObject)

tree:addEventListener(“touch”,touchObject)

[/lua]

Then, to make multiple objects using one re-usable function (and as piotrz55 says, ‘return’ the object):

[lua]

local boxes = {}

local createBox = function (x, y, height, width, r,g,b )

    local i = display.newRect(0,0,height,width)

    i.x = x

    i.y = y

    i:setFillColor(r,g,b)

    i.id = #boxes+1

    return i   –  the i object is sent to the boxes array when function called as shown below

end

boxes[#boxes+1] = createBox(240, 160, 50,100, 255, 0, 0)

boxes[#boxes+1] = createBox(100, 400, 40,40, 0, 255, 0)

[/lua]

I understand the local airplane more or less

I’m going to try that

but the local boxes, I think it’s too advanced for me.

in line 20 I don’t see the – i – anywhere.

I understand that in line 20 the – createBox( ) it’s when you call a function, and “inside” you just pass all the numbers.

is the key, when you say – i.id = #boxes+1 ?

#boxes+1 is it a variable name,?

or is part of the table?

 :)

in line 20 I don’t see the – i – anywhere.

hmmm… what is ‘i’ ? it is nothing specific. You mean variable used when looping through table? If so, this ‘i’ can be called ‘a’, ‘b’ or whatever you want.

Imagine table as bar of chcocolate. It is created from pieces. To get one piece from chocolate you must say which piece you want so

​myPiece = chocolate[2] -- we got 2nd piece

but we can also do 

local myPieceNumber = 2 myPiece = chocolate[myPieceNumber]

as you see the most important part is to give number inside [] brackets.

#boxes+1 is it a variable name

+, -, /, ., <, > etc cannot be variables

It is some arithmetic operation, let’s break it down

we add to ‘#boxes’ value of 1

So what is ‘#boxes’? As you see we have ‘#’ and ‘boxes’ - ‘boxes’ is our table. ‘#’ sign before table will get us number of elements inside. So if be have 5 elements in boxes table then ‘#boxes’ will give us 5 so we have: 5 + 1 = 6

Second issue, why we didn’t write number there? Problem is as folows

we have empty table and we want to add somethig, so we write 

boxes[1] = "new box 1" -- put text here instead object for simplicity&nbsp;

if we want to add second object we will do:

boxes[2] = "new box 2" -- easy, right?&nbsp;

But what if we would like to add next elements but we do not know how many elemets are in table during this proces? We have to add element to table at it’s end, but how?

local boxes = {} print(#boxes) -- we will get '0' and this is right because it is empty -- let's add something at the end print(#boxes + 1) -- will give '1' boxes[#boxes + 1] = &nbsp;"new box 1" -- now there is 1 element in table print(#boxes) -- will now give us '1', so there is 1 element -- let's add something &nbsp;again at the end print(#boxes + 1) -- will give '2' boxes[#boxes + 1] = &nbsp;"new box 2" -- now there is 1 element in table print(#boxes) -- will now give us '2', so there are 2 elements inside table -- and so on &nbsp;

Hope it helps  :slight_smile:

[to removal]