Can crankIndicator:update() be called in a class?

I'm having trouble getting the crank indicator working.

If I run crankIndicator:start() near the top of my main.lua, and then call crankIndicator:update() in playdate.update() (after updateTimers()), the indicator appears.

but if I move crankIndicator:update() into the update function of one of my classes that extends 'sprite', I can't make the indicator appear.

I know crankIndicator:update() is/should be being called, because I have a print statement just before it.

Are you sure that your sprite's update() method is being called? It will need to be added to the display list via sprite:add() and have updatesEnabled set to true, and you'll need to call sprite.update() (note: dot, not colon) from playdate.update().

Yeah, all that is already done.

There is a print statement just before the call to crank indicator update , and I can see that being output.

Here's a very simple example if this helps you debug your own code somehow:

import "CoreLibs/graphics"
import "CoreLibs/ui"
import "CoreLibs/timer"

playdate.ui.crankIndicator:start()

function playdate.update()
		playdate.graphics.drawText("Hello World!", 50, 50)
		playdate.ui.crankIndicator:update()
		playdate.timer.updateTimers()
end

I'm having the same problem: crankIndicator inside a class extending sprite, and the crank is not shown.

I solved it with a messy workaround: I sent an event from the sprite to the main.lua asking to show the indicator.

main.lua extract

local showCrankAlertAskedForShowing = false

local function initialize()
	player = Player()

	playdate.ui.crankIndicator:start()
	player.onShouldCrankIndicatorChangeCallback = function (shouldShow) 
		showCrankAlertAskedForShowing = shouldShow
	end
end


function playdate.update()
	playdate.timer.updateTimers()
	gfx.sprite.update()

	if playdate.isCrankDocked() and showCrankAlertAskedForShowing then
		playdate.ui.crankIndicator:update()
	end
end

player.lua extract


class('Player').extends(gfx.sprite)

function Player:init() 
	-- i removed some standard code from this init
	
	self.onShouldCrankIndicatorChangeCallback = nil
end



function Player:update()
	Player.super.update(self)
	local crankRequired = false

	--I am hiding some code here

	if myCustomConditionThatRequiresCrank then
		crankRequired = true
	end

	--si la palanca esta escondida y deberia usarse, solicitamos que se envie la alerta
	if self.onShouldCrankIndicatorChangeCallback ~= nil then
		self.onShouldCrankIndicatorChangeCallback(crankRequired)
	end
end

I hope this helps

I did it by having a global variable in main.lua that I update from my player, then having the main update function show the indicator based on that.

Possibly not as good as your solution, due to updating a global variable every frame.

2 Likes

I found the issue, but not sure how to solve it without using a variable like others have mentioned.

Works:

function playdate.update()
    playdate.timer.updateTimers()
    gfx.sprite.update()
    playdate.ui.crankIndicator:update()
end

Doesn't Work:

function playdate.update()
    playdate.timer.updateTimers()
    playdate.ui.crankIndicator:update()
    gfx.sprite.update()
end

So this means that the crankIndicator can't be invoked from within the sprite update method. It needs to be invoked after the update loop. So, the easiest way is to use a global variable as indicated. The interesting thing is that the screen is being updated if you look at the simulator, but it must be being drawn "underneath" all the sprites on screen so you can't see the UI. This is why it must be called outside the update loop so its ui is drawn on top of all sprites. I'm still investigating the source code to see if there's a way around this issue.

1 Like

Good catch. I just added support for the crank indicator to my Plupdate toybox. This lets you display the indicator with a single call to Plupdate.showCrankIndicator() (no need to call playdate.ui.crankIndicator:start()) and that can be called from anywhere in your code, even a sprite update method.

1 Like