tsteinholz wrote:Would game states really be useful for levels in a large game?
Yes and even necessary if you don't want to loose your sanity, in my opinion.
I've recently did this:
Code: Select all
-- state.lua
-- this is a function that takes the name of a file, including it's path
-- and returns the environment of the values defined within.
-- This environment is table containing everything that was in the lua file
function loadState( filename )
-- first we create an empty environment with an index metamethod on the
-- global environment.
-- That way you can read variables from the global environment, as long
-- as the variable isn't defined in our new environment.
-- This is useful to gain access to functions like print and also ensures
-- that no variables in the global environment are overwritten.
local env = setmetatable( {}, { __index = _G } )
-- we load the file as a function
local ffunc = love.filesystem.load( filename )
-- checking if everything went right
if not ffunc then error( err ) end
-- we set the environment of our new function to our new environment.
setfenv( ffunc, env )
-- we execute the function to populate the environment with the files contents
ffunc()
return env
end
states = {} -- this is the table that holds all your environments
-- iterating over a directory containing all our state scripts and then
-- assigning their environments to our states table indexed under the
-- files name with no suffixes.
-- (The way it is done here it only looks for filenames without
-- spaces or special characters.)
for _, v in pairs( love.filesystem.getDirectoryItems"states" ) do
local name = v:match"^(%w+).lua$"
if name then
states[name] = loadState( "states/" .. v )
-- states["title"] = loadState( "states/title.lua" )
end
end
-- The function to change the state of the program.
-- Unless noInit is given, the states init function is executed.
function setState( newState, noInit )
state = states[newState]
if not noInit then
state.init()
end
end
setState"title"
That way you would just have this in your main.lua:
Code: Select all
require"state"
function love.update( dt )
state.update( dt )
end
function love.draw()
state.draw()
end
And have single files for every state you have that look like this:
Code: Select all
function init()
-- stuff to be called when you initially set this state
end
function update( dt )
-- updating stuff
end
function draw()
-- drawing stuff
end
Then just call setState from your current state to change the state.
In case you want to access something from another state, you can do it through the global environment.
For example if you want to use the same font as the one from the title screen in the menu you can do this:
Code: Select all
-- menu.lua
function draw()
love.graphics.setFont( states.title.font )
end
Of course this technique can be nested and you can create a table of substates in one of your states,
for instance if you want to load up the levels of your game.
(This way you can set an index metamethod to your game state, to have access to functions and variables
that are required by all levels - like hud drawing functions etc.)
I hope this helps.
Maybe you don't understand how all of this works yet, if so - I really recommend reading up on the stuff that
might seem alien to you, especially metatables.
Lua is
very flexible, and if you don't know Lua well you're likely to programm in an unnecessarily complicated way.
Even though your code will work it will be much harder to maintain, so if you invest a little time upfront to learn about Lua's strengths
it will pay off in the future.