TexturePacker Atlas – ShiVa Engine

TexturePacker Atlas

As you probably know, it’s important to use Texture Atlases for efficiency reasons on mobile devices. The idea is that you pack lots of textures into one big one, and then use UV offsets to define which region of this large texture to display in your HUD components. This means that only one texture has to be referenced by the graphics hardware. But it can be a bit fiddly calculating the UVs, especially if you want to add new textures to it later.

Creating the texture atlas

I use a program called Texture Packer (codeandweb.com/texturepacker) for this, which combines your textures into a single PNG and also exports an XML description of it (which we’ll need later; we could of course manually write the XML but it’s a bit more work that way..)
Texture-atlas-1

Write/export your XML

My Shiva code a bit later will assume the following format, which is what Texture Packer gives us. It simply encodes the names of the images (sprites), along with their positions and sizes in the atlas.







ShiVa Import

Import the xml file and texture atlas in to Shiva. Then create your HUD. Anywhere you want a texture out of the atlas, just set that HUD component to the Atlas texture (it looks a bit weird at design-time..)
Texture-atlas-2
Add an XML variable to an AI, and set it initialised from the imported xml. (I call my xml variable xmlZS_icons, and hard-code that in the code below)

LUA Code

Add the following function to your AI:

--------------------------------------------------------------------------------
function MyAI.SetUvsFromTextureAtlas ( sComp,sIcon )
--------------------------------------------------------------------------------
local r = xml.getRootElement ( this.xmlZS_icons ( ) )
local imgWid = string.toNumber ( xml.getAttributeValue ( xml.getElementAttributeWithName ( r, "width" ) ) )
local imgHgt = string.toNumber ( xml.getAttributeValue ( xml.getElementAttributeWithName ( r, "height" ) ) )
local c = xml.getElementChildCount ( r )
for i=0, c-1 do
   local e = xml.getElementChildAt ( r,i )
   if ( sIcon==xml.getAttributeValue ( xml.getElementAttributeWithName ( e, "n" ) ) ) then
      local uscale = string.toNumber ( xml.getAttributeValue ( xml.getElementAttributeWithName ( e, "w" ) ) ) / imgWid
      local vscale = string.toNumber ( xml.getAttributeValue ( xml.getElementAttributeWithName ( e, "h" ) ) ) / imgHgt
      local u = string.toNumber ( xml.getAttributeValue ( xml.getElementAttributeWithName ( e, "x" ) ) ) / imgWid
      local v = 1-( string.toNumber ( xml.getAttributeValue ( xml.getElementAttributeWithName ( e, "y" ) ) ) / imgHgt )-vscale
      local comp = hud.getComponent ( application.getCurrentUser ( ),sComp )
      hud.setComponentBackgroundImageUVOffset ( comp, u, v )
      hud.setComponentBackgroundImageUVScale ( comp, uscale, vscale )
      return
   end
end
log.message ( "Unable to find icon '"..sIcon.."' in texture atlas!" )
--------------------------------------------------------------------------------
end
--------------------------------------------------------------------------------

And finally, whenever you instantiate your HUD, call the following for each HUD component that’s included in the texture atlas:

this.SetUvsFromTextureAtlas ( "MyHUD.MyComponent", "sprite_name" )

Texture-atlas-3




Need more answers?

  • slackBanner