Error: function at line 239 has more than 60 upvalues

I have a text field in which when a person types in a number from 1-200, a scene will come up. Each 200 scenes are different. The code uses a button and 200 if/else statements. However only 61 scenes work and none of the other 149 scenes.

In the log it says:

22:57:37.988  error loading module ‘view3’ from file ‘C:\Users\cornt\Documents\Corona Projects\APP1\view3.lua’:

22:57:37.988   C:\Users\cornt\Documents\Corona Projects\APP1\view3.lua:364: function at line 239 has more than 60 upvalues

22:57:37.988  stack traceback:

22:57:37.988   [C]: in function ‘error’

22:57:37.988   ?: in function ‘gotoScene’

22:57:37.988   C:\Users\cornt\Documents\Corona Projects\APP1\view2.lua:49: in function ‘?’

22:57:37.988   ?: in function <?:182>

23:07:29.834  

What is wrong?

Is it because you can only do 60 if statements.

I do not want to Share my code because it would be too long and someone would take me code.

However here is the basic idea of my code:

--Textbox Variable local boxField --Text Listener local function textListener( event ) if ( event.phase == "began" ) then -- User begins editing "numericField" end end --Creating the textbox boxField = native.newTextField( background.x, background.y, 180, 30 ) boxField.inputType = "number" boxField:addEventListener( "userInput", textListener ) --Search Button local searchBn = display.newImageRect("name.png", 200,50) searchBn.x = display.contentCenterX searchBn.y =display.contentCenterY+50 --Scene Creation(Since there is no space for 200 lines of composer lines, I will do 3) local function 1( event ) composer.gotoScene( "1" ) end local function 2( event ) composer.gotoScene( "2" ) end local function 3( event ) composer.gotoScene( "3" ) end --Search function creation local function searchFunction() --if statement(Since there is no space for 200 lines of if statements, I will do 3) if boxField.text == "1" then 1() elseif boxField.text == "2" then 2() elseif boxField.text == "3" then 3() end end searchBn:addEventListener("tap",searchFunction) --That is the basic idea of my code except instead of 3 lines of if/else/composer code, it is 200

Hi, Gary the method you are referring is not the right way. I am shocked why you need 200 Different Scene.

The following are the two ways that you can refer:
 

1- Make 200 Scene as a Module in single file & call them respectively.

or

2-Suppose let’s consider your scene name are view1,view2,view3…view200.
  then you can do like this:

  1- make a function callMyScene(SceneNum), here SceneNum is textField value.

  2-Call this function when the user enters in textField & click submit.

   

  ex:

[lua]

– Declared Variables

local boxField

local searchBn

–callMyScene Function which calls respective scene

   

local callMyScene=function(SceneNum)

      local sceneName=“view”…SceneNum

      if composer.getScene(sceneName)==nil then

             print(“Scene/File Not Found - Check Scene Name”)

      else

             composer.gotoScene(sceneName)   

      end

end

–Creating the textbox

boxField = native.newTextField( background.x, background.y, 180, 30 )

boxField.inputType = “number”

–Search Button

searchBn = display.newImageRect(“name.png”, 200,50)

searchBn.x = display.contentCenterX

searchBn.y =display.contentCenterY+50

searchBn:addEventListener(“tap”,function()

              if boxField.text=="" or boxField.text==nil then

                  return true

              else

                  callMyScene(boxField.text)

              end

end)

[/lua]

Dear Gary, You can refer the above code. I didn’t compile the code but Hope it will work & you will get an idea how to implement it via referring above snippet.

Kindly,

Assif

As Assif says, having 200 functions to call 200 different scenes is very inefficient programming, even if Lua would allow it.

Each Lua module has a limit of 200 local variables, including function references, so that’s why you get this error. There are ways around it, but I wouldn’t recommend it for this purpose.

Similarly, having 200 scene files is probably not optimal, unless you are literally building a suite containing 200 completely different games or tools. 

If you think about something like Sonic The Hedgehog, if you build this in Corona you would have one central ‘game’ scene, that imports various data and code modules depending on the requirements of the stage being played. If you have multiple scenes, if you change the code for how Sonic jumps in one scene, you have to remember to change it in all of them.

A basic rule of thumb is that you should only write code once. If you find yourself needing to copy code somewhere else (i.e. 200 similar functions that all have one job, to load a scene), then it’s probably time to re-think how that can be re-structured.

Thanks for replying Assif and Nick. My app is not a game but more like a dictionary which is why there is 200 scenes. I will see if Assif’s code works.

The code didn’t work.

I got it working. I removed all the if statements to make the code simpler and removed some unnecessary variables. Here is the code:

--Search local boxField local searchBn local function textListener( event ) if ( event.phase == "began" ) then -- User begins editing "numericField" end end -- Create text field boxField = native.newTextField( background.x, background.y, 180, 30 ) boxField.inputType = "number" boxField:addEventListener( "userInput", textListener ) --callMyScene Function which calls respective scene local function callMyScene() composer.gotoScene(boxField.text) end searchBn = display.newImageRect("name.png", 200,50) searchBn.x = display.contentCenterX searchBn.y =display.contentCenterY+50 searchBn:addEventListener("tap",callMyScene)

