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

Animation frames out of order on Flash but not Windows #1926

Closed
IBwWG opened this issue Sep 2, 2016 · 7 comments
Closed

Animation frames out of order on Flash but not Windows #1926

IBwWG opened this issue Sep 2, 2016 · 7 comments

Comments

@IBwWG
Copy link
Contributor

IBwWG commented Sep 2, 2016

  • Flixel version: dev (also flixel-demos)
  • OpenFL version: 3.6.1
  • Lime version: 2.9.1
  • Affected targets:
    flash only

Open the TexturePackerAtlas demo, and unzip libgdx.zip into assets/libgdx/.

Then replace MenuState.hx with this:

package;

import flixel.FlxG;
import flixel.FlxObject;
import flixel.FlxSprite;
import flixel.FlxState;
import flixel.graphics.frames.FlxAtlasFrames;
import flixel.graphics.frames.FlxFrame;
import flixel.util.FlxColor;

class MenuState extends FlxState
{
    override public function create():Void
    {
        var tex9 = FlxAtlasFrames.fromLibGdx("assets/libgdx/libgdx-packed.png", "assets/libgdx/libgdx-packed.atlas");
        FlxG.debugger.drawDebug = true;
        FlxG.debugger.visible = true;
        bgColor = FlxColor.WHITE;
        var x11 = new FlxSprite(50, 50);
        x11.frames = tex9;
        x11.animation.addByPrefix("spin", "", 3);
        x11.animation.play("spin");
        add(x11);
        FlxG.watch.add(x11.animation, "frameIndex");


        // Remove atlas bitmaps from memory (useful for targets with hardware acceleration: cpp only atm).
        FlxG.bitmap.dumpCache();
    }
}

Observed behavior:

On Windows, the sequence is normal.
On Flash, I see the frames (with visuals to match) go by in this order: 3-1-2-0-4-5.

Expected behavior:

I'd expect Flash to also go 0-1-2-3-4-5.

Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.

@Beeblerox
Copy link
Member

Beeblerox commented Sep 29, 2016

if you set prefix parameter in animation.addByPrefix() method to "spin/" then it will work the same across the targets.
the "problem" is in FlxFrame.sortByName() static method which is used for sorting frames for animation.
But i'm not sure that this is actually a problem in this case, because when you specify prefix value as an empty string then this method tries to sort full strings "spin/1", "spin/2", etc.
But when you specify prefix as "spin/" then it sorts strings like "1", "2", etc.
And i believe that "Std.parseInt()" works differently (gives different results) across cpp and flash targets:
on cpp target it converts "spin/1" to 1 and on flash target it converts "spin/1" (and other strings like "spin/100500") to 0. that is why you have different results.

Of course we could make FlxFrame.sortByName() more complex to handle such cases, but while making those parsing and sorting methods i haven't expected that someone will "omit" prefix value when it necessary. i thought that method documentation makes it clear that you need to specify "common beginning of image names in atlas".

So what should we do:
a) handle this and similar cases in FlxFrame.sortByName() (this will require additional logic for converting frame names into numbers)
b) close this issue as showing incorrect usage of method?

@Beeblerox
Copy link
Member

Beeblerox commented Sep 29, 2016

we can achieve desired result with regexp. This is what i got now

public static function sortByName(frame1:FlxFrame, frame2:FlxFrame, prefixLength:Int, postfixLength:Int):Int
    {
        var subName1 = frame1.name.substring(prefixLength, frame1.name.length - postfixLength);
        var subName2 = frame2.name.substring(prefixLength, frame2.name.length - postfixLength);

        var num1:Int = 0;
        var num2:Int = 0;

        var regex = ~/([0-9])+$/; // ([0-9])*[^0-9]+$

        if (regex.matchSub(subName1, 0))
        {
            num1 = Std.parseInt(regex.matched(0));
        }

        if (regex.matchSub(subName2, 0))
        {
            num2 = Std.parseInt(regex.matched(0));
        }

        return num1 - num2;
    }

@Beeblerox
Copy link
Member

i know that it could be improved, but unfortunately i'm a total newbie with regular expressions

@Beeblerox
Copy link
Member

updated method in my snippet, so it returns correct result

@Gama11
Copy link
Member

Gama11 commented Sep 29, 2016

And i believe that "Std.parseInt()" works differently (gives different results) across cpp and flash targets:
on cpp target it converts "spin/1" to 1 and on flash target it converts "spin/1" (and other strings like "spin/100500") to 0. that is why you have different results.

That doesn't sound right... We should look into that.

@Beeblerox
Copy link
Member

@Gama11 i'll make example project for this behavior across different targeys, but in context of this issue this code works as expected (as i would expect it to work), it's just user's misuse of method parameters in my opinion

@Gama11 Gama11 added the Bug label Sep 29, 2016
@Gama11 Gama11 closed this as completed in 692da17 Sep 29, 2016
@Gama11
Copy link
Member

Gama11 commented Sep 29, 2016

The behavior is now consistent across platforms. You should still make sure to supply correct a correct Prefix parameter to addByPrefix() though (should be "split/" instead of an empty string).

Aurel300 pushed a commit to larsiusprime/haxeflixel that referenced this issue Apr 18, 2018
The behavior when Std.parseInt() fails (because of incorrect prefix or postfix input values) was inconsistent. On Neko it crashed, on Flash the sorting order changed.
closes HaxeFlixel#1926
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

No branches or pull requests

3 participants