Need Help Understanding How to Reset a Timer

Hi everyone,

This is still for my SpongeBob game project, and I used the TCastleTimer object type from the physics_2d_game_sopwith project; my question is the project I am using doesn’t seem to have a way to reset the timer if you need to, and my project needs to reset a timer, in particular it needs to reset the timer to indicate that the player is in pain every time they get hit so that the wincing face lasts 2 seconds exactly every time, so that way it doesn’t accumulate and then you get weirdness about it happening after 2 seconds one time, then 4 seconds another, then 1 second another, and so on.

Does anyone know the correct code for this?

I looked in the API page for the TCastleTimer and it doesn’t seem to have a Reset method, and neither do its parent classes the User Interface and Component.

Here is the link to my Github project for reference:

From your description it not clear how do you expect the “reset” of timer to work.

And looking at your code ( gameviewplay.pas ), you do not use TCastleTimer for what it was designed – which is to run some event regularly, e.g. every 2 seconds. Instead, what you do (and seem to want) is to run even once after 2 seconds, that’s it. Your current approach to this is somewhat complicated and buggy, i.e. you recreate the timer each time from TViewPlay.SandyWince (possibly making a memory leak, and double call to EventBacktoNeutral, since you don’t free previous timer).

I could advise how to use TCastleTimer without above bugs, but it would be unnecessarily complicated. You just should not really use TCastleTimer for what you want :slight_smile:

The solutions:

  1. If you want to do something when 2 seconds passed, just “count the time” yourself. It is trivial.

    • Declare a field like TimeToDoSomething: TFloatTime. (TFloatTime is just Double)

    • In every Update call of your view, if TimeToDoSomething is > 0 then decrease it by SecondsPassed, and if it drops <= then do what you want. Like

      if TimeToDoSomething > 0 then
      begin
        TimeToDoSomething := TimeToDoSomething - SecondsPassed;
        if TimeToDoSomething <= 0 then
          DoSomething;
      end;
      
    • To start it, e.g. in TViewPlay.SandyWince, just set TimeToDoSomething := 2.

    • As with my past answers, please don’t try to just paste the above snippet into your unit and expect it to work out of the box. The above is pseudocode, example. Try to understand it (maybe play with it in a new, simple application) if it isn’t clear.

    • This is it. You don’t need TCastleTimer.

  2. If you want to do something when e.g. some animation ended, or some sound finished, there are also specialized callbacks for this. For example

    • To watch animation end, use TPlayAnimationParameters.StopNotification , demo in examples/short_api_samples/animation_stop_notification/animation_stop_notification.dpr .

    • To watch sound end, use TCastlePlayingSound.OnStop.

Okay, I wanted it to do something after 2 seconds have passed, but be able to start the timer over again from blank so the seconds don’t add up from previous times it was called, when the trigger happens (namely, when you touch something that hurts you);

The “TimeDoSomething” method is exactly what I wanted for something like this; I am really sorry if it was unclear what “reset a timer” meant in this context.