The SDK provides a convenience for drawing a background via
playdate.graphics.sprite.setBackgroundDrawingCallback(drawCallback). However, there is no documented method for removing it once set. I can achieve the result I'm after by setting it to a no-op function (
function() end) but that feels like a hack. Given that it's a callback, I expect to be able to just set it to
nil, as most executors of optional callbacks will check for
nil before attempting to call them. However, calling
setBackgroundDrawingCallback(nil) results in a runtime crash.
I'm honestly not sure if this is a bug, a feature request, or just a misuse of the API on my part, so please let me know if this belongs under another topic. My use case is setting a background for various levels, but sometimes a background isn't needed and I'm looking for the recommended way to clear it.
This method is often misunderstood as being a little more magical than it really is; all it does is create and configure a new sprite, and assigns
drawCallback to the new sprite's drawing callback. (it's defined in
CoreLibs/sprite.lua, and actually the entire source is right in the documentation if you would like to see what it does (See: Inside Playdate).
The newly-created sprite is returned from the function, so to remove it you can call
local bgSprite = playdate.graphics.sprite.setBackgroundDrawingCallback(drawCallback)
That said, I think you're right that passing
nil should remove a previously-set background drawing callback. Looking at this also made me realize that if this method is called more than once, you'll end up with multiple background sprites, which feels like a bug to me. I'll file an issue and get a fix ready for this stuff as soon as possible!
Thanks Dan, that's clarifying. And I apologize, I should have dug a little deeper to check my assumptions. In fact, I did go read the docs, and the main documentation (in bright white text) actually supported my assumption that this would just configure the inner draw loop for the background object. I then glossed over the implementation details section, which would have corrected my seemingly reinforced but ultimately incorrect understanding.
That said, the behavior does go somewhat against my expectations! I think naming plays a part in that, because the side effect of creating a new sprite instance is non-obvious. My mental model was that this would set, overwrite, and hopefully "unset" the background drawing routine for a singular, static background object. The only "magic" I assumed was that the background object would live outside of the standard sprite list, as a singular special-case object which you could update the drawing routine for at any time.
Even if the functionality still manifests as a regular sprite, updating the behavior to avoid creating multiple instances, and to support passing
nil (either to remove it, or at least result in a no-op draw handler that appears like a cleared background) sounds like an improvement. Thanks again!
I agree that the naming of the method suggests the usage you were expecting, and that's how it should behave.
I think this will be the new implementation, if you want to replace the implementation in CoreLibs before it makes it into an SDK release:
if drawCallback == nil then
if bgsprite ~= nil then
bgsprite = nil
if bgsprite == nil then
bgsprite = gfx.sprite.new()
bgsprite.draw = function(s, x, y, w, h)
drawCallback(x, y, w, h)
I just ran into the same problem: Calling setBackgroundDrawingCallback with a nil value will lead to problems - #2 by matt
So I would like to know what the status of this issue is.
If the implementation is not changed, then at least the documentation (and maybe examples using this) should reflect that the result of the call can and should be used (to remove it and avoid having multiple backgrounds).
I feel like that is not obvious without looking at the implementation (which few people probably do).