-
Notifications
You must be signed in to change notification settings - Fork 1
Freezing
The freezing system gives you more control over when the stack can change. When it's active, this system will redirect stack changes into a buffer until it is unfrozen, after which it will copy the changes back into the original stack.
This is used automatically within sceneMan:event to prevent errors when scenes make changes to the stack. Without it, a scene might remove another scene from the stack and cause Scene Man to iterate over the wrong value or crash the entire system. Instead, stack changes only apply AFTER the event trigger has finished.
It is recommended that you manually trigger the freezing system in your game as shown below. This will prevent any stack changes until the next update cycle. This will be explained more in the following example.
--- main.lua
function love.update (dt)
sceneMan:freeze ()
sceneMan:event ("update", dt)
end
function love.draw ()
sceneMan:event ("draw")
sceneMan:unfreeze ()
end
Let's reuse the original example from the wiki. In this case, let's push the menu scene inside the game scene rather than inside love.load. You may encounter situations like this if you use immediate-mode GUI libraries like SUIT, where a player might push a button to transition into another scene.
--- main.lua
local sceneMan = require ("sceneMan")
function love.load ()
local initialRectW = 300
sceneMan:newScene ("game", require ("gameScene"), initialRectW)
sceneMan:newScene ("menu", require ("menuScene"))
-- Notice how we aren't pushing the menu scene here anymore?
sceneMan:push ("game")
end
function love.update (dt)
sceneMan:event ("update", dt)
end
function love.draw ()
local rng = math.random ()
sceneMan:event ("draw", rng)
end
--- gameScene.lua
-- (SNIPPET)
function thisScene:update (dt)
-- Now we are pushing the menu scene onto the stack inside the game scene
if yes ~= true then
sceneMan:push ("menu")
yes = true
end
end
Everything still works, right? What's the big deal? Well, let's modify the menu scene a bit to find out. Let's imagine that the menu scene now prints a test value that gets initialized inside the update event callback as shown below:
--- menuScene.lua
-- (SNIPPET)
local test
function thisScene:update (dt)
dt = dt
-- This is where our value gets its initial value, for demonstration purposes
if test == nil then
test = 24
end
end
function thisScene:draw (rng)
-- Renders some GUI items
love.graphics.setColor (1, 1, 1, 1)
love.graphics.print ("Hello world! This is a GUI!", 400, 400)
love.graphics.print ("Delta Time: " .. dt, 400, 425)
love.graphics.print ("RNG: " .. sceneMan.shared.rngValue, 400, 450)
-- But what happens when we try to perform math on this value???
test = test + 1
love.graphics.print ("Test: " .. test, 400, 475)
end
Now you'll probably be looking at a nasty error, right? Why is that? Well, when we pushed the menu scene onto the stack inside the update callback (within the game scene), the menu scene didn't get a chance to execute its update callback function. This means that the test value was never initialized, and it was nil when we tried to add to it within the draw callback function.
Thankfully, this is an easy fix! If we freeze the stack before the update event and unfreeze it after the draw event, the stack changes will only apply after the drawing event is finished. This ensures that the menu scene isn't actually added onto the stack until the next update trigger is called. Just modify your code like what's shown below:
--- main.lua
local sceneMan = require ("sceneMan")
function love.load ()
local initialRectW = 300
sceneMan:newScene ("game", require ("gameScene"), initialRectW)
sceneMan:newScene ("menu", require ("menuScene"))
sceneMan:push ("game")
end
function love.update (dt)
sceneMan:freeze () -- This will temporarily prevent stack changes while we trigger the events
sceneMan:event ("update", dt)
end
function love.draw ()
local rng = math.random ()
sceneMan:event ("draw", rng)
sceneMan:unfreeze () -- Now the stack changes can be applied!
end
Hooray! Looks like the program is working once again!