twolfson/spritesmith

Algorithm for Filename (Number) Sorting

woodydeck opened this issue · 2 comments

The Binary Tree algorithm does the job of making sprites in a square, however it sorts them randomly. Is there a way to have numbered sprites in order, show in order from left to right, and making a square?

For example, I have 256 sprites 64px squares. Binary Tree makes a perfect 1024x1024 square, but they are out of order. If I do left-right, they are in order, but the sprite sheet then breaks through the max spritesheet width on iOS and other phone browsers.

You can take the JSON mapping and find the sprites in browser, but this is much, much heavier in terms of load time. The order matters for my case.

While this is annoying, there is an ugly workaround! Talking it out here helped.

 let fs = require('fs')
 let Spritesmith = require('spritesmith');

 let images1 = [];
 let images2 = [];
 let images3 = [];
 let images4 = [];
 let images5 = [];
 let images6 = [];
 let images7 = [];
 let images8 = [];
 let images9 = [];
 let images10 = [];
 let images11 = [];
 let images12 = [];
 let images13 = [];
 let images14 = [];
 let images15 = [];
 let images16 = [];


 for (let i = 1; i <= 256; i++) {
     if (i <= 16) {
         images1.push('/sprites/' + i + '.png')
     }
     if (i > 16 && i <= 32) {
         images2.push('/sprites/' + i + '.png')
     }
     if (i > 32 && i <= 48) {
         images3.push('/sprites/' + i + '.png')
     }
     if (i > 48 && i <= 64) {
         images4.push('/sprites/' + i + '.png')
     }
     //And so on...
 }

 var variableArray = []

 variableArray.push(images1)
 variableArray.push(images2)
 variableArray.push(images3)
 variableArray.push(images4)
 variableArray.push(images5)
 variableArray.push(images6)
 variableArray.push(images7)
 variableArray.push(images8)
 variableArray.push(images9)
 variableArray.push(images10)
 variableArray.push(images11)
 variableArray.push(images12)
 variableArray.push(images13)
 variableArray.push(images14)
 variableArray.push(images15)
 variableArray.push(images16)

 //Lazy brute force way, but ten seconds

 for (let i = 1; i <= 16; i++) {
     saveRow(variableArray[i - 1], i)
 }

 function saveRow(row, number) {
     Spritesmith.run({
             src: row,
             algorithm: 'left-right'
         },
         function handleResult(err, result) {
             result.image
             fs.writeFile('/temp-rows/' + number + '.png', result.image, 'binary', function(err) {
                 if (err) throw err
                 console.log('File saved for row ' + number + '.')
             })
         })

 }

 var rows = []

 for (let i = 1; i <= 16; i++) {
     rows.push('/temp-rows/' + i + '.png')
 }

 console.log(rows)

 Spritesmith.run({
         src: rows,
         algorithm: 'top-down'
     },
     function handleResult(err, result) {
         result.image
         fs.writeFile('spritesheet.png', result.image, 'binary', function(err) {
             if (err) throw err
             console.log('Spritesheet saved!')
         })
     })
     ```

It's been a while since I've looked into this but I believe that binary-tree cannot guarantee sort order. As a result, please see these issues on wrapping instead:

There's also some issues that hint on sorting being consistent if filenames are ordered ahead of time, though these are for grunt-spritesmith and gulp.spritesmith: