3
\$\begingroup\$

So basically I'm using this:

 public bool IntersectPixels(Rectangle rectangleA, Color[] dataA,Rectangle rectangleB, Color[] dataB)
    {
        int top = Math.Max(rectangleA.Top, rectangleB.Top);
        int bottom = Math.Min(rectangleA.Bottom, rectangleB.Bottom);
        int left = Math.Max(rectangleA.Left, rectangleB.Left);
        int right = Math.Min(rectangleA.Right, rectangleB.Right);
        for (int y = top; y < bottom; y++)
        {
            for (int x = left; x < right; x++)
            {
                Color colorA = dataA[(x - rectangleA.Left) + (y - rectangleA.Top) * rectangleA.Width];
                Color colorB = dataB[(x - rectangleB.Left) + (y - rectangleB.Top) * rectangleB.Width];
                if (colorA.A != 0 && colorB.A != 0)
                {
                    return true;
                }
            }
        }
        return false;
    }

In order to detect collision, but I'm unable to figure out how to use it with animated sprites.

This is my animation update method:

public void AnimUpdate(GameTime gameTime)
    {
        if (!animPaused)
        {
            animTimer += (float)gameTime.ElapsedGameTime.TotalMilliseconds;
            if (animTimer > animInterval)
            {
                currentFrame++;
                animTimer = 0f;
            }
            if (currentFrame > endFrame || endFrame <= currentFrame || currentFrame < startFrame)
            {
                currentFrame = startFrame;
            }
            objRect = new Rectangle(currentFrame * TextureWidth, frameRow * TextureHeight, TextureWidth, TextureHeight);
            origin = new Vector2(objRect.Width / 2, objRect.Height / 2);
        }
    }

Which works with multiple rows and columns.

and how I call the intersect:

    public bool IntersectPixels(Obj me, Vector2 pos, Obj o)
{
Rectangle collisionRect = new Rectangle(me.objRect.X, me.objRect.Y, me.objRect.Width, me.objRect.Height);
                    collisionRect.X += (int)pos.X;
                    collisionRect.Y += (int)pos.Y;
if (IntersectPixels(collisionRect, me.TextureData, o.objRect, o.TextureData))
{
    return true;
}
return false;

}

Now my guess is that I have to update the textureData everytime the frame changes, no? If so then I already tried it and miserably failed doing so

Any hints, advices?

If you need to see any more of my code just let me know and I'll update the question.

Updated almost functional collisionRect:

collisionRect = new Rectangle((int)me.Position.X, (int)me.Position.Y, me.Texture.Width / (int)((me.frameCount - 1) * me.TextureWidth), me.Texture.Height);

What it does now is "move" the block up 50%, shouldn't be too hard to figure out.

Update:

Alright, so here's a functional collision rectangle(besides the height issue)

collisionRect = new Rectangle((int)me.Position.X, (int)me.Position.Y, me.TextureWidth / (int)me.frameCount - 1, me.TextureHeight);

Now the problem is that it's still not getting the correct color values of the animated sprite.

So it detects properly but the color values are always:

R:0 G:0 B:0 A:0

↑↑↑ disregard that, it's not true after all.

For some reason now the collision area height is only 1 pixel..

\$\endgroup\$
7
  • \$\begingroup\$ Pixel perfect collision is hard. I got it to working after a lot of pain. Why do you need it? \$\endgroup\$
    – ashes999
    Commented May 29, 2012 at 20:53
  • \$\begingroup\$ Because my sprites have transparent areas, it works perfectly with still sprites but when it's animated it doesn't do anything. I already have a check for rectangle collision first and if that's true it goes to pixel detection. \$\endgroup\$
    – Jixi
    Commented May 29, 2012 at 20:56
  • \$\begingroup\$ From what I recall, the main problem was that the TextureData refers to the non-scaled, non-rotated image; you need to modify it accordingly (or iterate accordingly over the right area) to get pixel perfect collision. \$\endgroup\$
    – ashes999
    Commented May 29, 2012 at 21:14
  • \$\begingroup\$ What does Vector2 pos do? It's never touched in your small IntersectPixels. \$\endgroup\$
    – Hackworth
    Commented May 29, 2012 at 21:36
  • \$\begingroup\$ Sorry about that, forgot to update it into it.. it's there to prevent the sprite for getting stuck, it's the movement speed of the sprite. Updating the question \$\endgroup\$
    – Jixi
    Commented May 29, 2012 at 21:59

1 Answer 1

1
\$\begingroup\$

It looks to me like you collide the wrong Rectangles. What you want for you collision rectangles for an object o is something like o.Position (a Vector2) plus the dimensions of its texture size:

o.collisionRect = new Rectangle(o.Position.X, o.Position.Y, o.TextureWidth, o.TextureHeight)

What you are currently taking as the collision rectangle is the source rectangle, the rectangle that tells you which part of the sprite sheet you want to draw for your current animation frame, which has nothing to do with your object's position:

objRect = new Rectangle(currentFrame * TextureWidth, frameRow * TextureHeight, TextureWidth, TextureHeight);


Rectangle collisionRect = new Rectangle(me.objRect.X, me.objRect.Y, me.objRect.Width, me.objRect.Height);
                collisionRect.X += (int)pos.X;
                collisionRect.Y += (int)pos.Y;

You also add a Vector2 pos, which you described in the comments as the object velocity vector, which would make even less sense; though by the name pos I guess you meant the right thing, the position vector, the object's location.

So you got it half right: the mistake was that you added that position vector to the sprite sheet source rectangle (which has varying X and Y values), instead of the object's dimensions (which, expressed as a rectangle, always has position (0, 0)).

Assuming your default, non-animated source rectangle is located at (0, 0) on the sprite sheet, it would explain why collision is working when not animated, because you happen to have a rectangle with the correct location, i.e. (0, 0). But as soon as you start animating, the X and Y coordinates are wrong, because you always need (0 + pos.X, 0 + pos.Y), but you get something other than 0, depending on your currentFrame and frameRow.

\$\endgroup\$
4
  • \$\begingroup\$ Exactly what i started doing a moment ago ^^ collisionRect = new Rectangle((int)me.Position.X, (int)me.Position.Y, me.Texture.Width / (int)((me.frameCount - 1) * me.TextureWidth), me.Texture.Height); Now that almost works, it has some weird problems with getting the correct height position of the obstacle, even when using a single row spritesheet.(half of the block is above the block as an invisible block and half of the bottom is missing, like it moved 50% up). Once i figure that out it's pretty much perfect. Edit. and yeah the pos is a temporary position modifier. \$\endgroup\$
    – Jixi
    Commented May 29, 2012 at 22:27
  • \$\begingroup\$ @Jixi If I answered your original question, consider an upvote and accept. \$\endgroup\$
    – Hackworth
    Commented May 29, 2012 at 22:39
  • \$\begingroup\$ Sadly i can't upvote yet =( I'll definitely accept it though once i get it 100% functiona =) \$\endgroup\$
    – Jixi
    Commented May 29, 2012 at 22:50
  • \$\begingroup\$ Right, forgot about that. Cheers. \$\endgroup\$
    – Hackworth
    Commented May 29, 2012 at 22:55

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .