Help Understanding Global Variables (How to not use them). *Very Confused

So I have developed a few games so far using Corona SDK, but in all of them I have used global variables to access variables throughout the program. Now I realize this is bad practice so in my next game I want to only use local. However, I do not really get how you do that.

My confusion is, for example, I always have a gameplay class (object oriented in a separate file) that has the background class, character class, enemy class, etc as properties. I store an instance of this gameplay class as a global so I can access everything in every class. (I think this is called a singleton or something). My trouble is that I can’t require the gameplay class in every class because then it would require the current file - recursion! Also wouldn’t it just make a new copy of the gameplay class?

Ex: if I try to access the character in the background class I would have to require the gameplay class which would just make another copy of the gameplay class. Also in the required gameplay class, the background class would be required again-> recursion occurs.

As you can tell I am very confused.

Hopefully that made sense and someone can explain.

Thanks,

David

To get your programming terms right, a singleton class is a class in which only one object is allowed to be created (yes, it’s becoming used to mean class of which only one object should exist or does exist, but I’m a programming purist :slight_smile: ). Whereas normally in classes you’d do something like this (don’t know how to do C++ highlighting in this forum, sorry):

[lua]

MyClass foo;

MyClass bar;

// Now foo and bar represent two completely different objects

[/lua]

In a singleton class, it’s configured such that the first instance you create actually uses the constructor, but the others just return the instance.

[lua]

MySingleton foo;

MySingleton bar;

// Foo and bar are both the same object

[/lua]

They’re usually implemented by making the “real” constructor private and the public constructor check for the existing instance or call the “real” constructor. You can read more about it here: http://en.wikipedia.org/wiki/Singleton_pattern.

Anyway.

I have had this very same problem before. You have a number of ways to solve it. First of all, you can make a pseudo-singleton class like so:

[lua]

local gameplay = {}

local gameplayBuilt = false

local gameplayInstance

function gameplay.new()

  local obj = {}

  setmetatable(obj, {__index = gameplay})

end

function gameplay:doThis()

end

function gameplay:doThat()

end

if gameplayBuilt then

  return gameplayInstance

else

  gameplayInstance = gameplay.new()

  gameplayBuilt = true

  return gameplayInstance

end

[/lua]

Now each file that require()-s this will get the same object.

You can also solve this by passing the gameplay object to any functions you need to access it in. This is the easier way, in my opinion.

[lua]

local cluck = {}

function cluck.doSomethingToGameplay(gameplay)

end

return cluck

[/lua]

There are no limitations to this approach (as in memory), because Lua treats tables as references instead of values. Thus, each time you modify a table from an arg list, you’ll also modify the original.

Code on, and eat plenty of mushrooms!

  • Caleb

Thanks for the response Caleb!

Just to be sure, in the gameplay class if I wanted to make a chuck object, I would require the chuck class in the function gameplay.new so that it is not required unless I am making a new gameplay object.

David.

P.S. Thanks for the info on singletons. :slight_smile:

Wow that 2nd option (passing in the gameplay as an argument) is magic. It took only 15 minutes and my code is now global free!!!

I didn’t realize that the parameters are references, not copies, so this makes a lot of sense to do.

Still a few memory leaks but they will be much easier to find without me having to worry about globals messing everything up.

Well thanks again, and I’ll let you know if I have anymore questions, if that’s ok with you.

David

We have a tutorial just for this question:   http://coronalabs.com/blog/2013/05/28/tutorial-goodbye-globals/

@davidgmonical:

Glad to help :slight_smile:

  • C

@Rob:

I read that tutorial trying to solve this problem, but I found it hard to relate to my project, as the example classes were very simple. If I spent a lot of time on it, I may have been able to figure it out, but why struggle when you have an awesome Corona community? :slight_smile:

@Claeb or anyone else

So everything is local now but there is one problem that seems to have arisen from the global to local conversion. It could be unrelated but I don’t remember it being there before…

When I explore the variables in Lua Glider after the game has ended and I have removed all the game display objects, timers, etc., there is a recursive _G variable. When I expand _G I get a lot of other variables (such as audio, transition, math, and other libraries) and another _G variable which has the same variables and another _G when I expand it. This continues on for a while, so I assume it is some sort of recursion.

Let me know if you have any thoughts.

If you don’t think it’s related I can post a new question too.

Thanks again and sorry for bugging you,

David

In Lua, the _G variable is a global variable that refers to itself. It’s global, so any globals checker will pick it up. Don’t know why Glider would have only picked it up now - perhaps you just didn’t notice :slight_smile:

