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 = scanLines; while(true) { if (!cspr.IntersectsWith(arrangedSprites)) break; // Scan along the X axis cspr.Area.X = 0; cspr.Area.Y = scanLines.Y; bool foundPosition = false; while(cspr.Area.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.Area.Right > rightProblem.Area.Right) rightProblem = probSpr; // Move up to the position furthest to the right // NOTE: We may need to add one here. cspr.Area.X = furthestRightPos + 1; } if (!foundPosition) { // We didn't find anything along the x axis - let's scan the y axis next cspr.Area.X = scanLines.X; cspr.Area.Y = 0; while (cspr.Area.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.Area.Bottom > downProblem.Area.Bottom) downProblem = probSpr; // Move up to the position furthest downwards cspr.Area.Y = downProblem.Area.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; } if (cspr.IntersectsWith(arrangedSprites)) { // We have a conflict! Let's move it to try and sort this out. List problemSprites = cspr.GetIntersectors(arrangedSprites); // Find the problem sprite closest to (0, 0) Sprite mainProblem = problemSprites[0]; foreach (Sprite pSpr in problemSprites) { if ((pSpr.Area.X < mainProblem.Area.X && pSpr.Area.Y <= mainProblem.Area.Y) || (pSpr.Area.Y < mainProblem.Area.Y && pSpr.Area.X <= mainProblem.Area.X)) mainProblem = pSpr; } Point scanBox = new Point(mainProblem.Area.X, mainProblem.Area.Y); } else { arrangedSprites.Add(cspr); } } } } public class Sprite { private Rectangle area; private string filename; public Rectangle Area { get { return area; } set { area = value; } } public string Filename { get { return filename; } set { filename = value; } } public Sprite(string inFilename) { Filename = inFilename; // TODO: Fill in the area automagically based on the given image throw new NotImplementedException("Todo: Fill in the area automagically based on the given image"); } public static int GetLargestSize(List sprList) { int largestSoFar = 0; foreach(Sprite spr in sprList) { if (spr.Area.Width > largestSoFar) largestSoFar = spr.Area.Width; } } public List GetIntersectors(List spriteList) { List result = new List(); foreach(Sprite spr in spriteList) { if (spr.IntersectsWith(this)) result.Add(spr); } return result; } public List GetIntersectorsX(List spriteList) { List result = new List(); foreach(Sprite spr in spriteList) { if (spr.IntersectsWithX(this)) result.Add(spr); } return result; } public List GetIntersectorsY(List spriteList) { List result = new List(); foreach(Sprite spr in spriteList) { if (spr.IntersectsWithY(this)) result.Add(spr); } return result; } public bool IntersectsWith(List otherSprites) { foreach (Sprite spr in otherSprites) { if (IntersectsWith(spr)) return true; } return false; } public bool IntersectsWith(Sprite otherSprite) { return otherSprite.Area.IntersectsWith(Area); } public bool IntersectsWithX(List otherSprites) { foreach (Sprite spr in otherSprites) { if (IntersectsWithX(spr)) return true; } return false; } public bool IntersectsWithY(List otherSprites) { foreach (Sprite spr in otherSprites) { if (IntersectsWithY(spr)) return true; } return false; } public bool IntersectsWithX(Sprite otherSprite) { if(Area.Right > otherSprite.Area.X && Area.X < otherSprite.Area.Right) return true; else return false; } public bool IntersectsWithY(Sprite otherSprite) { if(Area.Bottom > otherSprite.Area.Y && Area.Y < otherSprite.Area.Bottom) return true; else return false; } } }