Masking sprites?

I have some sprites that I want to fade in, individually. Is there a sprite draw mode that I can use where i can set opacity/blur/whatever you want to call it... So that i can draw the sprite once and then just affect the way it's plopped into the screen buffer? Or like, mask it using a dither pattern, so it's got transparent holes in it throughout the transition...

There are some ways i've found to do this;

  • during the transition, draw right into the display buffer/context rather than using the sprite, during the transition
  • re-draw to the sprite's image buffer, and let the regular sprite mechanisms take over the rest of the rendering pipeline...

Since the Playdate has a 1-bit screen, opacity does not make sense. Pixels are either black or white. If you want to fade in, try a scanline-type effect where the sprite is invisible on the first frame. Every frame, fill one line of the mask you want to use to display the final sprite. Other fade in effects could make sense.

I was thinking of opacity similarly to the way "alpha" is used as a parameter for playdate.graphics.setDitherPattern() or like playdate.graphics.setPattern(). Essentially using the dither pattern as a mask.

And you mention "one line of the mask", but what mask are you talking about? Is there one that can be applied at some point in the sprite rendering process? I can't seem to find that feature.

C API / Lua API
If using Pulp, you probably need to brute force it by creating frames to fade in and out.

Your post doesn't really answer my question.

I was asking about (for lua/c) if there's a way to have the internal sprite rendering apply a mask (or custom mask pattern, or "blur" as it is sometimes called in the docs) to the sprite as its being rendered to the display buffer.

The functions in that part of the documentation can be used to add/remove a 1-bit mask. The mask is just a bitmap. I forget if black or white is draw, but you use one color for the region you want to draw, and another for the region you want to be transparent.

For a fade in effect, you load the stand mask and clear the portion that has not faded in yet. Each frame, you clear less of the mask.

If you are asking about the sprite system as opposed to masking/drawing standard bitmaps, it is probably somewhere in the Lua documentation. The C documentation seems to assume knowledge of things written in the Lua docs at this point. Without checking, my guess would be that you can assign a masked bitmap to a sprite though.

I know that.

Per my original question, i know how to do this with direct gfx.xxx draw routines. I was asking if there was a way to do it within the sprite subsystem, during the internal process where all of the sprites are being rendered to the screen.

"Without checking, my guess would be that you can assign a masked bitmap to a sprite though." - That's exactly the thing i was asking about in the first place. I know how to do all of the rest of this.... THAT Is the thing I'm asking about.

Check out the following Lua functions:

  • playdate.graphics.sprite:setStencilImage(stencil, [tile])
  • playdate.graphics.sprite:setStencilPattern(level, [ditherType])
  • playdate.graphics.sprite:clearStencil()

edit: level is alpha, as in setDitherPattern(alpha, [ditherType]), I've filled a docs bug report about that.

At https://sdk.play.date/inside-playdate/#m-graphics.sprite.setStencilImage

I'm sorry I can't help in C land.

2 Likes

This seems like it should do what you want, but I am not really sure why it only dithers a tiny area.

import "CoreLibs/graphics"
import "CoreLibs/sprites"

local gfx <const> = playdate.graphics

local image = gfx.image.new(400, 240, gfx.kColorBlack)
local sprite = gfx.sprite.new(image)
sprite:moveTo(200, 120)
sprite:add()

playdate.display.setRefreshRate(1)

local level = 0.0
function playdate.update()
  sprite:setStencilPattern(level)
  gfx.sprite.update()
  level += 0.1
end

if you replace the image I have above with a real image it does the dithering you're after, but again - only in a small box.

1 Like

The second argument on setStencilPattern is for the dithering type, not tiling.

edit: I also tried setting a stencil image as well and use that with stencil pattern, including allowing tiling and... same problem. just a tiny part gets dithered / shown.

2 Likes

Oops. Sorry.

Anyway, I think we've found an omission/bug.

2 Likes

I forgot to set the tile flag on the image it creates for the stencil. :man_facepalming: At least it's an easy fix. :sweat_smile:

4 Likes

This is awesome! thanks!

3 Likes