This circumstance (_G being global) enables you to do this weird code thing (not that you’d ever want to :D):

[lua]

_G._G._G._G._G._G._G._G._G._G._G._G._G._G._G.display.newImage(“image.png”)

[/lua]

  • Caleb

Thanks again Caleb.

I did not know that _G could refer to itself, and I’m surprised I missed that earlier.

As long as it’s not an issue I guess it doesn’t matter.

David

To get your programming terms right, a singleton class is a class in which only one object is allowed to be created (yes, it’s becoming used to mean class of which only one object should exist or does exist, but I’m a programming purist :slight_smile: ). Whereas normally in classes you’d do something like this (don’t know how to do C++ highlighting in this forum, sorry):

[lua]

MyClass foo;

MyClass bar;

// Now foo and bar represent two completely different objects

[/lua]

In a singleton class, it’s configured such that the first instance you create actually uses the constructor, but the others just return the instance.

[lua]

MySingleton foo;

MySingleton bar;

// Foo and bar are both the same object

[/lua]

They’re usually implemented by making the “real” constructor private and the public constructor check for the existing instance or call the “real” constructor. You can read more about it here: http://en.wikipedia.org/wiki/Singleton_pattern.

Anyway.

I have had this very same problem before. You have a number of ways to solve it. First of all, you can make a pseudo-singleton class like so:

[lua]

local gameplay = {}

local gameplayBuilt = false

local gameplayInstance

function gameplay.new()

  local obj = {}

  setmetatable(obj, {__index = gameplay})

end

function gameplay:doThis()

end

function gameplay:doThat()

end

if gameplayBuilt then

  return gameplayInstance

else

  gameplayInstance = gameplay.new()

  gameplayBuilt = true

  return gameplayInstance

end

[/lua]

Now each file that require()-s this will get the same object.

You can also solve this by passing the gameplay object to any functions you need to access it in. This is the easier way, in my opinion.

[lua]

local cluck = {}

function cluck.doSomethingToGameplay(gameplay)

end

return cluck

[/lua]

There are no limitations to this approach (as in memory), because Lua treats tables as references instead of values. Thus, each time you modify a table from an arg list, you’ll also modify the original.

Code on, and eat plenty of mushrooms!

  • Caleb

Thanks for the response Caleb!

Just to be sure, in the gameplay class if I wanted to make a chuck object, I would require the chuck class in the function gameplay.new so that it is not required unless I am making a new gameplay object.

David.

P.S. Thanks for the info on singletons. :slight_smile:

Wow that 2nd option (passing in the gameplay as an argument) is magic. It took only 15 minutes and my code is now global free!!!

I didn’t realize that the parameters are references, not copies, so this makes a lot of sense to do.

Still a few memory leaks but they will be much easier to find without me having to worry about globals messing everything up.

Well thanks again, and I’ll let you know if I have anymore questions, if that’s ok with you.

David

We have a tutorial just for this question:   http://coronalabs.com/blog/2013/05/28/tutorial-goodbye-globals/

@davidgmonical:

Glad to help :slight_smile:

  • C

@Rob:

I read that tutorial trying to solve this problem, but I found it hard to relate to my project, as the example classes were very simple. If I spent a lot of time on it, I may have been able to figure it out, but why struggle when you have an awesome Corona community? :slight_smile:

@Claeb or anyone else

So everything is local now but there is one problem that seems to have arisen from the global to local conversion. It could be unrelated but I don’t remember it being there before…

When I explore the variables in Lua Glider after the game has ended and I have removed all the game display objects, timers, etc., there is a recursive _G variable. When I expand _G I get a lot of other variables (such as audio, transition, math, and other libraries) and another _G variable which has the same variables and another _G when I expand it. This continues on for a while, so I assume it is some sort of recursion.

Let me know if you have any thoughts.

If you don’t think it’s related I can post a new question too.

Thanks again and sorry for bugging you,

David

In Lua, the _G variable is a global variable that refers to itself. It’s global, so any globals checker will pick it up. Don’t know why Glider would have only picked it up now - perhaps you just didn’t notice :slight_smile:

This circumstance (_G being global) enables you to do this weird code thing (not that you’d ever want to :D):

[lua]

_G._G._G._G._G._G._G._G._G._G._G._G._G._G._G.display.newImage(“image.png”)

[/lua]

  • Caleb

Thanks again Caleb.

I did not know that _G could refer to itself, and I’m surprised I missed that earlier.

As long as it’s not an issue I guess it doesn’t matter.

David