Question about making textures customizable at runtime

Jun 27, 2011 at 11:55 PM
Edited Jun 28, 2011 at 5:58 PM

Hey Jesse, first off, thanks again for this great program.  It's saved me a ton of time building a similar thing for myself, and has some really nice features I never would have added.


My question is on the already discussed topic of changing textures at runtime, in order to allow things like character customization, where a head texture could be swapped out for a helmet, for example.


I'm currently implementing this in the AnimationPlayer class -- every animated entity in my game contains one instance of that class.  The methods for doing this will only be called when a player changes their equipment, or when the game loads, and the methods will iterate through each animation belonging to the AnimationPlayer's dictionary containing animations and update each one to point to the new texture.


My question is, I see two ways to go about doing this, and I was wondering if you might give me any advice that comes to mind about which one will be a better long-term solution. 


The first way is to change the bone.TextureIndex value, which is an int.  Doing it this way would require adding a ton of extra unused textures to the .anim files, which (I think) really means you add a bunch of extra TextureEntry objects to each animation.  With enough animations and enough AnimationPlayer objects each with their own instances of each animation, this could get annoying.  Obviously, the actual texture2ds are just references and no texture actually gets loaded into memory more than once, so it's not that big a deal.  This way seems like it could work pretty well.


The second way would be to do something a little different with the TextureDictionary class.  What I would do is create a big .tdict file with all the possible textures for a set of animations, just as normal, but instead of adding every texture to each individual animation, as in the first method, I would keep only the number of TextureEntrys in each .anim file that the animation actually needs.  So, the bone.TextureIndex int would remain unchanged.

What would change is the source rectangle* used to locate specific textures on the composite texture created by the TextureDictionary.  One way to change this would be to read the TextureDictionary into memory on its own (not within the AnimationReader's read method).  The TextureCollection dictionary within the TextureDictionary could then be used to look up a specific TextureBounds by name, which is a pretty cool bonus.


Anyway, I haven't fully implemented either of these -- I was part way through the first when I thought of the second, and I was wondering if you could warn me of any foreseeable pitfalls or big tradeoffs I haven't seen yet for doing things the second way.


Long live Demina!



* when I say source rectangle, I'm talking about animation.Textures[bone.TextureIndex].TextureBounds.Location, which is a Rectangle that the AnimationPlayer's draw call uses to choose which part of the big, composite texture should be drawn.

Jun 29, 2011 at 4:29 PM

If I were doing it myself, I'd start with method one, as it's trivial to get working, it just means you need to add the extra parts to each animation. (And that means duplicating textures if you pack the animations, but can't manage to fit all the animations that share parts into one texture.)

That said, I don't see any problem with option 2, it just seems like you'll need to do a bit of tinkering to make sure it works like you expect. If you're going to get any extra benefit from it, then it's totally awesome. (I'm really unhappy with the way my texture packer works. It needs to be more general purpose. I need to port the work I've done for FGE back to XNA at some point. I much prefer the system I'm using in the Hypership port.)

I'm really glad Demina is working out so well for you. I feel bad that I haven't been spending more time working on it, but I've gotta get my games done too. I need more hours in the day. :)