0
votes

If anyone is familiar with knife.timer on Lua, could you please look at my code and tell me what I have out of order?

I'm hoping to do two things:

  1. have a countdown timer that ticks down every second and
  2. have a timer that after six seconds begins blinking my characters for 3 more seconds before changing state.

With the following code, my countdown timer starts at 9 but gets well into the negative tens. My characters begin to blink after what feels like 4 seconds, and continue blinking for a few seconds after changing state.

I have Timer:update(dt) in main, so I'm not sure why the timing is off. And I thought the finish would not call the change state function until the characters' 16 iterations of blinking were done.

function PlayerPilotState:update(dt)
    self.player.currentAnimation:update(dt)
    Timer.every(1, function()
        self.timer = self.timer - 1
    end)
    
    Timer.after(6, function()
        Timer.every(0.2, function() 
            self.player.blinking = not self.player.blinking
            self.player.otherPlayer.blinking = not self.player.otherPlayer.blinking
        end):finish(function()
            self.player:changeState('falling')
            self.player.otherPlayer:changeState('falling')
        end):limit(16)
    end)
end

Thanks!

2
I haven't used knife.timer, but it seems like this code is in an update function that happens for every frame of your game. Are you sure it's not creating lots of timers? - Jason Goemaat

2 Answers

1
votes
  1. With the basic countdown timer, you never specify when it should stop. Try using :limit(9) or self.timer = math.max(0,self.timer - 1)

2.Have you timed it properly (it's hard to feel how much time has passed), since you use Timer.after. The :finish() function happens inside the :after(), and after the :every(), which could cause things to be weird. I suggest adding the :limit before the :finish().

Timer.after(6, function()
        Timer.every(0.2, function() 
            self.player.blinking = not self.player.blinking
            self.player.otherPlayer.blinking = not self.player.otherPlayer.blinking
        end):limit(16):finish(function()
            self.player:changeState('falling')
            self.player.otherPlayer:changeState('falling')
        end)
    end)
0
votes

Both of the above comments were extremely useful. It turns out that putting timers under update is a bad idea because they either are calling new timers or refreshing strangely. What I ended up with, and works perfectly is:

function PlayerPilotState:enter(params)
    Timer.every(1, function()
        self.timer = self.timer - 1
    end)

    Timer.after(6, function()
        Timer.every(0.2, function() 
            self.player.blinking = not self.player.blinking
            self.player.otherPlayer.blinking = not self.player.otherPlayer.blinking
        end)
        :limit(15)
        :finish(function()
            self.player.blinking = false
            self.player.otherPlayer.blinking = false 
            self.player:changeState('falling')
            self.player.otherPlayer:changeState('falling')
        end)
    end)

end

A follow up question I would have, is how to do this without using an enter function? I guess any function call that called only once (with maybe a boolean flag to call it) would work. Thanks!