Kris Keillor
Kris Keillor

Reputation: 47

Texture2D.GetData "Index out of range"

I'm trying to integrate per-pixel collision with spritesheets in my XNA game. I'm mostly basing it off of this, but it's not working for me.

Here's what I'm doing to get data from a sprite in the top left corner of my spritesheet. It seems to be working fine - no errors, at least.

Rectangle SpriteSource = new Rectangle(0, 0, 32, 32);
ColorData = new Color[SpriteSource.Width * SpriteSource.Height];
Owner.Spritesheet.GetData(0, SpriteSource, ColorData, SpriteSource.X * SpriteSource.Y, 
SpriteSource.Width * SpriteSource.Height);

Now to get a sprite that's not in the top left:

Rectangle SpriteSource = new Rectangle(48, 32, 16, 32);
ColorData = new Color[SpriteSource.Width * SpriteSource.Height];
Owner.Spritesheet.GetData(0, SpriteSource, ColorData, SpriteSource.X * SpriteSource.Y,
SpriteSource.Width * SpriteSource.Height);

Exact same code, except for offsetting the rectangle by (48, 32). For some reason though, it throws the exception "This parameter must be a valid index within the array. Parameter name: dataIndex"

What am I doing wrong? What is dataIndex referring to in this instance - the ColorData array, or the actual Texture2D? Also, if I haven't done any special 'mipmapping' - not entirely sure what that is but I have a rough idea - I would use 0 as as the mipmapping level, right?

EDIT: Some more info (SS = SpriteSource, O.Tex = Owner.Spritesheet):

As long as SS.X <= O.Tex.Width - SS.Width and SS.Y == 0, the code compiles/runs fine. If SS.X > O.Tex - SS.Width, it produces a totally expected "The rectangle is too large or too small for this resource" error. Same for changing the Y and keeping X at zero.

However, if all the following are true: SS.X > 0 && SS.Y > 0 && (SS.X * SS.Y) < (SS.Width * SS.Height), the similarly frustrating yet different error "This parameter must be a valid index within the array. Parameter name: elementCount" is produced.

EDIT2: Seems I was slightly mistaken about the elementCount error, it can be produced under conditions where SS.X * SS.Y > SS.Width * SS.Height. I'm glad such a stupid condition isn't part of the problem, at least.

Upvotes: 0

Views: 422

Answers (1)

user1323245
user1323245

Reputation: 638

I'm not a XNA programmer, but if Spritesheet is a Texture2D I believe I know why you have a problem. Let's take a closer look at the parameters:

  • int level - Mipmap level
  • Nullable - The section of the texture to copy. null indicates the data will be copied from the entire texture
  • T[] data - Array of data int
  • startIndex - Index of the first element to get
  • int elementCount - Numnber of elements to get

Since you pass in SpriteSource as the second parameter you have already selected a sub-section of the texture. The fourth parameter is the start index of the rectangle (SpriteSource) you pass in as the second parameter!

In the first case everything works as expected because you effctively pass in 0 as the fourth parameter to GetData (both SpriteSource.X and SpriteSource.Y are 0, and 0 * 0 = 0). The second case fails because you are saying that the start index should be 1024, which is greater than the size of SpriteSource (16 * 32 = 512). If you pass in 0 as the forth parameter it would work since it would mean "start at index 0 in SourceSprite".

So, if SourceSprite always is the rectangle of the sprite in the spritesheet that you want, pass in 0 as startIndex and you'll get the sprite you are after.

I think...

Upvotes: 1

Related Questions