Mixing sprite.update() and drawText()

Hi! What is the right way to use sprites together with "raw" graphics (eg, drawText(), drawCircleAtPoint(), etc)?

If I call drawText() followed by sprite.update(), then the text from drawText() does not appear:

import 'CoreLibs/graphics'
import "CoreLibs/sprites"
gfx = playdate.graphics

sp = gfx.sprite.spriteWithText('world', 100, 100)
sp:moveTo(250,120)
sp:add()

function playdate.update()
    gfx.drawText('hello',100,120)
    gfx.sprite.update()
end

However, if change the order (sprite.update() followed by drawText()), then both the raw text and the sprite appear:

import 'CoreLibs/graphics'
import "CoreLibs/sprites"
gfx = playdate.graphics

sp = gfx.sprite.spriteWithText('world', 100, 100)
sp:moveTo(250,120)
sp:add()

function playdate.update()
    gfx.sprite.update()
    gfx.drawText('hello',100,120)
end

Is sprite.update() implicitly clearing the screen or something?

I'm happy to just make everything a sprite, but I'm curious what is the right way to draw static text over a dynamic scene?

Thanks!

-Justin
Playdate SDK v2.0.1 on MacOS

Draw into an image using lockfocus/pushcontext and put that image on a sprite or use it as a sprite background.

See the basic game example in the docs, to see how to set up a sprite background.

https://sdk.play.date/inside-playdate/#basic-playdate-game

1 Like

Thank you! I'm happy to make everything a sprite. But I'm curious, are there cases where you'd mix sprites and non-sprites? Or is it basically always inadvisable to do "raw" calls to drawText() etc, because they don't play well with the sprite system?
Thanks!
-Justin

The sprite system can be a real time and performance saver. Once you use it you have to go all in for the reasons you've noticed. This is simply to ensure everything you do will benefit from the optimisations in the sprite system. So, sure, you can mix them but you have to use one sprite as the drawing canvas. But "raw" draw calls to the screen buffer are for without the sprite system.

Also, there are instances where you might not want to use the sprite system at all because of the overhead of processing. For example, it's generally quicker to manage particles manually and draw them manually rather than use sprites to manage them. You can simply have more of them by having your own light weight object rather than a sprite. Of course, if you want to have such particles alongside sprites then you're back to drawing them into an image that you're using as a sprite or background. (this is the approach we use for particles in Sparrow Solitaire).

In comparison:

  • Ball und Panzer Golf I don't use the sprite system at all.
  • in some puzzle games I use one sprite as my drawing canvas, to get benefits of partial screen refresh (only redrawing rows of pixels when they change)
  • Mole Hole I use minimal sprites so I can set and forget certain screen elements.

TL;DR: depends on your needs and design.

1 Like

Thank you for your thorough response! I appreciate the details and the background.
-Justin

Adding a bit to what Matt said: If you do have a lot of small sprites moving around it might be more efficient to skip its dirty rect handling and redraw the entire screen every frame with sprite.setAlwaysRedraw().

Also, what's going on when you mix sprites and normal drawing functions is the drawing functions mark those parts of the screen as dirty, then the next time you call sprite.update() it clears them to the background color and redraws the sprites that overlap them. That means anything that you draw manually before sprite.update() will be erased but drawing after the sprite.update() call won't be erased until the next playdate.update() cycle. Most of the time it's easier to just do that drawing in a sprite, as Matt suggested.

2 Likes

Thank you Dave. I really like knowing the "why" behind this observed behavior!
-Justin

2 Likes