ProgressTimer doesn't runAction(progress)

Hello, dear community!

I am trying to implement a radially disappearing clock image as a countdown. My sprite appears and is removed correctly, but no animation occurs, what should I do? Thank you!

void MainScene::setupCountdown(){
   if (countdownTimer_ != nullptr) {
      unschedule(schedule_selector(MainScene::countdownScheduler));
      countdownTimer_->removeFromParentAndCleanup(true);
      countdownTimer_ = nullptr;
   }
   
   auto clock = Sprite::create("clock.png");
   countdownTimer_ = ProgressTimer::create(clock);
   countdownTimer_->setType(ProgressTimer::Type::RADIAL);
   countdownTimer_->setBarChangeRate(Point(1,0));
   countdownTimer_->setMidpoint(Point(0,0.5f));
   this->addChild(countdownTimer_, kZOrderClock);
   countdownTimer_->setPosition(kPointClockPos);
   this->schedule(schedule_selector(MainScene::countdownScheduler), 0.1f);
   countdownTimer_->setPercentage(0.0f);

}

void MainScene::countdownScheduler(float dt){
   
   duration_ -= 0.1f;
   auto percentage = 100.0f * (duration_ / kInitialDuration);
   auto progress = ProgressTo::create(0.1f, percentage);
   countdownTimer_->runAction(progress);
   
   if (duration_ <= 0.0f) {
      unschedule(schedule_selector(MainScene::countdownScheduler));
      countdownTimer_->removeFromParentAndCleanup(true);
      countdownTimer_ = nullptr;
   }
}

I think you’re trying to make it more complicated than it needs to be. You want something more like this:

void MainScene::setupCountdown()
{
    if (countdownTimer_ != nullptr) 
    {
      countdownTimer_->removeFromParentAndCleanup(true);
      countdownTimer_ = nullptr;
    }

    auto clock = Sprite::create("clock.png");
    countdownTimer_ = ProgressTimer::create(clock);
    countdownTimer_->setType(ProgressTimer::Type::RADIAL);

    this->addChild(countdownTimer_, kZOrderClock);

    auto progress = ProgressTo::create(kInitialDuration, 100);
    countdownTimer_->runAction(progress);
}

Oh yes, you’re right, the logic is the same. But it still doesn’t work. Did you tested this code in your machine?

I had just typed it directly into the forum. I noticed I forgot two semicolons. I put those back in. I just tried this code and it works. One thing to note, is that it was based on your original code. This puts the countdown timer in the bottom left hand corner.

If you’re going to be reusing the countdown timer often, this code is inefficient, as it always creates a new one instead of reusing one. If you want to reuse the countdown timer, you could do something like this:

void MainScene::init()
{
    ...
    Size visibleSize = Director::getInstance()->getVisibleSize();

    auto clock = Sprite::create("clock.png");
    countdownTimer_ = ProgressTimer::create(clock);
    countdownTimer_->setType(ProgressTimer::Type::RADIAL);
    countdownTimer_->setPosition(visibleSize / 2);    // this will put it at the center of the screen

    this->addChild(countdownTimer_, kZOrderClock);
    ...
}

void MainScene::setupCountdown()
{
    countdownTimer_->stopActionByTag(kCountdownActionTag);    // kCountdownActionTag would need to be defined

    auto reset = ProgressTo::create(0, 0);
    auto progress = ProgressTo::create(kInitialDuration, 100);
    auto progSeq = Sequence::create(reset, progress, NULL);
    progSeq->setTag(kCountdownActionTag);

    countdownTimer_->runAction(progSeq);
}

Never use a scheduler for a progress timer, as it’s timed/progressed on it’s own through an action. As @toojuice pointed out, it will contradict it’s purpose.

The animation does not show, cause you set one of the midpoint coordinates to zero. The radial progress timer needs space to wrap around. A value of 0 means, that it already reached that endpoint.
Also it changes it’s center point and for that reason it needs each bar change rate greater than zero.

The difference between your code and the one of @toojuice is, that it rotates counter clockwise instead of clockwise.

Do you want a centered radial progress timer? Than just apply these changes:

countdownTimer_->setBarChangeRate(Point(1,1));
countdownTimer_->setMidpoint(Point(0.5f,0.5f));

It’s also better to use floats for readability and getting rid of implicit casting, if the function takes floats. So maybe you want to use 1.0f instead of 1.

Thank you a lot. Really nice explanation of the methods! Appreciated it, guys!