Quick and Dirty Asset Caching
Posted on August 03, 2016 by Donny Lawrence
My love2d game has a lot of assets. When I first started writing it, I didn’t pay much attention to “best practices” when it came to performance. Eventually I started to try and optimize.
One of the first things I noticed when reading the docs for
love.graphics.newImage was this:
Apparently, love2d doesn’t automatically cache images if they’ve already been loaded once, instead opting to read from disk each time. That’s fine if your disk access speed is fast enough, but for those with slow computers, it causes the game to chug. I saw similar issues with other file loading methods like
love.graphics.newFont. This seemed like an obvious thing to tackle in my project, and a solution ended up being pretty simple.
Thanks to the power of Lua, I didn’t even have to rewrite any code in order to fix the issue. I just created a new small module that “overwrote” some of the built in asset loading functions.
I started it with this, which allowed me to safely overwrite the built in functions with my own, while still being able call the originals.
local new_image = love.graphics.newImage
I was then able to drop in my replacement. It first checks if the name of the image is not a string, in case I’m trying to make an image using
ImageData. If it IS a string, and the image can’t be found in the cache, it loads it using the
new_image function that is actually the original
love.graphics.newImage. After that, it returns the image, simply grabbing it from the cache if it was already there.
local function newImage(name, ...) if type(name) ~= "string" then return new_image(name, ...) end if cachedImages[name] == nil then print("Loading image " .. name) cachedImages[name] = new_image(name, ...) end return cachedImages[name] end
Finally, I pointed
love.graphics.newImage at my newly created function. This made it so all of my existing code would automatically point to this new function.
love.graphics.newImage = newImage
This provided me with a large performance boost with very little work. I wrote similar functions that handled fonts as well, since they can be cached in a similar way. I have put up a gist here that contains the full module. All you need to do in order to use it is put
require "autocache" at the top of your main.lua.
A full example, which offers a better look at the performance increase, can be found here.