Runtime error that makes no sense to me.

Not sure what the problem is, but when testing on a device I get a Runtime Error. I posted a screenshot of the error. Can anyone tell me what’s wrong with my code?

It points to the x value I set for my floor1 variable. Why? I first thought it was due to the image being case sensitive but it’s actually spelled correctly. Why would it call an error on the x value? I’m so confused.

Here’s the chunk it was called in:

EDIT: It was due to my code not being implemented into Composer correctly. Variables are only called once if outside the listeners, therefore it didn’t know what floor1 was after it was called the first time (I think??).

I could really use some help with converting my project to composer. Please read the message below.

local floor1 = display.newImageRect("/images/Items/springboardUp.png", 80, 30)

floor1.x = centerX – [[<<< This is where the error is.]]–

floor1.y = centerY + 30

floor1:setFillColor(0, 0, 1)

physics.addBody(floor1, “kinematic”, {radius = 10})

floor1.rotation = 40

floor1.name = “floor1”

floor1.isPlatform = true

I’ve figured out that it has everything to do with "composer’. I really…REALLY do not understand how to use composer. I went over the tutorial quite a number of times. I’ve tried and tried to piece my code into the template but I seem to always get an error. I believe to have followed the tutorial and template to a T; from putting all the display objects into create:scene, listeners where it says to put listeners, display objects into the group and basically whatever was commented in the template I put the code that would fit there.

Is there anyone willing to help me convert my project into composer and answer any questions I may have? There’s really not much to convert - I only have one level of my game complete and the code is short, so it won’t be too much of a hassle for anyone.

Any help would be greatly appreciated.

Assuming you’re converting from Storyboard, it’s not that huge of change. You could conceivably put everything  in the scene:show (phase == “did”) and everything would work fine. I think what you’re running into is a problem with scope, rather than a Composer-specific issue.

If you do something like this:

local function creatFloor() local floor1 = display.newImageRect("/images/Items/springboardUp.png", 80, 30) end creatFloor() floor1.x = centerX floor1.y = centerY + 30

you are going to get an error because the variable “floor1” is local to the function createFloor(). You will not be able to get access to the floor1 anywhere outside of that function. If you could post more of your code it would help to isolate and explain the issue in further detail.

Let me take a crack at this.  Composer scene’s are Lua modules, nothing more.  You require some stuff.  You create a scene object (a Lua Table) and return that table at the end.  The composer.gotoScene() call is going to dispatch some events as part of it’s code to transition a scene on and off screen.   It’s these events that cause your scene:create() and scene:show() functions to fire.

But on a more simple level, you have to deal with scope between modules.  When you do:

local centerX  = display.contentCenterX

in main.lua, only main.lua knows about the centerX variable.  When you’re in your menu.lua scene it has no clue that centerX exists.  This is where global variables become useful.  If in main.lua you instead did:

centerX = display.contentCenterX

then centerX would be known by all scenes.  Globals in general are very bad to use if you don’t know what you’re doing with them.   You may not realize you’re using a variable in one module and then in another you use it there and change the value, you’ve changed it for your entire app.  They are not performance friendly.  They can lead to memory leaks if you use them for things other than simple variables and so on.  But for things like defining short-cut constants like centerX and centerY that you’re not going to change won’t be used in places where performance has to be super optimal, it’s okay to do them.  Corona SDK already provides you a centerX and centerY constant with display.contentCenterX which is a bit long to type.  I use that instead of trying to have a global short cut.

Many programmers new to working with multiple modules will think leaving the “local” off is the solution to their problems of not understanding scope and that’s where you’re going to get into major trouble.  Globals are evil until you know what you’re doing.

Normally for data to be passed between scenes there are three main ways:

1.  Use a data module.  See:  http://coronalabs.com/blog/2013/05/28/tutorial-goodbye-globals/

2.  Use parameter passing when you call composer.gotoScene().  There should be a good explanation of this in the Composer Guide:  https://docs.coronalabs.com/guide/system/composer/index.html#goingto

