Skip to content

FlxTimer - Add function to complete the callback early.#3575

Open
Vulpicula wants to merge 5 commits intoHaxeFlixel:devfrom
Vulpicula:dev
Open

FlxTimer - Add function to complete the callback early.#3575
Vulpicula wants to merge 5 commits intoHaxeFlixel:devfrom
Vulpicula:dev

Conversation

@Vulpicula
Copy link

Small feature. First time contributing, so this may not be up to normal standards.
Seems to work based on testing, although I don't know if any additional work is required.

Needed for a personal use-case, was told to give contributing to the main source code a go.
Copy link
Member

@Geokureli Geokureli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made a little test to try this out (I always recommend doing this)

package states;

import flixel.FlxG;
import flixel.FlxSprite;
import flixel.group.FlxSpriteGroup;
import flixel.text.FlxBitmapText;
import flixel.ui.FlxButton;
import flixel.util.FlxColor;
import flixel.util.FlxTimer;

class FinishTimerTestState extends flixel.FlxState
{
    var timer:FlxTimer;
    var barBg:FlxSprite;
    var barFg:FlxSprite;
    var text:FlxBitmapText;
    var finishBtn:FlxButton;
    var startBtn:FlxButton;
    var loopBtn:FlxButton;
    
    override function create()
    {
        super.create();
        FlxG.camera.bgColor = FlxColor.WHITE;

        
        final ui = new FlxSpriteGroup();
        add(ui);
        
        final WIDTH = FlxG.width - 20;
        final BORDER = 5;
        ui.add(barBg = new FlxSprite()).makeGraphic(WIDTH, 50, FlxColor.BLACK);
        ui.add(barFg = new FlxSprite(BORDER, BORDER)).makeGraphic(barBg.frameWidth - BORDER * 2, barBg.frameHeight - BORDER * 2, FlxColor.GRAY);
        barFg.origin.x = 0;
        
        ui.add(text = new FlxBitmapText(barFg.x, "Unstarted"));
        final SCALE = 2;
        text.scale.scale(SCALE);
        text.updateHitbox();
        text.fieldWidth = Std.int(barFg.frameWidth / SCALE);
        text.autoSize = false;
        text.alignment = CENTER;
        text.y = barFg.y + (barFg.height - text.height) / 2;
        
        final btns = new FlxTypedSpriteGroup<FlxButton>();
        ui.add(btns);
        btns.add(startBtn = new FlxButton(0, 0, "Start 10s", ()->timer = FlxTimer.wait(10, onComplete)));
        btns.add(loopBtn = new FlxButton(startBtn.width, 0, "Start 10 Loops", ()->timer = FlxTimer.loop(10, onLoopComplete, 10)));
        btns.add(finishBtn = new FlxButton(loopBtn.x + loopBtn.width, 0, "Finish", ()->timer.completeEarly()));
        btns.y = barBg.height;
        
        ui.screenCenter();
        btns.screenCenter(X);
    }
    
    override function update(elapsed)
    {
        super.update(elapsed);
        if (timer != null && timer.finished == false)
        {
            barFg.setGraphicSize(barFg.frameWidth * (timer.elapsedTime / timer.time), barFg.frameHeight);
            final time = StringTools.rpad(Std.string(Std.int((timer.elapsedTime) * 10) / 10), ".0", 2);
            if (timer.loops > 1)
                text.text = '$time / ${timer.time} loops ${timer.elapsedLoops} / ${timer.loops}';
            else
                text.text = '$time / ${timer.time}';
        }
    }
    
    function onComplete()
    {
        text.text = "Completed";
        barFg.scale.x = 1.0;
    }
    
    function onLoopComplete(numLoops:Int)
    {
        FlxG.log.add('$numLoops loops');
    }
}

It doesn't work as expected, when completeEarly is called the timer starts ticking up from a negative number. onComplete is called immediately but also when the timer actually finishes, later.

Also maybe we should have both complete and completeLoop?

P.S.: It's easier for me to test your changes locally if you use a feature branch rather than making changes to your fork's dev branch. For more info, check the very hard-to-find Contribution Guide

Co-authored-by: George Kurelic <Gkurelic@gmail.com>
@Vulpicula
Copy link
Author

Thanks for letting me know! I sorta just threw it out there without properly testing it I think, as I was simultaneously attempting to get something else rolling.

I'll get this patched up and properly tested tonight.

Basically just a little sanity check in there to call the complete function. There might be a better way to do this, but it appears to work just fine.
@Vulpicula Vulpicula requested a review from Geokureli March 19, 2026 09:37
@Vulpicula
Copy link
Author

Used your little testing class, and appears everything is passing as intended now.

Only thing I'd mention is the name of the complete function now. I wonder if it might be a bit confusing, as there's both a timer.finished, and timer.complete, which can be read as the same thing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants