2

I'm trying to flip horizontally the sprites from a SpriteSheet animation. I'm starting from this example

I've added the flipped frames right after creating the SpriteSheet

    var ss = new createjs.SpriteSheet(spriteSheet);

    createjs.SpriteSheetUtils.addFlippedFrames(ss, true, false, false);

    grant = new createjs.BitmapAnimation(ss);
...

And I always get this error :

Uncaught TypeError: Cannot read property 'length' of null    (SpriteSheetUtils.js l.174)

I've seen that someone has got the same problem in this github thread And fixed it using the preload mecanism.

The example is also using the preload so I've tried to call the addFlippedFrames after the resource loading, but I'm still seeing the same error.

Does anyone have a clue for me ? how can I use addFlippedFrames ?

EDIT : here is the code I tried :

Init the stage with my spritesheet :

    spriteSheet = new createjs.SpriteSheet({
        "animations": {
            "none": [0, 0],
            "run": [0, 25],
            "jump": [26, 63]
        },
        "images": ["characters/grant/runningGrant.png"],
        "frames": {
            "height": h,
            "width": w,
            "regX": 0,
            "regY": 0,
            "count": 64
        }
    });



    sprite = new createjs.BitmapAnimation(spriteSheet);
    sprite.x = startPosition.x;
    sprite.y = startPosition.y;

// Add the sprite to the stage.
stage.addChild(this.sprite);

Then use the preload like this :

var manifest = [{
        src: "characters/grant/runningGrant.png",
        id: "grant"
    }
];

var loader = new createjs.LoadQueue(false);
loader.onFileLoad = handleFileLoad;
loader.onComplete = onResourcesLoaded;
loader.loadManifest(manifest);

and the callback functions :

handleFileLoad = function(event) {
    assets.push(event.item);
};

onResourcesLoaded = function() {

    for (var i = 0; i < assets.length; i++) {
        var item = assets[i];
        var id = item.id;
        var result = loader.getResult(id);

        if (item.type == createjs.LoadQueue.IMAGE) {
            var bmp = new createjs.Bitmap(result);
                //does this Bitmap creation trigger the real bitmap loading ?
                //is this loading asynchrous which would explain my problem.
                //in this case, how can I manage the loading callback ?
        }
    }

    //I would expect here to have the image fully loaded but its not
    //A timeout of 2 seconds makes the addFlippedFrames works.
    setTimeout(function(){
            createjs.SpriteSheetUtils.addFlippedFrames(spriteSheet, true, false, false);
            sprite.gotoAndPlay("run_h"); //I think "run_h" is used to launch the flipped version of "run"
    }, 2000);
};
Guian
  • 4,423
  • 4
  • 30
  • 53
  • Can you share your specific example via jsfiddle? I have had the same issue and in my case the issue was that the image wasn't loaded yet. As a very quick&dirty test you could use a timeout of 1 or 2 seconds before executing the `addFlippedFrames` (just for testing) – olsn Jun 13 '13 at 15:51
  • yep it works after a timeout of 2 seconds ... :/ – Guian Jun 14 '13 at 19:44
  • I tried to create a JSFiddle with my example but getting a DOM SECURITY exception :/ you can see it here : http://jsfiddle.net/2K6SX/5/ – Guian Jun 14 '13 at 20:20

2 Answers2

3

Your issue was, that you created a SpriteSheet with an image-url, this triggered a loading process already, and the preload-js queue actually loaded nothing, because the loading for the image was already in progress, so the "onComplete"-event was allways triggered before the image was actually loaded - which makes sense, because there is no need to load an image twice

I've updaded your jsfiddle and added some comments: http://jsfiddle.net/K4TmS/1/ (full code)

spriteSheet = new createjs.SpriteSheet({
            "animations": {
                "none": [0, 0],
                "run": [0, 25],
                "jump": [26, 63]
            },
            //this line in YOUR version triggered an own loading process, independent from the queue
            "images": [result],  
            "frames": {
                "height": 292.5,
                "width":165.75,
                "regX": 0,
                "regY": 0,
                "count": 64
            }
        });

// this was executed instantly, because the image was already in another loading progress, and therefore wasn't even added to the queue
loader.onComplete = onResourcesLoaded;

The DOM Security Error18 can be ignored with this argument here (for development) Disable same origin policy in Chrome But for production you should just load the img from the same server, then image-operations won't give an error.

So in short: Your issue was due to the wrong order of executing things, remember: if you use preloading: Do preloading before EVERYTHING else, and do NOTHING else untill the preloading isn't done. (Except for a loading-graphic/animation/indicator).

Community
  • 1
  • 1
olsn
  • 15,273
  • 5
  • 51
  • 61
  • Seems a good explanation. I'll give it a try, thx! About the loading from a different server, I did it only for the JSfiddle example so it won't be a problem in my actual code ;) – Guian Jun 16 '13 at 10:35
  • Yes, I was guessing that, just thought I'd mention it, in case you or anyone else stumbles upon the issue ;) – olsn Jun 16 '13 at 12:42
2

It's easy to do with scaleX

if(right == true)
    {
        //walking direction en sprite switch
        rogerWalk.scaleX = -1 * rogerWalk.scaleX;
        right = false;
    }

//code i used to make (in this case roger walk right(standard sprite direction)

if(right == false)
    {
        rogerWalk.scaleX = -1 * rogerWalk.scaleX;
        right = true;

//this is in the keyleft/keyright function i have

i know the post it old but still someone might be able to use it :)

Xereoth
  • 21
  • 1
  • Also consider setting `rogerWalk.regX` to the center pixel of a sprite to keep the reflection on same place. – Klesun May 12 '16 at 23:42