Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow non-global managers for FlxTween and FlxTimer #1934

Merged
merged 4 commits into from
Sep 11, 2016

Conversation

JoeCreates
Copy link
Member

@JoeCreates JoeCreates commented Sep 7, 2016

Pretty relevant to #1087. Solves the problems of pausing or changing the update speed of states and having their timers and tweens also change. I've been through a few solutions for this, but have eventually landed on this. I have provided a test state to see the new behaviour in action at the bottom.

FlxTweens and FlxTimers now have their own member manager, while the existing manager has been renamed to globalManager (making this a potentially breaking change where things previously referenced the global managers). Timers and tweens now have an additional optional parameter to set the manager, which defaults to the global manager.

In FlxTween I moved the implementations of tween etc to the manager and made the static versions simply defer to these on the global manager. This means that FlxTween.tween() still works exactly as it used to, but now we also have myTweenManager.tween().

Note that a tweens manager is not updated when a tween/timer is added to a manager. I had experimented with having the manager be the manager that the tween/timer is currently a member of, however it would have become very different in behaviour to the existing use of the global manager. It was complicated because of things such as cancelling and starting/stopping timers/tweens adds and removes them from the manager. If you remove a tween from a manager, you may want to restart it in the same manager, so it would not be desirable to set the manager to null. Therefore the member manager should be treated as "the manager that future changes to this tween will be performed on". This should help with backward compatibility.

I had played around with having lazily initialised managers on FlxBasic, but ultimately decided that this overcomplicated things, and it is easy enough to add them when needed.

Note that this will only break existing games which referenced the global managers as simply manager rather than globalManager, but this will be uncommon and easy to solve in those cases.

package;

import flixel.FlxG;
import flixel.FlxSprite;
import flixel.FlxState;
import flixel.FlxSubState;
import flixel.addons.ui.FlxSlider;
import flixel.group.FlxSpriteGroup;
import flixel.math.FlxRect;
import flixel.tweens.FlxEase;
import flixel.tweens.FlxTween;
import flixel.ui.FlxButton;
import flixel.util.FlxColor;
import flixel.util.FlxTimer;

class PlayState extends FlxState {

    var tweens:FlxTweenManager = new FlxTweenManager();
    var timers:FlxTimerManager = new FlxTimerManager();

    public var updateSpeed:Float = 1;

    override public function create():Void {
        var sprGlobalTween = makeSprite(0, 0);
        var sprLocalTween = makeSprite(300, 0);
        var sprGlobalTimer = makeSprite(0, 300);
        var sprLocalTimer = makeSprite(300, 300);

        var group = new FlxSpriteGroup();

        group.add(sprLocalTimer);
        group.add(sprGlobalTimer);
        group.add(sprLocalTween);
        group.add(sprGlobalTween);

        group.screenCenter();

        add(group);

        var slider = new Slider(this, "updateSpeed", 0, 0, 0, 3, 300, 30, 10, 0xFF444444);
        slider.color = FlxColor.WHITE;
        slider.nameLabel.text = "Update Speed";
        slider.screenCenter();
        slider.value = 1;
        slider.updateBounds();
        add(slider);

        add(tweens);
        add(timers);

        sprLocalTween.x -= 75;
        tweens.tween(sprLocalTween, {x: sprLocalTween.x + 150, angle: 360}, 1, {ease: FlxEase.quadInOut, type: FlxTween.PINGPONG});

        sprGlobalTween.x -= 75;
        FlxTween.tween(sprGlobalTween, {x: sprGlobalTween.x + 150, angle: 360}, 1, {ease: FlxEase.quadInOut, type: FlxTween.PINGPONG});

        new FlxTimer(timers).start(0.3, function(t:FlxTimer) {
            sprLocalTimer.visible = !sprLocalTimer.visible;
        }, 0);

        new FlxTimer().start(0.3, function(t:FlxTimer) {
            sprGlobalTimer.visible = !sprGlobalTimer.visible;
        }, 0);

        var button = new FlxButton(5, 5, "Pause", function() {
            persistentUpdate = false;
            persistentDraw = true;
            openSubState(new PauseSubstate());
        });
        add(button);

    }

    function makeSprite(x:Float, y:Float):FlxSprite {
        var spr = new FlxSprite(x, y);
        spr.scale.set(3, 3);
        return spr;
    }

    override public function update(dt:Float):Void {
        super.update(dt * updateSpeed);
    }
}

class Slider extends FlxSlider {
    public function updateBounds() {
        _bounds = FlxRect.get(x + offset.x, y +offset.y, _width, _height);
    }
}

class PauseSubstate extends FlxSubState {
    override public function create():Void {
        super.create();

        this.bgColor = 0x44000000;

        var button = new FlxButton(0, 0, "Unpause", function() {
            close();
        });
        button.screenCenter();
        button.y = FlxG.height - 50;
        add(button);
    }
}

@MSGhero
Copy link
Member

MSGhero commented Sep 8, 2016

Omg yes

@IBwWG
Copy link
Contributor

IBwWG commented Sep 8, 2016

Ah, so with persistentUpdate off, that stops all local tweens and timers from updating. I like this idea very much. Also clever with the localized updateSpeed, independent from the global FlxG.timeScale.

@Gama11
Copy link
Member

Gama11 commented Sep 8, 2016

There's a failing unit test:

src/flixel/util/FlxTimerTest.hx:40: characters 2-18 : Class<flixel.util.FlxTimer> has no field manager

@Gama11
Copy link
Member

Gama11 commented Sep 8, 2016

Oh, right, I can just fix this myself now: https://github.com/blog/2247-improving-collaboration-with-forks :)

@IBwWG
Copy link
Contributor

IBwWG commented Sep 8, 2016

Cool re: collab...

@Gama11
Copy link
Member

Gama11 commented Sep 8, 2016

While this includes a breaking change, it's a fairly small one, and I can't really think of a great way to avoid it. Need a second opinion from @HaxeFlixel/owners though.

@Gama11 Gama11 added this to the 4.2.0 milestone Sep 9, 2016
@Beeblerox
Copy link
Member

i like this pull request.
Renaming static variable to globalManager and adding property to object is a good way.

The only way we can avoid this small breaking change is to leave global manager's name as is, and select different name for "local" manager (but i can't think of another good name for it :) )

@Gama11
Copy link
Member

Gama11 commented Sep 11, 2016

Thanks a lot for this! We can now finally close that issue. :)

Do you think you could incorporate the test code you provided here into the FlxSubState demo somehow? We should definitely have an example of how to use local tween / timer managers.

@Gama11 Gama11 changed the title Make it possible to use non-global FlxTweenManagers and FlxTimerManagers Allow non-global managers for FlxTween and FlxTimer Sep 11, 2016
@Gama11 Gama11 merged commit 5cae7e9 into HaxeFlixel:dev Sep 11, 2016
Aurel300 pushed a commit to larsiusprime/haxeflixel that referenced this pull request Apr 18, 2018
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.

5 participants