Unless each scene is drastically different, you probably be doing more data driven. You can have one module with all the data in it (if it’s a dictionary like app: word, pronunciation, definition. I’m greatly simplifying this:

local words = { &nbsp; { word="Apple", pronounced="Ah-peel", definition = ("Tree Fruit"} }, -- word #1 &nbsp; { word="Bat", pronounced="bu-at", definition = { "flying mammal", "sporting equipment" }, -- word 2 &nbsp; { word="Cat", pronounced "kh-at", definition = { "sneaky feline animal } }, &nbsp;-- word 3 }

You have a table thats indexed by number. Each array entry has key-value pairs for the data. Notice for the Bat, how I’m using a sub-table to allow multiple definitions.

Then in your scene, create display.newTextObject()'s for each piece to display. when your search text is entered, if it’s a valid number, then do something like and it’s saved in a variable named “whichWord”

wordText.text = &nbsp;words[whichWord].word pronounceText.text = words[whichWord].pronounced.

This of course would require you have already created display.newText() objects called wordText and pronouneText.

Can all be done with one scene.

Rob

Agreed with Rob, If the scene display object structure is same & only data is getting changed for respective search.
Then you should probably go with the way Rob mentioned via declaring a JSON.

I have developed an application for dictionary & used the same way as Rob mentioned.
 

Assif

 

Hi, Gary the method you are referring is not the right way. I am shocked why you need 200 Different Scene.

The following are the two ways that you can refer:
 

1- Make 200 Scene as a Module in single file & call them respectively.

or

2-Suppose let’s consider your scene name are view1,view2,view3…view200.
  then you can do like this:

  1- make a function callMyScene(SceneNum), here SceneNum is textField value.

  2-Call this function when the user enters in textField & click submit.

   

  ex:

[lua]

– Declared Variables

local boxField

local searchBn

–callMyScene Function which calls respective scene

   

local callMyScene=function(SceneNum)

      local sceneName=“view”…SceneNum

      if composer.getScene(sceneName)==nil then

             print(“Scene/File Not Found - Check Scene Name”)

      else

             composer.gotoScene(sceneName)   

      end

end

–Creating the textbox

boxField = native.newTextField( background.x, background.y, 180, 30 )

boxField.inputType = “number”

–Search Button

searchBn = display.newImageRect(“name.png”, 200,50)

searchBn.x = display.contentCenterX

searchBn.y =display.contentCenterY+50

searchBn:addEventListener(“tap”,function()

              if boxField.text=="" or boxField.text==nil then

                  return true

              else

                  callMyScene(boxField.text)

              end

end)

[/lua]

Dear Gary, You can refer the above code. I didn’t compile the code but Hope it will work & you will get an idea how to implement it via referring above snippet.

Kindly,

Assif

As Assif says, having 200 functions to call 200 different scenes is very inefficient programming, even if Lua would allow it.

Each Lua module has a limit of 200 local variables, including function references, so that’s why you get this error. There are ways around it, but I wouldn’t recommend it for this purpose.

Similarly, having 200 scene files is probably not optimal, unless you are literally building a suite containing 200 completely different games or tools. 

If you think about something like Sonic The Hedgehog, if you build this in Corona you would have one central ‘game’ scene, that imports various data and code modules depending on the requirements of the stage being played. If you have multiple scenes, if you change the code for how Sonic jumps in one scene, you have to remember to change it in all of them.

A basic rule of thumb is that you should only write code once. If you find yourself needing to copy code somewhere else (i.e. 200 similar functions that all have one job, to load a scene), then it’s probably time to re-think how that can be re-structured.

Thanks for replying Assif and Nick. My app is not a game but more like a dictionary which is why there is 200 scenes. I will see if Assif’s code works.

The code didn’t work.

I got it working. I removed all the if statements to make the code simpler and removed some unnecessary variables. Here is the code:

--Search local boxField local searchBn local function textListener( event ) if ( event.phase == "began" ) then -- User begins editing "numericField" end end -- Create text field boxField = native.newTextField( background.x, background.y, 180, 30 ) boxField.inputType = "number" boxField:addEventListener( "userInput", textListener ) --callMyScene Function which calls respective scene local function callMyScene() composer.gotoScene(boxField.text) end searchBn = display.newImageRect("name.png", 200,50) searchBn.x = display.contentCenterX searchBn.y =display.contentCenterY+50 searchBn:addEventListener("tap",callMyScene)

Unless each scene is drastically different, you probably be doing more data driven. You can have one module with all the data in it (if it’s a dictionary like app: word, pronunciation, definition. I’m greatly simplifying this:

local words = { &nbsp; { word="Apple", pronounced="Ah-peel", definition = ("Tree Fruit"} }, -- word #1 &nbsp; { word="Bat", pronounced="bu-at", definition = { "flying mammal", "sporting equipment" }, -- word 2 &nbsp; { word="Cat", pronounced "kh-at", definition = { "sneaky feline animal } }, &nbsp;-- word 3 }

You have a table thats indexed by number. Each array entry has key-value pairs for the data. Notice for the Bat, how I’m using a sub-table to allow multiple definitions.

Then in your scene, create display.newTextObject()'s for each piece to display. when your search text is entered, if it’s a valid number, then do something like and it’s saved in a variable named “whichWord”

wordText.text = &nbsp;words[whichWord].word pronounceText.text = words[whichWord].pronounced.

This of course would require you have already created display.newText() objects called wordText and pronouneText.

Can all be done with one scene.

Rob

Agreed with Rob, If the scene display object structure is same & only data is getting changed for respective search.
Then you should probably go with the way Rob mentioned via declaring a JSON.

I have developed an application for dictionary & used the same way as Rob mentioned.
 

Assif