Here's a method that should do what you need:
/// <summary>
/// Splits a texture into an array of smaller textures of the specified size.
/// </summary>
/// <param name="original">The texture to be split into smaller textures</param>
/// <param name="partWidth">The width of each of the smaller textures that will be contained in the returned array.</param>
/// <param name="partHeight">The height of each of the smaller textures that will be contained in the returned array.</param>
public Texture2D[] Split(Texture2D original, int partWidth, int partHeight, out int xCount, out int yCount)
{
yCount = original.Height / partHeight + (partHeight % original.Height == 0 ? 0 : 1);//The number of textures in each horizontal row
xCount = original.Height / partHeight + (partHeight % original.Height == 0 ? 0 : 1);//The number of textures in each vertical column
Texture2D[] r = new Texture2D[xCount * yCount];//Number of parts = (area of original) / (area of each part).
int dataPerPart = partWidth * partHeight;//Number of pixels in each of the split parts
//Get the pixel data from the original texture:
Color[] originalData = new Color[original.Width * original.Height];
original.GetData<Color>(originalData);
int index = 0;
for (int y = 0; y < yCount * partHeight; y += partHeight)
for (int x = 0; x < xCount * partWidth; x += partWidth)
{
//The texture at coordinate {x, y} from the top-left of the original texture
Texture2D part = new Texture2D(original.GraphicsDevice, partWidth, partHeight);
//The data for part
Color[] partData = new Color[dataPerPart];
//Fill the part data with colors from the original texture
for (int py = 0; py < partHeight; py++)
for (int px = 0; px < partWidth; px++)
{
int partIndex = px + py * partWidth;
//If a part goes outside of the source texture, then fill the overlapping part with Color.Transparent
if (y + py >= original.Height || x + px >= original.Width)
partData[partIndex] = Color.Transparent;
else
partData[partIndex] = originalData[(x + px) + (y + py) * original.Width];
}
//Fill the part with the extracted data
part.SetData<Color>(partData);
//Stick the part in the return array:
r[index++] = part;
}
//Return the array of parts.
return r;
}
And here's an example of how to use it:
protected override void LoadContent()
{
//Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
Texture2D tex = Content.Load<Texture2D>("MyTexture");
parts = Split(tex, 10, 10, out xCount, out yCount);
}
Texture2D[] parts;
int
xCount,
yCount,
partWidth = 10;
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin(SpriteSortMode.Texture, BlendState.Opaque);
for (int y = 0; y < yCount; y++)
for (int x = 0; x < xCount; x++)
spriteBatch.Draw(parts[x + y * xCount], new Rectangle(10 + x * 40 + x * 10, 10 + y * 40 + y * 10, 40, 40), Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
Please realize that this is not quite the most efficient way to do what you want, but it is very maintainable and easy to understand (I hope).
If you're looking for more efficiency, and have some experience with XNA, I would recommend using RenderTargets1. Just set each texture "part" in your array as a render target, then draw the original large texture, offset by the position of the part you're drawing. Be aware that this method requires your XNA project to target the Hi-Def profile 99% of the time, which is why I couldn't give you a working sample with that method (my current computer doesn't support the Hi-Def profile). I have used RenderTargets to do this exact thing in the past, though, so it's possible. It's also much easier2 now than in previous versions of XNA, thanks to the RenderTarget changes in XNA Game Studio 4.03.
Please feel free to comment if you need any clarification or more help :)
Links (Sorry- I'm a new user, so I can't post hyperlinks):
- http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.graphics.rendertarget%28v=xnagamestudio.31%29.aspx
- http://blogs.msdn.com/b/shawnhar/archive/2007/02/04/xna-rendertarget-semantics.aspx
- http://blogs.msdn.com/b/shawnhar/archive/2010/03/26/rendertarget-changes-in-xna-game-studio-4-0.aspx