3.  Use Composer’s own object to store data in that all scenes need to see (similar to #1 but using the scene object instead).  See: https://docs.coronalabs.com/guide/system/composer/index.html#other

Now none of these three deal with the fact that you’re using centerX as a shortcut for display.contentCenterX and all will involve typing a bit more to make work.  That’s why centerX and centerY will work as globals.

Rob

Thank you guys. I appreciate the help.

@Alex@Panc – I’m only about 2 weeks into using Corona SDK. Therefore, I have never used Storyboard. The first version of Corona I downloaded was the latest version (the current version).

@ Rob Miracle – That was very useful information, thank you. Alex was saying that putting everything into scene:show “did” phase would would perfectly fine. I tried that with a different project and it worked. Is that really the best way to do it though? Would it cause any problems?

Alex’s suggestion is great if you don’t care about transitions and until you get a better grasp of scope.  The idea of creating them in scene:create() is that they are created off screen and then when you call scene:show().  If you only use scene:show() you loose this.

Scope isn’t hard.  Just a couple of things to commit to memory.  Corona (well Lua) is a one pass compiler.  That is it starts at the top and reads down your code once.  Other compilers like C++ are two pass.  The first time the learn all the variable names you are going to use and what they are defined as, then they go back and fill in anything that’s undefined.  Since Lua doesn’t do that second pass, if you reference a variable or function before it’s defined, it’s going to be nil.  So the basic rule:  define it before you use it is key to making Lua work for you.

The second part of scope is that things defined “local” can only be seen in the block they are defined in and any children blocks.  This means if you create an image object in scene:create and make it local in scene create:

function scene:create( event ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local image = display.newImage("somegraphic.png") &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local function doSomething() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; image.someNewProperty = true &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doSomething() end

then image is only known to scene:create() and it’s child function “doSomething”.  Other sibling functions like scene:show() can’t  see image.

To solve that, the solution is to declare image at a higher level block, i.e. the module’s main chunk:

local image function scene:create( event ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; image = display.newImage("somegraphic.png") &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local function doSomething() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; image.someNewProperty = true &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doSomething() end

Notice that image was declared outside of the scene:create() function, but it didn’t get a value until inside scene:create().  It’s still visible to doSomething, but now it’s visible to scene:show() also.  However doSometthing is still limited to scene:create().  If you want that function to be visible to anything in the scene, you can do:

local image &nbsp; local function doSomething() &nbsp;&nbsp;&nbsp; image.someNewProperty = true end &nbsp; function scene:create( event ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; image = display.newImage("somegraphic.png") &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doSomething() end

now doSomething can be called from scene:create, scene:show or any function in the main chunk defined after it.

Hope this helps

Rob

Great info! I just started learning about this while running through the “Attack of the Cuteness” tutorial on the Udemy lecture by Jay. Going into further detail about how it works has really helped. Thanks Rob =D.

For the longest I was trying to figure out how to call my variables/objects that were inside functions. It was frustrating, so I just started making everything I wanted to be called a local variable outside of functions instead of throwing it into a function lol. Now I could better manage and organize my code. Appreciate the help.

Rob, I took my code out of composer and built for Android, but I still get the Runtime Error on my device. What I don’t understand is it’s saying floor1 is a nil value. “floor1” is a local variable that isn’t placed into a function. It’s in the main chunk. I’m gonna send the code in a PM (I’d rather not post it for everyone to see). Would you mind looking at it?

EDIT: There doesn’t seem to be an option to PM you on your page. How else can I show you?

Here is the top part of my code, up until floor1:

– Add physics

local composer = require( “composer” )

local gameUI = require(“gameUI”)

local ragdogLib = require “ragdogLib”;

local physics = require(“physics”)

– physics.setDrawMode(“hybrid”)

– physics.setDrawMode(“debug”)

physics.setDrawMode(“normal”)

physics.start()

physics.gravity = 15

– Forward references

local myPlayer

– Set Variables

local xMin = display.screenOriginX

local yMin = display.screenOriginY

local xMax = display.contentWidth - display.screenOriginX

local yMax = display.contentHeight - display.screenOriginY

local _W = display.contentWidth

local _H = display.contentHeight

local centerX = display.contentCenterX

local centerY = display.contentCenterY

local rand = math.random

local randColor = math.random(0, 255)/255

local dragBody = gameUI.dragBody

–[[local background = display.newImageRect(“bg1.png”, display.contentWidth, display.contentHeight)

background.x = display.contentWidth*0.5

background.y = display.contentHeight*0.5

]]–

– Let’s set the level up here

local background = display.newImage(“full-background.png”, centerX, centerY)

background.x = _W/2

background.y = _H/2

local floor1 = display.newImage("/images/Items/springboardUp.png", 80, 30)

floor1.x = 400

floor1.y = centerY + 80

floor1:setFillColor(0, 0, 1)

physics.addBody(floor1, “kinematic”, {radius = 10})

floor1.rotation = 50

floor1.name = “floor1”

floor1.isPlatform = true

The error is where floor1.x is defined.

floor1 is only called one more time… and that’s in a function to transition floor1 back and forth across the screen. Here’s the code for that section:

function movePlatform2()

    transition.to( floor1, {time = 5000, x = 400, onComplete = movePlatform } )

end

function movePlatform()

transition.to( floor1, {time = 5000, x = 40, onComplete = movePlatform2 } )

end

floor1 will remain a nil value if you don’t successfully create a display object. It’s possible that the problem lies with the line of code where you create the display object using display.newImageRect - double-check the path to your image file, including capitalization. Also, get rid of the slash at the beginning of your image file string ("/images/items/springboardUp.png") - it definitely isn’t necessary, and it might actually be the cause of your problem.

Good luck!

I have my PM’s turned off because too many people want to get direct help.  These are community forums and frequently the other community members can provide better solutions than Brent and I can. 

Rob

I’ve figured out that it has everything to do with "composer’. I really…REALLY do not understand how to use composer. I went over the tutorial quite a number of times. I’ve tried and tried to piece my code into the template but I seem to always get an error. I believe to have followed the tutorial and template to a T; from putting all the display objects into create:scene, listeners where it says to put listeners, display objects into the group and basically whatever was commented in the template I put the code that would fit there.

Is there anyone willing to help me convert my project into composer and answer any questions I may have? There’s really not much to convert - I only have one level of my game complete and the code is short, so it won’t be too much of a hassle for anyone.

Any help would be greatly appreciated.

Assuming you’re converting from Storyboard, it’s not that huge of change. You could conceivably put everything  in the scene:show (phase == “did”) and everything would work fine. I think what you’re running into is a problem with scope, rather than a Composer-specific issue.

If you do something like this:

local function creatFloor() local floor1 = display.newImageRect("/images/Items/springboardUp.png", 80, 30) end creatFloor() floor1.x = centerX floor1.y = centerY + 30

you are going to get an error because the variable “floor1” is local to the function createFloor(). You will not be able to get access to the floor1 anywhere outside of that function. If you could post more of your code it would help to isolate and explain the issue in further detail.

Let me take a crack at this.  Composer scene’s are Lua modules, nothing more.  You require some stuff.  You create a scene object (a Lua Table) and return that table at the end.  The composer.gotoScene() call is going to dispatch some events as part of it’s code to transition a scene on and off screen.   It’s these events that cause your scene:create() and scene:show() functions to fire.

But on a more simple level, you have to deal with scope between modules.  When you do:

local centerX  = display.contentCenterX

in main.lua, only main.lua knows about the centerX variable.  When you’re in your menu.lua scene it has no clue that centerX exists.  This is where global variables become useful.  If in main.lua you instead did:

centerX = display.contentCenterX

then centerX would be known by all scenes.  Globals in general are very bad to use if you don’t know what you’re doing with them.   You may not realize you’re using a variable in one module and then in another you use it there and change the value, you’ve changed it for your entire app.  They are not performance friendly.  They can lead to memory leaks if you use them for things other than simple variables and so on.  But for things like defining short-cut constants like centerX and centerY that you’re not going to change won’t be used in places where performance has to be super optimal, it’s okay to do them.  Corona SDK already provides you a centerX and centerY constant with display.contentCenterX which is a bit long to type.  I use that instead of trying to have a global short cut.

Many programmers new to working with multiple modules will think leaving the “local” off is the solution to their problems of not understanding scope and that’s where you’re going to get into major trouble.  Globals are evil until you know what you’re doing.

Normally for data to be passed between scenes there are three main ways:

1.  Use a data module.  See:  http://coronalabs.com/blog/2013/05/28/tutorial-goodbye-globals/

2.  Use parameter passing when you call composer.gotoScene().  There should be a good explanation of this in the Composer Guide:  https://docs.coronalabs.com/guide/system/composer/index.html#goingto

3.  Use Composer’s own object to store data in that all scenes need to see (similar to #1 but using the scene object instead).  See: https://docs.coronalabs.com/guide/system/composer/index.html#other

Now none of these three deal with the fact that you’re using centerX as a shortcut for display.contentCenterX and all will involve typing a bit more to make work.  That’s why centerX and centerY will work as globals.

Rob

Thank you guys. I appreciate the help.

@Alex@Panc – I’m only about 2 weeks into using Corona SDK. Therefore, I have never used Storyboard. The first version of Corona I downloaded was the latest version (the current version).

@ Rob Miracle – That was very useful information, thank you. Alex was saying that putting everything into scene:show “did” phase would would perfectly fine. I tried that with a different project and it worked. Is that really the best way to do it though? Would it cause any problems?

Alex’s suggestion is great if you don’t care about transitions and until you get a better grasp of scope.  The idea of creating them in scene:create() is that they are created off screen and then when you call scene:show().  If you only use scene:show() you loose this.

Scope isn’t hard.  Just a couple of things to commit to memory.  Corona (well Lua) is a one pass compiler.  That is it starts at the top and reads down your code once.  Other compilers like C++ are two pass.  The first time the learn all the variable names you are going to use and what they are defined as, then they go back and fill in anything that’s undefined.  Since Lua doesn’t do that second pass, if you reference a variable or function before it’s defined, it’s going to be nil.  So the basic rule:  define it before you use it is key to making Lua work for you.

The second part of scope is that things defined “local” can only be seen in the block they are defined in and any children blocks.  This means if you create an image object in scene:create and make it local in scene create:

function scene:create( event ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local image = display.newImage("somegraphic.png") &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local function doSomething() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; image.someNewProperty = true &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doSomething() end

then image is only known to scene:create() and it’s child function “doSomething”.  Other sibling functions like scene:show() can’t  see image.

To solve that, the solution is to declare image at a higher level block, i.e. the module’s main chunk:

local image function scene:create( event ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; image = display.newImage("somegraphic.png") &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local function doSomething() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; image.someNewProperty = true &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doSomething() end

Notice that image was declared outside of the scene:create() function, but it didn’t get a value until inside scene:create().  It’s still visible to doSomething, but now it’s visible to scene:show() also.  However doSometthing is still limited to scene:create().  If you want that function to be visible to anything in the scene, you can do:

local image &nbsp; local function doSomething() &nbsp;&nbsp;&nbsp; image.someNewProperty = true end &nbsp; function scene:create( event ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; image = display.newImage("somegraphic.png") &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doSomething() end

now doSomething can be called from scene:create, scene:show or any function in the main chunk defined after it.

Hope this helps

Rob

Great info! I just started learning about this while running through the “Attack of the Cuteness” tutorial on the Udemy lecture by Jay. Going into further detail about how it works has really helped. Thanks Rob =D.

For the longest I was trying to figure out how to call my variables/objects that were inside functions. It was frustrating, so I just started making everything I wanted to be called a local variable outside of functions instead of throwing it into a function lol. Now I could better manage and organize my code. Appreciate the help.

Rob, I took my code out of composer and built for Android, but I still get the Runtime Error on my device. What I don’t understand is it’s saying floor1 is a nil value. “floor1” is a local variable that isn’t placed into a function. It’s in the main chunk. I’m gonna send the code in a PM (I’d rather not post it for everyone to see). Would you mind looking at it?

EDIT: There doesn’t seem to be an option to PM you on your page. How else can I show you?

Here is the top part of my code, up until floor1:

– Add physics

local composer = require( “composer” )

local gameUI = require(“gameUI”)

local ragdogLib = require “ragdogLib”;

local physics = require(“physics”)

– physics.setDrawMode(“hybrid”)

– physics.setDrawMode(“debug”)

physics.setDrawMode(“normal”)

physics.start()

physics.gravity = 15

– Forward references

local myPlayer

– Set Variables

local xMin = display.screenOriginX

local yMin = display.screenOriginY

local xMax = display.contentWidth - display.screenOriginX

local yMax = display.contentHeight - display.screenOriginY

local _W = display.contentWidth

local _H = display.contentHeight

local centerX = display.contentCenterX

local centerY = display.contentCenterY

local rand = math.random

local randColor = math.random(0, 255)/255

local dragBody = gameUI.dragBody

–[[local background = display.newImageRect(“bg1.png”, display.contentWidth, display.contentHeight)

background.x = display.contentWidth*0.5

background.y = display.contentHeight*0.5

]]–

– Let’s set the level up here

local background = display.newImage(“full-background.png”, centerX, centerY)

background.x = _W/2

background.y = _H/2

local floor1 = display.newImage("/images/Items/springboardUp.png", 80, 30)

floor1.x = 400

floor1.y = centerY + 80

floor1:setFillColor(0, 0, 1)

physics.addBody(floor1, “kinematic”, {radius = 10})

floor1.rotation = 50

floor1.name = “floor1”

floor1.isPlatform = true

The error is where floor1.x is defined.

floor1 is only called one more time… and that’s in a function to transition floor1 back and forth across the screen. Here’s the code for that section:

function movePlatform2()

    transition.to( floor1, {time = 5000, x = 400, onComplete = movePlatform } )

end

function movePlatform()

transition.to( floor1, {time = 5000, x = 40, onComplete = movePlatform2 } )

end

floor1 will remain a nil value if you don’t successfully create a display object. It’s possible that the problem lies with the line of code where you create the display object using display.newImageRect - double-check the path to your image file, including capitalization. Also, get rid of the slash at the beginning of your image file string ("/images/items/springboardUp.png") - it definitely isn’t necessary, and it might actually be the cause of your problem.

Good luck!

I have my PM’s turned off because too many people want to get direct help.  These are community forums and frequently the other community members can provide better solutions than Brent and I can. 

Rob