Archive for February 27th, 2008


Asking a computer to make a value judgment

The value judgment in question is what is the best way to layout a series of similarly sized elements on the screen to get it, in that hazy sense, to look ‘right’?

ie. distributing items on the screen dynamically.

Scenario: I have a random number of items, maybe being pulled in from xml, and I want to place movieclips on the screen in a grid which are placed evenly in columns. Thing is, how many rows and how many columns do I need? Especially as the height and width of my movieclip may not be square.

To distribute mcs of lampposts you’re likely to have more mcs running horizontally than vertically – as opposed to distributing mcs of snakes, which you are more likely to want to stack vertically.

Well the most effective way of doing this I could muster was to get the square root of the total number of items and then multiply that by a suitable aspect ratio.

For example. Let’s say I want to distribute to a square stage 500 x 500.

I have 36 items. So, I get the square root which is 6.

var array = [0,1,2 … , 35];
var sqrt = Math.sqrt(array.length);

Next I’ll add these together to get a total 12.
var total = (sqrt + sqrt);

Now I want to multiply this by an aspect ratio to work out the distribution. If the mcs are twice as wide as they are high, the aspect ratio is 2 and an ideal distribution would be 4 columns and 8 rows. 4×2 = 8 and 8×1 = 8… width and height match.

So my total, 12 needs to be somehow split into 4 and 8.

My approach is to divide 12 by height and length ratios, i.e. 1(h) + 2(w) = 3.
var ratiodiff = (total/(ratio+1));

Then multiply the result (4) by the ratio 2, so 4 * 2 = 8.
var ratiodiff = (total/(ratio+1)) * ratio;

Now I can use this for my number of rows, and the remainder for the number of columns.
var cols = total – ratiodiff;
var rows = total – cols;

Now, instead of 32, if i was using scraggly odd numbers like 73 or 113, I can apply the same maths to get an approximation. For 73, the result for the number of columns is 5.7 which is no use… we need a whole number.

Therefore I’ll use the ceiling of the number, 6. Then I’m assured of having enough space for all the movieclips .. although there’ll be some gaps at the bottom. I’ll be treating my columns like buckets.

var cols = Math.ceil(total – ratiodiff);

Since cols is now an approximation I need to calculate the rows differently to make sure I’ve got all the items from the original array.

var rows = Math.ceil(array/cols);

Wow. That was intense. I’m sure there are other approaches to this problem, and many of them maybe better than this, but this works and it’ll suit me for now.