Modules and scope

General discussion about LÖVE, Lua, game development, puns, and unicorns.
Post Reply
User avatar
mr_happy
Citizen
Posts: 84
Joined: Fri Mar 18, 2016 8:57 pm

Modules and scope

Post by mr_happy »

I'm trying to learn Lua and Love at the same time (at 2,000 MPH!) so sorry if this is a bit of a noob question...

Trying to make my code modular from the outset, I have functions related to map generation in the file map.lua, like this:

Code: Select all

map = {}
function map.createMap()
...
return map
I have stuff relating to the player in player.lua like so:

Code: Select all

player = {
  ["xPos"] = 10,
  ["yPos"] = 20
  }
return player
At the top of main.lua I have:

Code: Select all

local mapModule = require("map")
local playerModule = require("player")
So, when the game starts up I can call:

Code: Select all

mapModule.createMap()
Great, but what do I do if I want to access the player's position in map.lua, I'm guessing I wouldn't want to 'require' it in that module as well? (I assume 'require' reads in the source file at runtime??)

My other question is about global variables. In my game I'd like to make a small number of variables (well, really pseudo constants) accessible to all modules, for example the size of the map, MAPSIZE. Where's the best place to define such things? I read something about _G, the environment table but not sure if that's a good idea.
User avatar
MadByte
Party member
Posts: 533
Joined: Fri May 03, 2013 6:42 pm
Location: Braunschweig, Germany

Re: Modules and scope

Post by MadByte »

Code: Select all

map = {}
function map.createMap()
...
return map
You really should use " local map = {}" because otherwise "map" is a globally defined variable. ( same for the player).
Great, but what do I do if I want to access the player's position in map.lua, I'm guessing I wouldn't want to 'require' it in that module as well? (I assume 'require' reads in the source file at runtime??)
Basically what I would do is finding a system which handles multiple modules (the map/level and the player) and then add methods to both to interact with each other. e.g

Code: Select all

local GameState = {}

local map = require("map")
local player = require("player")
local enemy = require("enemy")

function GameState:init()
  local x, y = map:getPlayerSpawn()
  player:setPosition(x, y)
end



function GameState:update(dt)
  player:update(dt)
  map:update(dt)
end


function GameState:draw()
  player:draw()
  map:draw()
end

return GameState
This way you just have to require both in the GameState and they can send informations to each other.
My other question is about global variables. In my game I'd like to make a small number of variables (well, really pseudo constants) accessible to all modules, for example the size of the map, MAPSIZE. Where's the best place to define such things? I read something about _G, the environment table but not sure if that's a good idea.
If you want to declare something global it's just importent that you make it visible by formatting your code as you already wrote (all uppercase e.g "MAPSIZE"). But e.g MAPSIZE shouldn't be a global value because you could send this informations as I descript in the example above.
User avatar
mr_happy
Citizen
Posts: 84
Joined: Fri Mar 18, 2016 8:57 pm

Re: Modules and scope

Post by mr_happy »

Thanks for the reply.
You really should use " local map = {}" because otherwise "map" is a globally defined variable. ( same for the player).
Doh, of course!

I haven't got a grip on methods in Lua yet - from what I read, ':' syntax is the same as passing 'self' to a normal '.' function but what is being passed in your example code? To me it just looks like you're calling the getPlayerSpawn() method in the map module. Does getPlayerspawn() have to be defined in map using the ':' notation?

Code: Select all

function GameState:init()
  local x, y = map:getPlayerSpawn()
  player:setPosition(x, y)
end
Thanks again, I'm sure it will 'click' shortly :D
User avatar
MadByte
Party member
Posts: 533
Joined: Fri May 03, 2013 6:42 pm
Location: Braunschweig, Germany

Re: Modules and scope

Post by MadByte »

Thanks again, I'm sure it will 'click' shortly :D
It will for sure. :cool:
I haven't got a grip on methods in Lua yet - from what I read, ':' syntax is the same as passing 'self' to a normal '.' function but what is being passed in your example code? ... Does getPlayerspawn() have to be defined in map using the ':' notation?
No it doesn't have to be defined with ":" but it can. It passes as you already said "self" to the arguments. Here is what the method would look like:

Code: Select all

