Page 1 of 1

Is scene management a good idea?

Posted: Fri Jun 23, 2023 2:35 pm
by Dangerous beetle
Hi, In my new game I am using a scene management function by nagi(a YouTuber I got inspired from to make games in love2d), He used an extremely simple and good scene management you can search him in youtube and watch his love2d tutorials to know more.


I just wanted to know if it is worth using it, what are it's disadvantages and is there any more better way but as easy as that one.

The scene management function is:
function changeScene(nextScene)
Scene=require("src/"..nextScene)
end


Re: Is scene management a good idea?

Posted: Fri Jun 23, 2023 3:08 pm
by darkfrei
It's nice until you change the scene, you cannot require the same scene twice, the preloaded scene will be used, you cannot restore the default values from it.

Re: Is scene management a good idea?

Posted: Fri Jun 23, 2023 3:42 pm
by Dangerous beetle
Yes you're right it is ok for mini-games but for big projects I should not use it...but is there any alternative for that which is better??

Re: Is scene management a good idea?

Posted: Fri Jun 23, 2023 4:34 pm
by pgimeno
I wouldn't even call that a scene management function. It's a loader.

In the sense that you mean, scenes are more often called gamestates. "Scene" is a term more commonly used for a tree of transformations and sprites, and is less commonly used in 2D (such as love) than in 3D (such as amulet or irrlicht). Look for gamestate libraries, there are a number of them out there. One of the most famous gamestate management libraries is probably hump. I like to keep gamestate management very simple (but not just a loader), but for certain projects more sophisticated management is necessary.

In a basic gamestate manager, the idea is that the events such as love.draw, love.update, love.keypressed etc. call the corresponding events of the currently selected gamestate (or call it screen, if you want). Some gamestates may not need certain events, so you usually have to protect the calls against the case that the event does not exist in that gamestate.

For example, in a simple gamestate manager, a game with three gamestates (menu, game, game over) could look like this:

states.lua:

Code: Select all

local states = {}

function states.changeTo(newState)
  states.state = newState
end

return states
main.lua:

Code: Select all

local states = require('states') -- load the states library
states.menu = require('menu') -- load a file with the definition of the menu state
states.game = require('game') -- load a file with the game itself
states.gameover = require('gameover') -- load a file with the definition of the gameover state

states.changeTo(states.menu) -- set the menu state at start


-- Let's imagine that no gamestates use any events other than update, draw, and keypressed

function love.keypressed(...)
  if states.state.keypressed then -- if the keypressed event exists in the current state
    states.state.keypressed(...) -- call it with all arguments received
  end
end

function love.update(dt)
  if states.state.update then -- if the update event exists in the current state
    states.state.update(dt) -- call it
  end
end

function love.draw()
  if states.state.draw then -- if the draw event exists in the current state
    states.state.draw() -- call it
  end
end
menu.lua:

Code: Select all

local states = require('states')
local menu = {}

function menu.keypressed(k, s)
  -- key "1" starts the game
  if s == "1" then
    states.changeTo(states.game) -- set the "game" state
  end
end

function menu.draw()
  love.graphics.print("Menu\nPress 1 to start game\nThere are no other options!")
end

return menu
game.lua:

Code: Select all

local states = require('states')
local game = {}

local time = 0

function game.keypressed(k, s)
  if s == "space" then
    _G["WON"] = true -- won the game
    states.changeTo(states.gameover)
  end
end

function game.update(dt)
  time = time + dt
  if time >= 2 then
    _G["WON"] = false -- set the WON global to false
    states.changeTo(states.gameover)
  end
end

function game.draw()
  love.graphics.print("Press space in less than two seconds to win!")
end

return game
gameover.lua:

Code: Select all

local states = require('states')
local gameover = {}

local wonlost
if _G["WON"] then
  wonlost = "won"
else
  wonlost = "lost"
end

function gameover.keypressed(k, s)
  if s == "escape" then return love.event.quit() end
end

function gameover.draw()
  love.graphics.print("You " .. wonlost .. "!\nPress escape to exit")
end

return gameover
That's a VERY barebones example. You may want to add events to reinitialize the state (like the counter in the game screen, in order to be able to play again without restarting the whole thing). Also events to load state-specific assets. Also events to pause and resume the current state, which you can use for example to pause/resume the game music. It's very flexible and you can add a lot of things with little effort.

Re: Is scene management a good idea?

