I made this resource queue in Love2D.
function GameState:queue(file, arg)
self.res.loaded = self.res.loaded + 1;
self.res.queue[self.res.loaded] = {f = file, t = game.getResourceType(file), id = self.res.loaded, s = arg};
game.log("Resource Queued: "..file);
return {f = self.res.loaded, t = game.getResourceType(file), id = self.res.loaded, s = arg};
end
function GameState:loadQueue(loader, post)
self.post = post or function() self.state = self.prevState end;
game.log("Loading Resource Queue...");
queueThread = love.thread.newThread("queue.lua");
queueChannel = love.thread.getChannel("queue");
local fonts = {};
for k, v in pairs(self.res.queue) do
if (not v or not v.f or not v.t) then goto continue end;
if (v.t ~= self.RESOURCE_FONT) then
queueChannel:push(v);
else
fonts[k] = v;
end
::continue::
end
for k, v in pairs(fonts) do
self.res.fnt[k] = love.graphics.newFont(v.f, v.s);
print("Loaded Resource: "..v.f);
end
queueChannel:push(table.size(self.res.queue)-table.size(fonts));
if (table.size(self.res.queue)-table.size(fonts) > 0) then
queueThread:start();
else
queueChannel = nil;
queueThread = nil;
return;
end
self.state = self.STATE_LOADING
end
The thread:
require "love.image"
require "love.audio"
require "love.sound"
require "love.timer"
queue = {};
img = {};
snd = {};
local queueChannel = love.thread.getChannel("queue");
local pop = queueChannel:pop();
while (type(pop) ~= "number" and pop) do
queue[pop.id] = pop;
pop = queueChannel:pop();
end
for k, v in pairs(queue) do
if (not v or not v.f or not v.t) then print("Resource Load Failed!"); goto continue; end;
if (v.t == 0) then -- image
img[k] = love.image.newImageData(v.f);
queueChannel:supply({data = img[k], t = 0, id = k, s = v.s});
end
if (v.t == 1) then -- sound
snd[k] = love.audio.newSource(v.f, "static");
queueChannel:supply({data = snd[k], t = 1, id = k, s = v.s});
end
::continue::
queue[k] = nil;
print("Loaded Resource: "..v.f);
love.timer.sleep(0.01);
end
queueChannel:clear();
queueChannel:push(true);
return;
Handling while loading resources:
if (self.state == self.STATE_LOADING) then
local e = queueThread:getError();
if (e ~= nil) then
print("Thread: "..e)
end
local r = queueChannel:peek();
if (type(r) == "table" and r and r.data and r.t) then
if (r.t == self.RESOURCE_IMAGE) then
if (r.s) then
love.graphics.setDefaultFilter(r.s, r.s);
end
self.res.img[r.id] = love.graphics.newImage(r.data);
end
if (r.t == self.RESOURCE_SOUND) then
self.res.snd[r.id] = r.data;
end
queueChannel:pop();
end
if (queueChannel:peek() == true and type(queueChannel:peek()) == "boolean") then
self.post();
game.log("Finished Loading Resources.");
end
end
If there's any bad habits, or anything that could be improved, please let me know.
goto
is evil. 2. Use better variable names thane
orr
. \$\endgroup\$goto
in some cases, for instance when jumping to a point within the same functiongoto
is being used.goto
is used a lot in huge codebases such as the Linux kernel. This goto is evil thing is cargocult originated by Dijkstra's infamous article Goto statement considered harmful. In this particular case,goto
is well used. It's the recommended way of implementingcontinue
in Lua, as the language lacks a nativecontinue
statement. \$\endgroup\$