-- The "syntax sugar" way
function map:getPlayerSpawn()
  return self.playerSpawn.x, self.playerSpawn.y -- Assuming that these values already has been created somewhere, somehow.
end

-- Following methods equals the previous one but dont use the : notation and passes self "manually" instead
function map.getPlayerSpawn(self)
  return self.playerSpawn.x, self.playerSpawn.y
end

map.getPlayerSpawn = function(self)
  return self.playerSpawn.x, self.playerSpawn.y
end
Thats all the difference and it's up to you which way you use to write it.
Sorry for bringing that up with using self, I always forget that it is something I also had to learn first.
User avatar
Roland_Yonaba
Inner party member
Posts: 1563
Joined: Tue Jun 21, 2011 6:08 pm
Location: Ouagadougou (Burkina Faso)
Contact:

Re: Modules and scope

Post by Roland_Yonaba »

mr_happy wrote:My other question is about global variables. In my game I'd like to make a small number of variables (well, really pseudo constants) accessible to all modules, for example the size of the map, MAPSIZE. Where's the best place to define such things? I read something about _G, the environment table but not sure if that's a good idea.
May I suggest to avoid globals and use something like this (this is a pattern I am always using). Create a file where you will define all relevant constants you will need. And require this file at the top of each module which is like to use any of these constants.

Code: Select all

--file constants.lua
local constants = {}
constants.MAPSIZE = 500
constants.GRAVITY = 9.81
constants.ATMPRESSURE = 101300
-- etc etc ...

return constants
Then, in each single module where you will need any of these constants, require the file constants.lua

Code: Select all

local constants = require 'path.to.constants'
local MAPSIZE = constants.MAPSIZE
-- etc etc
User avatar
T-Bone
Inner party member
Posts: 1492
Joined: Thu Jun 09, 2011 9:03 am

Re: Modules and scope

Post by T-Bone »

If you're going to use those constants pretty much everywhere, why not make them globals? That's what globals are meant for, aren't they?

If I has lots of global constants, I'd create a file called "constants.lua" where I'd define a global table called "constants" and just require it once in main.lua. Then you can always refer to constants.map_size or whatever. Easy to understand, easy to use, and very little code.
User avatar
mr_happy
Citizen
Posts: 84
Joined: Fri Mar 18, 2016 8:57 pm

Re: Modules and scope

Post by mr_happy »

Roland_Yonaba wrote: May I suggest to avoid globals and use something like this (this is a pattern I am always using). Create a file where you will define all relevant constants you will need. And require this file at the top of each module which is like to use any of these constants.
Thanks for the suggestion - I've used a similar tactic with other programming languages in the past.
T-Bone wrote: If I has lots of global constants, I'd create a file called "constants.lua" where I'd define a global table called "constants" and just require it once in main.lua. Then you can always refer to constants.map_size or whatever. Easy to understand, easy to use, and very little code.
Seems sensible (and easy :D) - I need to get used to the Lua way of things...
User avatar
Kingdaro
Party member
Posts: 395
Joined: Sun Jul 18, 2010 3:08 am

Re: Modules and scope

Post by Kingdaro »

I'll add that, I understand the reason for the "locals only" approach when using Lua, but in my opinion it's really just not worth it a lot of the time. I've never bothered. I always just define my game classes/objects as global variables and require them all in main.
User avatar
T-Bone
Inner party member
Posts: 1492
Joined: Thu Jun 09, 2011 9:03 am

Re: Modules and scope

Post by T-Bone »

The one big benefit that I see with having a local require at the top of each file that uses something, is that for people reading only this file it will be more clear where things come from. If you're using globals, I'd strongly recommend to make it as easy as possible to find where these globals are defined. For example, if you have a global called "constants" it should be defined in "constants.lua".
User avatar
zorg
Party member
Posts: 3444
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Modules and scope

Post by zorg »

To me, using locals is straightforward, since they don't leak out of the file (== chunk) they are defined in, and requiring in data in one or more files really doesn't cost much more than accessing a table (after it was required once already, that is), plus i seldom can keep the amount of state in my head all the time, so compartmentalization is useful... that said, everyone's free to do things how they want to :3
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
Post Reply

Who is online

Users browsing this forum: No registered users and 97 guests