Posted: Sun Jun 25, 2023 2:13 pm
by dusoft
Dangerous beetle wrote: Fri Jun 23, 2023 3:42 pm Yes you're right it is ok for mini-games but for big projects I should not use it...but is there any alternative for that which is better??
You can also check existing libraries such as Hump:
https://hump.readthedocs.io/en/latest/gamestate.html

Re: Is scene management a good idea?

Posted: Tue Oct 24, 2023 4:49 am
by Dangerous beetle
dusoft wrote: Sun Jun 25, 2023 2:13 pm
Dangerous beetle wrote: Fri Jun 23, 2023 3:42 pm Yes you're right it is ok for mini-games but for big projects I should not use it...but is there any alternative for that which is better??
You can also check existing libraries such as Hump:
https://hump.readthedocs.io/en/latest/gamestate.html
Thanks! I'll try it.

Re: Is scene management a good idea?

Posted: Tue Oct 24, 2023 4:50 am
by Dangerous beetle
pgimeno wrote: Fri Jun 23, 2023 4:34 pm I wouldn't even call that a scene management function. It's a loader.

In the sense that you mean, scenes are more often called gamestates. "Scene" is a term more commonly used for a tree of transformations and sprites, and is less commonly used in 2D (such as love) than in 3D (such as amulet or irrlicht). Look for gamestate libraries, there are a number of them out there. One of the most famous gamestate management libraries is probably hump. I like to keep gamestate management very simple (but not just a loader), but for certain projects more sophisticated management is necessary.

In a basic gamestate manager, the idea is that the events such as love.draw, love.update, love.keypressed etc. call the corresponding events of the currently selected gamestate (or call it screen, if you want). Some gamestates may not need certain events, so you usually have to protect the calls against the case that the event does not exist in that gamestate.

For example, in a simple gamestate manager, a game with three gamestates (menu, game, game over) could look like this:

states.lua:

Code: Select all

local states = {}

function states.changeTo(newState)
  states.state = newState
end

return states
main.lua:

Code: Select all

local states = require('states') -- load the states library
states.menu = require('menu') -- load a file with the definition of the menu state
states.game = require('game') -- load a file with the game itself
states.gameover = require('gameover') -- load a file with the definition of the gameover state

states.changeTo(states.menu) -- set the menu state at start


-- Let's imagine that no gamestates use any events other than update, draw, and keypressed

function love.keypressed(...)
  if states.state.keypressed then -- if the keypressed event exists in the current state
    states.state.keypressed(...) -- call it with all arguments received
  end
end

function love.update(dt)
  if states.state.update then -- if the update event exists in the current state
    states.state.update(dt) -- call it
  end
end

function love.draw()
  if states.state.draw then -- if the draw event exists in the current state
    states.state.draw() -- call it
  end
end
menu.lua:

Code: Select all

local states = require('states')
local menu = {}

function menu.keypressed(k, s)
  -- key "1" starts the game
  if s == "1" then
    states.changeTo(states.game) -- set the "game" state
  end
end

function menu.draw()
  love.graphics.print("Menu\nPress 1 to start game\nThere are no other options!")
end

return menu
game.lua:

Code: Select all

local states = require('states')
local game = {}

local time = 0

function game.keypressed(k, s)
  if s == "space" then
    _G["WON"] = true -- won the game
    states.changeTo(states.gameover)
  end
end

function game.update(dt)
  time = time + dt
  if time >= 2 then
    _G["WON"] = false -- set the WON global to false
    states.changeTo(states.gameover)
  end
end

function game.draw()
  love.graphics.print("Press space in less than two seconds to win!")
end

return game
gameover.lua:

Code: Select all

local states = require('states')
local gameover = {}

local wonlost
if _G["WON"] then
  wonlost = "won"
else
  wonlost = "lost"
end

function gameover.keypressed(k, s)
  if s == "escape" then return love.event.quit() end
end

function gameover.draw()
  love.graphics.print("You " .. wonlost .. "!\nPress escape to exit")
end

return gameover
That's a VERY barebones example. You may want to add events to reinitialize the state (like the counter in the game screen, in order to be able to play again without restarting the whole thing). Also events to load state-specific assets. Also events to pause and resume the current state, which you can use for example to pause/resume the game music. It's very flexible and you can add a lot of things with little effort.
Thanks, I saw some tutorials on scene management, I am going to use hump because I'm already familiar with that library. Thanks for replying!