How does setBackgroundDrawingCallback work with Tilemaps and setDrawOffset?

I'm creating a sidescroller where the "camera" follows the player. I am setting the drawOffset in my updated loop after the player moves.

gfx.setDrawOffset(offsetX, offsetY)

I have a tilemap I set to the background. The following code works just fine for drawing the background, but it draws the entire tilemap:

gfx.sprite.setBackgroundDrawingCallback(
	function( x, y, width, height )
		tilemap:draw(offsetX, offsetY)
	end
)

How do I get the tileMap to only draw the visible part on the screen? I've tried the following code and it produces erratic results where the background is shifted and scrolls super fast.

gfx.sprite.setBackgroundDrawingCallback(
	function( x, y, width, height )
		tilemap:draw(offsetX, offsetY, -offsetX + x, -offsetY + y, width, height)
	end
)

I can't seem to find any good documentation on how to draw the tilemap in the background as just the visible part of the tilemap. Is there some translation between tile coordinates and world coordinates I'm missing? Any help would be greatly appricated! Thanks!

Sorry for the late reply--it's been a little busy over here! :sweat_smile: An odd thing about setBackgroundDrawingCallback() is that the sprite it creates ignores the global draw offset. (The source is in the SDK in CoreLibs/sprites.lua if you haven't seen it, might be useful to check it out.) We mention this in the docs but it's easy to miss:

The background sprite ignores the drawOffset, and will not be automatically redrawn when the draw offset changes; use playdate.graphics.sprite.redrawBackground() if necessary in this case.

Shifting by the offset in the callback should work, as long as you're invalidating the background sprite when you change the offset so that it knows to redraw. But an easier way to do this is just create a sprite for the background, give it a low Z index, then set the tilemap on it:

bg = gfx.sprite.new()
bg:setZIndex(-32767)
bg:setTilemap(tilemap)
bg:setCenter(0,0)
bg:moveTo(0,0)
bg:add()