ui.crankIndicator:draw() just shows a white silhouette instead of the animated sprite

, ,

How's it going everybody? Thank you for reading in the first place.

I'm developing my first game, Kazoku, and I wanted to implement the usage of ui.crankIndicator:draw(). I know there's been a few issues and workarounds, such as using a Global variable in the logic to call crankIndicator from the main.lua file and such.

I've tried all of that, and while it all seems to be looking quite similar to the solutions provided, the problem I am having is that the crankIndicator is being show, but just a white background silhouette, like this:

All the imports were already done in the main.lua file, as well as necessary consts for shortening

local pd <const> = playdate
local gfx <const> = pd.graphics
local spr <const> = gfx.sprite
local img <const> = gfx.image
local ui <const> = pd.ui

For you reading to have an idea of my code, the parts using the crankIndicator and/or the playdate.update() and Sprite:update() methods are the following:

  1. I use this custom function to call the ui.crankIndicator:draw(), in a common_functions.lua file
function startUseCrankAnimation()
	print('Crank indicator being drawn')
	ui.crankIndicator:draw()
end
  1. I call this function in the main.lua file based on a global variable, PLAYER_OOB (out of bounds), for the crankIndicator to appear when the character is out of screen. I paid attention to calling any crankIndicator updates AFTER the graphics.update(), as seen below.
function pd.update()
    spr.update()
    pd.timer.updateTimers()

    global.currentScreen.update()
    Message.update()

    if PLAYER_OOB == true then
        startUseCrankAnimation()
    end
end

initGame()
  1. I set the global PLAYER_OOB value based on the player's position, from the player.lua (sprite) file, read as self.x and self.y, if out of bounds (out of screen limits actually), PLAYER_OOB is set to true, then as seen in step #2, the startUseCrankAnimation() is called per frame as long as player stays out of the screen, which calls ui.crankIndicator:draw() as seen in step #1.
function Player:move()
    *Also does some other input things to move the sprite and such*

    PLAYER_OOB = false

    *self.oobCoords.top, .bottom, .left, .right being the screen values taken from a custom table I initialize with the Player sprite*

    if (self.y < self.oobCoords.top) or (self.y > self.oobCoords.bottom) then
        PLAYER_OOB = true
    end
    if (self.x < self.oobCoords.left) or (self.x > self.oobCoords.right) then
        PLAYER_OOB = true
    end
end


Then I call Player:move() in the Player:update() method:

function Player:update()
    if GAMEMODE == 1 then
        self:move() -- Here
    else
        self:onDisappear()
	end
end

That's pretty much all I use, however the crankIndicator still shows the white silhouette only, so I am kinda stuck here. I tried taking a look at the most recent SDK version's official Inside Playdate docs but I think it ain't really well explained, the crankIndicator related info there is really short and doesn't really get into how it works under the hood.

I also tried running the game both in the Simulator as well as Physical console, same results.

Any help is much appreciated!

Also, please let me know if you need any additional info, pics, lines, file previews, etc.

Thanks in advance, and have a great week!

Are you setting the draw mode with gfx.setImageDrawMode anywhere in your code? That looks like what happens when the crank indicator is drawn with kDrawModeFillWhite.

What happens if you set it back to the default mode by calling gfx.setImageDrawMode(gfx.kDrawModeCopy) immediately before ui.crankIndicator:draw()?

1 Like

Oooooooh, boy that did the trick!

Indeed, I had been calling some other setImageDrawModes in some other parts of the code, and I completely forgot the crankIndicator was being treated as a sprite, or similar.

Thank you very much for your time writing, and helping out with finding a solution :slight_smile: