I did come up with a way after posting the above (couldn't let it go..) but didn't want to make things even more confusing. But since you've got it working on your end, here's what I came up with:
import "CoreLibs/graphics"
import "CoreLibs/sprites" -- for sprite.new(image) function
gfx = playdate.graphics
player = gfx.image.new(10,16)
gfx.pushContext(player)
gfx.drawText("@",0,0)
gfx.popContext()
playerSprite = gfx.sprite.new(player)
playerSprite:moveTo(200,120)
playerSprite:setZIndex(1)
playerSprite:add()
function makeSpotlightImage(r)
local image = gfx.image.new(2*r,2*r)
gfx.pushContext(image)
gfx.setColor(gfx.kColorBlack)
gfx.fillRect(0,0,image:getSize())
gfx.setColor(gfx.kColorClear)
gfx.fillCircleAtPoint(r, r, r)
gfx.popContext()
return image
end
spotlightRadius = 50
spotlight = makeSpotlightImage(spotlightRadius)
spotlightSprite = gfx.sprite.new()
spotlightSprite:setSize(400,240)
spotlightSprite:moveTo(200,120)
spotlightSprite:add()
spotlightSprite.draw = function()
local x,y = playerSprite.x, playerSprite.y
-- fill in previous bounds
gfx.setColor(gfx.kColorBlack)
gfx.fillRect(0,0,x-spotlightRadius,240)
gfx.fillRect(x+spotlightRadius,0,400-(x+spotlightRadius),240)
gfx.fillRect(0,0,400,y-spotlightRadius)
gfx.fillRect(0,y+spotlightRadius,400,240-(y+spotlightRadius))
spotlight:draw(x-spotlightRadius,y-spotlightRadius)
end
gfx.sprite.addDirtyRect(0,0,400,240)
local lastx, lasty = 200, 120
function playdate.update()
local x,y = playerSprite.x + math.random(-3,3), playerSprite.y + math.random(-3,3)
playerSprite:moveTo(x,y)
gfx.sprite.addDirtyRect(lastx-spotlightRadius, lasty-spotlightRadius, 2*spotlightRadius, 2*spotlightRadius)
gfx.sprite.addDirtyRect(x-spotlightRadius, y-spotlightRadius, 2*spotlightRadius, 2*spotlightRadius)
gfx.sprite.update()
lastx, lasty = x, y
end
Adding the dirty rect by hand is kind of weird, I know. You could probably use an empty sprite to do the same thing. And you could also use gfx.sprite.setClipRect()
to clip out all the scene drawing that should be covered by the spotlight effect.