Getting nil from gfx.image.new()

Unable to create a new image graphic to use with pushContext() or lockFocus(), keeps saying its acting on nil after initialising with:

local bgFabric = playdate.graphics.image.new(screenWidth, screenHeight)

Hard to say with this amount of info... but if you're declaring it as local are you accessing it in the same scope?

See the Basic Game example https://sdk.play.date/2.5.0/Inside%20Playdate.html#basic-playdate-game

OK so still couldnt get the gfx focus to work on its own but i did get it to work when writing and graphic to sprite, am I right in saying you need to write the graphic to a sprite to get it to appear if its not in the screen buffer?

This worked:

local backgroundImage = gfx.image.new(100,100)
gfx.lockFocus(backgroundImage)
gfx.fillCircleInRect(0, 0, backgroundImage:getSize())
gfx.unlockFocus()
backgroundSprite = gfx.sprite.new( backgroundImage )
backgroundSprite:add()

No, that's not a correct assertion.

well..... thats confusing.

Is there some actual game code examples, as the examples on the docs Inside Playdate are good but not really representative.

There's a whole folder at SDK/Examples. But I'd say that the Basic Example is very representative of recommended practices.

lockFocus() will allow you to draw to an image. But you still need to draw the resulting image to the screen. Are you drawing the image to screen after drawing into the image?

If you're using sprites then they will draw at whatever point you're calling sprite update. So they will draw over anything drawn manually straight to the screen before them. So the solution is to draw into the image used in the sprite background function.

OK, thanks for teh pointers. If there's any code that shows the background thing specificaly that would be useful. I guess im struggling with the difference between, drawing graphics, images and sprites and how they all work together.

It's in the Basic Game in the docs

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

gfx.sprite.setBackgroundDrawingCallback()

https://sdk.play.date/inside-playdate/#f-graphics.sprite.setBackgroundDrawingCallback

I'd encourage you to read through the graphics and sprite section of the SDK docs, it doesn't take long and will reduce frustration going forward

Ok thanks, I'll look elsewhere for help in future.

It's hard to tell without more context but I think that your main problem must be that playdate.graphics.sprite.update() erase the screen before drawing the sprites.

So if you try to draw a background and then have sprites moving above it, your background will not be shown. You either have to add your background as a sprite or use setBackgroundDrawingCallback.

When you do this, the sprite backgroundSprite now holds a reference to backgroundImage so it does not get released when the scope ends.

I suspect that your variable backgroundImage is freed by the garbage collector when you don't add it to a sprite (because it has nothing referencing it). Can you show more of your code?

Hello Ben! How's it going!

HELLO @AlexMay, sorry everyone, was on holiday.

@Daeke super useful thank you! I read the docs and noticed that the setBackGroundDrawingCallback actually results in a sprite which is why I was getting confused when getting told that that wasn't the case...

Think I probably just need to make sure I have references to things that need to persist rather than realying on drawing with graphics each frame :slight_smile:

The recommended way is to actually create sprites for everything (even for backgrounds). Then you add them to the sprite list with :add() and you don't have to worry about them being freed by GC.

1 Like

Awesome thanks for your help!

1 Like