using System; using System.Collections.Generic; using System.Drawing; using System.Security.Cryptography; using System.IO; using System.Configuration; using System.Drawing.Text; namespace SpritePacker { public class Packer { private List sprites = new List(); public Packer() { } public void Add(Sprite sprite) { sprites.Add(sprite); } public bool Remove(Sprite sprite) { return sprites.Remove(sprite); } public void Arrange() { List arrangedSprites = new List(); foreach(Sprite cspr in sprites) { Point scanLines = Point.Empty; Point nextScanLines = new Point(int.MaxValue, int.MaxValue); while(true) { if (!cspr.IntersectsWith(arrangedSprites)) break; // Scan along the X axis cspr.X = 0; cspr.Y = scanLines.Y; bool foundPosition = false; while(cspr.X < scanLines.X) { if (!cspr.IntersectsWith(arrangedSprites)) { foundPosition = true; break; } // Get the edge furthest to the right List problems = cspr.GetIntersectors(arrangedSprites); Sprite rightProblem = problems[0]; foreach (Sprite probSpr in problems) { if (probSpr.Right > rightProblem.Right) rightProblem = probSpr; if (probSpr.Top < nextScanLines.Y) nextScanLines.Y = probSpr.Top + 1; } // Move up to the position furthest to the right // NOTE: We may need to add one here. cspr.X = rightProblem.Right + 1; } if (!foundPosition) { // We didn't find anything along the x axis - let's scan the y axis next cspr.X = scanLines.X; cspr.Y = 0; while (cspr.Y < scanLines.Y) { if (!cspr.IntersectsWith(arrangedSprites)) { foundPosition = true; break; } // Get the edge furthest downwards List problems = cspr.GetIntersectors(arrangedSprites); Sprite downProblem = problems[0]; foreach (Sprite probSpr in problems) { if (probSpr.Bottom > downProblem.Bottom) downProblem = probSpr; if (probSpr.Left < nextScanLines.X) nextScanLines.X = probSpr.Left + 1; } // Move up to the position furthest downwards cspr.Y = downProblem.Bottom + 1; } } // If we found a new position, then we don't need to move the scan lines up and try again if (foundPosition) break; // Make sure that the next scan lines are sane if (nextScanLines.X == int.MaxValue) nextScanLines.X = scanLines.X; if (nextScanLines.Y == int.MaxValue) nextScanLines.Y = scanLines.Y; // If the next scan lines and the current scan lines are identical, // then something is very wrong if(nextScanLines.Equals(scanLines)) throw new Exception("Failed to find the next set of lines to scan!"); // Move the scan lines up to the next nearest ones we've found scanLines = nextScanLines; nextScanLines = new Point(int.MaxValue, int.MaxValue); } arrangedSprites.Add(cspr); } // We don't need to copy the list of arranged sprites across to the main list here // because Sprite is a class and classes are passed by _reference_. } public override string ToString() { string result = string.Format("SpritePacker:"); foreach (Sprite spr in sprites) result += string.Format("\t{0}\n", spr); return result; } } }