Duplicating Sprite Including Animation Data



  • Alright, so this is my first HaxeFlixel (and Haxe in general) project, so I'm trying to do things a bit more manually to get the hang of how it all fits together.

    To that end, I've got some code that loads a sprite and creates the frames and animations (I have 512 32x32 frames at the start and the rest is full of 64x64 frames, and I was curious how hard it would be to define it manually instead of relying on another tool):

    	var tiles = new FlxSprite("assets/images/tiles.png");
    	var f = new FlxFramesCollection(tiles.graphic);
    	
    	for (r in 0...numSmallTileRows)
    	{
    		for (t in 0...numSmallTilesPerRow)
    		{
    			f.addSpriteSheetFrame(new FlxRect(t * smallTileSize, r * smallTileSize, smallTileSize, smallTileSize));
    		}
    	}
    	for (r in startingLargeRow...numLargeTileRows)
    	{
    		for (t in 0...numLargeTilesPerRow)
    		{
    			f.addSpriteSheetFrame(new FlxRect(t * largeTileSize, r * largeTileSize, largeTileSize, largeTileSize));
    		}
    	}
    	
    	tiles.setFrames(f);
    	
    	for (anim in gameData.animations)
    	{
    		tiles.animation.add(anim.name, anim.indices, anim.frameRate, anim.looped, anim.flipX, anim.flipY);
    	}
    

    This part works fine, but presumably I wouldn't want to run this code for every individual tile on my map, so I'm looking for a way to basically do this once and then copy the data to a bunch more FlxSprite objects.

    Currently I have this code:

    	var tiles = TileLoader.GetBaseTileSprite(game);
    	
    	var lvl = game.missions[0].levels[0];
    	for (x in 0...lvl.xDim)
    	{
    		for (y in 0...lvl.yDim)
    		{
    			var s = new FlxSprite(x * 32, y * 32);
    			s.loadGraphicFromSprite(tiles);
    			s.animation.play(lvl.tiles[x][y], -1);
    			add(s);
    		}
    	}
    

    This also basically works, tiles is the FlxSprite generated by the first code block, and it is then successfully copied to all my individual tile sprites (and quite quickly at that). The resultant sprite has both the sprite sheet frames and animations from the parent.

    The one thing I've run into, is that the copied animations do not have the flipX and flipY properties copied over.

    So, my question ultimately is, is this the correct way to be creating/copying tiles, and is there something else I need to do to get the flip flags to come over, or is there some other way I should be doing this?

    Thanks!



  • Here is how I did replacing the sprite texture while keeping all the animations:

    class Player extends FlxSprite
    {
    
    public function replaceClothes1()
    {
        var a = new FlxAnimationController(this);
        var oldWidth = width;
        var oldHeight = height;
    		
        a.copyFrom(animation);
        loadGraphic("assets/images/mag_sh.png", true, frameWidth, frameHeight);
        animation = a;
    		
        setSize(oldWidth, oldHeight);
    }
    
    }
    
    

    Hope this helps



  • Thanks for the code, so here's what I just tested:

    	var tiles = TileLoader.GetBaseTileSprite(game);
    	tiles.animation.play("flag");
    	tiles.animation.play("testAnim");
    	trace(tiles.animation.curAnim.flipY);
    	
    	var a = new FlxAnimationController(tiles);
    	a.copyFrom(tiles.animation);
    	tiles.animation = a;
    	tiles.animation.play("flag");
    	tiles.animation.play("testAnim");
    	trace(tiles.animation.curAnim.flipY);
    

    I played flag and then testAnim to make sure that nothing funny was going on with it thinking that it was the same animation and not updating.

    Results:
    true and then false, so it looks like copyFrom also leaves behind the flip flags.

    So...any other ideas?



  • I think the right way is to patch the copyFrom function:

    public function copyFrom(controller:FlxAnimationController):FlxAnimationController
    	{
    		destroyAnimations();
    		
    		for (anim in controller._animations)
    		{
    			add(anim.name, anim.frames, anim.frameRate, anim.looped, anim.flipX, anim.flipY);
    		}
    		
    		if (controller._prerotated != null)
    		{
    			createPrerotated();
    		}
    		
    		if (controller.name != null)
    		{
    			name = controller.name;
    		}
    		
    		frameIndex = controller.frameIndex;
    		
    		return this;
    	}
    

    Then, if all is fine, we can submit a pull request :-)



  • Ah, yes, looking at the code on GitHub that does seem like where it should go.

    Took me a few minutes to track down where to put it locally to test it, but that worked fine and didn't appear to break anything, so I've submitted a pull request.

    First time in a while I've had an opportunity to give back to an open-source project; any idea how long these sort of things take?

    (although the good news is I can always use my local copy easily enough)



  • It depends when the guys with the commit rights will have time to review and merge it. They seem to be absent at the moment though



  • Well, I did my part at least.

    Thanks again for the help!


Log in to reply