Skip to content

Texture Sprite Packer

Allen Ray edited this page Aug 14, 2020 · 1 revision

This tool is a runtime texture packer. You can load and provide sprites to this during your games loading and it'll combine them into a single texture for more efficient drawing.

sPacker := packer.NewPacker(100, 100, 0) // creates a packer with a 100x100 internal texture

// load a sprite with Pixel
var sprite *pixel.Sprite
var err error
if sprite, err = pixelutils.LoadSprite("sprite.png"); err != nil {
  log.Fatal(err) // failed to load sprite
}

// insert the sprite into the packer
spriteId := sPacker.GenerateId()
if err := sPacker.Insert(spriteId, sprite); err != nil {
  // there was not enough space to insert the sprite.
  log.Fatal(err)
}

Packer creation flags

  • AllowGrowth: Will grow the internal texture size if the sprite can't fit; you can create the packer with w=0, h=0 and this flag if you want the starting size as small as possible.
  • DebugDraw: When the packer.Draw() routine is called, draw the emptyspaces with red rectangles.

To insert with additional flags

if err := sPacker.InsertV(spriteId, sprite, flags); err != nil {
  log.Fatal(err)
}

Available flags:

  • OptimizeOnInsert: Will run the packer.Optimize routine before inserting the sprite
  • InsertFlipped: Will insert the sprite data upside-down into the packer's internal texture

Querying the packer

Asking for the bounds of a sprite

There is a shortcut provided to give you access to the sprite's bounds at a given id.

spriteBounds := sPacker.BoundsOf(spriteId)

Retrieving sprite from packer

If you need to get the sprite back out of the packer; this will create a new sprite with a copy of the sprite data:

sprite := sPacker.SpriteFrom(spriteId)

Replacing a sprite with another

If you need to replace a sprite with another one (can be of different size): NOTE: To allow for replacing sprites with different sizes, optimize will be run

newSprite, _ := pixelutils.LoadSprite("another-sprite.png") // for brevity, ignoring the returned err

err := sPacker.Replace(spriteId, newSprite)

Optimizing the internal texture

This is basically a defragment operation; pull everything out of the packer's texture, sort them largest to smallest, and reinsert them. This should limit the amount of wasted space.

sPacker.Optimize()

Miscellaneous Routines

// returns the center point of the internal texture
center := sPacker.Center()

// returns the bounds of the internal texture
bounds := sPacker.Bounds()

// returns the pixel.Picture (actually a *pixelgl.GLPicture)
picture := sPacker.Picture()

Drawing the internal texture

For debug purposes, I've included the ability to draw the packer's internal texture so you can see its makeup and see any issues you might have.

// this will draw the internal texture centered on the window
sPacker.Draw(win, pixel.IM.Moved(sPacker.Center()))