Reputation: 75
I'm just learning lua and love2d and I am trying to make an example game to get familiar. I'm following goature's tutorial on youtube and am using his states system to navigate the game. I finished writing the example code for the menu and decided I would like to be able to get back to the menu from the game. The problem is that the game will not load the game state a second time and instead gives me a gray screen. This should be the relavant code.
From the root file main.lua
function clearLoveCallbacks()
love.draw = nil
love.joystickpressed = nil
love.joystickreleased = nil
love.keypressed = nil
love.keyrelease = nil
love.load = nil
love.mousepressed = nil
love.mousereleased = nil
love.update = nil
end
states = {}
function loadState(name)
states = {}
clearLoveCallbacks()
local path = "states/" .. name
require(path .. "/main")
load()
end
function load()
end
function love.load()
loadState("menu")
end
From the menu main.lua
function load()
love.graphics.setBackgroundColor(190, 190, 190, 255)
imgPlay = love.graphics.newImage("Textures/start.png")
imgPlayOn = love.graphics.newImage("Textures/start_on.png")
imgexit = love.graphics.newImage("Textures/exit.png")
imgexitOn = love.graphics.newImage("Textures/exit_on.png")
buttons = {
{imgOff = imgPlay, imgOn = imgPlayOn, x = 400, y = 300 - 64, w = 256, h = 64, action = "play"},
{imgOff = imgexit, imgOn = imgexitOn, x = 400, y = 300 + 64, w = 256, h = 64, action ="exit"}
}
end
function love.mousepressed(x, y, button)
if button == 1 then
for k,v in pairs(buttons) do
local ins = insideBox(x, y, v.x - (v.w/2), v.y - (v.h/2), v.w, v.h) -- must use v. for the rest of the arguments except the first 2 because that x and y defined in arguments of the function
if ins then
if v.action == "play" then
loadState("New_Game") -- loads new game for some reason if i load the menu state from game it won't load the game a secound time
elseif v.action == "exit" then
love.event.quit() -- love2d function to quit
end
end
end
end
end
And from the New_Game main.lua
function load()
require("States/New_Game/entities")
love.graphics.setBackgroundColor(255,255,255,255)
ents.startup()
--local newEnt= ents.Create("new_ent", 128, 128)
ents.Create("enemy_base", -math.random(128, 256), 128)
end
function love.keypressed(key, unicode)
if love.keyboard.isDown("escape") then
loadState("Menu")
end
end
Upvotes: 0
Views: 523
Reputation: 473926
The code you have provided, as written, cannot do what you seem to want.
You seem to want to be able to call loadState
, and you want this function to load things into globals that effectively sets up a new "state".
Well, that might be fine... except that you are using require
to do the loading. And, unless Love2D changed how the function works, require
will only ever load a particular script once.
See, it is the execution of the script itself that is changing the state. It's defining a global load
function, which you call. It defines some other functions in the love
table. And so forth.
But this will only happen when the script is loaded and executed. And as previously said, require
will only do this the first time you require a new module.
Presumably, what you want is dofile
, not require
. But honestly, I'd suggest re-architecting your system to not rely on globals. Register which states you want up-front, but don't have them set global values. Instead, have each state define a table that contains its load
function. And the load
function should register its Love2D callbacks.
Your "states" would look more like this:
local ret = {}
--Executed only once.
local imgPlay = love.graphics.newImage("Textures/start.png")
local imgPlayOn = love.graphics.newImage("Textures/start_on.png")
local imgexit = love.graphics.newImage("Textures/exit.png")
local imgexitOn = love.graphics.newImage("Textures/exit_on.png")
local buttons =
{
{imgOff = imgPlay, imgOn = imgPlayOn, x = 400, y = 300 - 64, w = 256, h = 64, action = "play"},
{imgOff = imgexit, imgOn = imgexitOn, x = 400, y = 300 + 64, w = 256, h = 64, action ="exit"}
}
local function mousepressed(x, y, button)
if button == 1 then
for k,v in pairs(buttons) do
local ins = insideBox(x, y, v.x - (v.w/2), v.y - (v.h/2), v.w, v.h) -- must use v. for the rest of the arguments except the first 2 because that x and y defined in arguments of the function
if ins then
if v.action == "play" then
loadState("New_Game") -- loads new game for some reason if i load the menu state from game it won't load the game a secound time
elseif v.action == "exit" then
love.event.quit() -- love2d function to quit
end
end
end
end
end
function ret.load()
--Actual state setup.
love.mousepressed = mousepressed
love.graphics.setBackgroundColor(190, 190, 190, 255)
end
return ret
Your loadState
function also needs to change:
function loadState(name)
states = {}
clearLoveCallbacks()
local path = "states/" .. name
local state = require(path .. "/main")
state.load()
end
Oh, and I would advise you to ditch whatever tutorial you are "learning" from. It's teaching you terrible things. It involves way too much global usage, which is what led to this problem. If you're just learning Lua, then you are learning to use Lua very badly.
Upvotes: 1