honigbeutler - 2013-05-01

I dont now if there is any interrest in this but i had a little problem with my project using tilesets. So i updated this two functions to support an offset of pixels.

/*
SDL_Collide: A 2D collision detection library for use with SDL

MIT License
Copyright 2005-2006 SDL_collide Team
http://sdl-collide.sourceforge.net
All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

Amir Taaki
genjix@gmail.com

Rob Loach
http://robloach.net

*/

int SDL_CollideTransparentPixel(SDL_Surface surface , int u , int v, int w, int h, SDL_Rect offset)
{
if(SDL_MUSTLOCK(surface))
SDL_LockSurface(surface);
/
assert that (u,v) offsets lie within surface*/
assert((u < w) && (v < h));

int bpp = surface->format->BytesPerPixel;
/*here p is the address to the pixel we want to retrieve*/
Uint8 *p = (Uint8 *)surface->pixels + (v + offset.y) * surface->pitch + (u+offset.x) * bpp;

Uint32 pixelcolor;

switch(bpp)
{
    case(1):
        pixelcolor = *p;
    break;

    case(2):
        pixelcolor = *(Uint16 *)p;
    break;

    case(3):
        if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
            pixelcolor = p[0] << 16 | p[1] << 8 | p[2];
        else
            pixelcolor = p[0] | p[1] << 8 | p[2] << 16;
    break;

    case(4):
        pixelcolor = *(Uint32 *)p;
    break;
}

if(SDL_MUSTLOCK(surface))
    SDL_UnlockSurface(surface);
/*test whether pixels color == color of transparent pixels for that surface*/
return (pixelcolor == surface->format->colorkey);

}

/
SDL pixel perfect collision test
/
int SDL_CollidePixel(SDL_Surface as , int ax , int ay , int aW, int aH, SDL_Rect offset,
SDL_Surface
bs , int bx , int by, int bW, int bH, SDL_Rect offset1, int skip)
{
/a - bottom right co-ordinates in world space/
int ax1 = ax + aW - 1;
int ay1 = ay + aH - 1;

/*b - bottom right co-ordinates in world space*/
int bx1 = bx + bW - 1;
int by1 = by + bH - 1;

/*check if bounding boxes intersect*/
if((bx1 < ax) || (ax1 < bx))
    return 0;
if((by1 < ay) || (ay1 < by))
    return 0;

/Now lets make the bouding box for which we check for a pixel collision/

/*To get the bounding box we do
        Ax1,Ay1______________
            |                |
            |                |
            |                |
            |    Bx1,By1____________
            |        |       |      |
            |        |       |      |
            |________|_______|      |
                     |    Ax2,Ay2   |
                     |              |
                     |              |
                     |___________Bx2,By2

To find that overlap we find the biggest left hand cordinate
AND the smallest right hand co-ordinate

To find it for y we do the biggest top y value
AND the smallest bottom y value

Therefore the overlap here is Bx1,By1 --> Ax2,Ay2

Remember    
        Ax2 = Ax1 + SA->w
        Bx2 = Bx1 + SB->w

        Ay2 = Ay1 + SA->h
        By2 = By1 + SB->h
*/

/*now we loop round every pixel in area of
intersection
    if 2 pixels alpha values on 2 surfaces at the
    same place != 0 then we have a collision*/
int xstart = SDL_COLLIDE_MAX(ax,bx);
int xend = SDL_COLLIDE_MIN(ax1,bx1);

int ystart = SDL_COLLIDE_MAX(ay,by);
int yend = SDL_COLLIDE_MIN(ay1,by1);

for(int y = ystart ; y <= yend ; y += skip)
{
    for(int x = xstart ; x <= xend ; x += skip)
    {
        /*compute offsets for surface
        before pass to TransparentPixel test*/
        if(!SDL_CollideTransparentPixel(as , x-ax , y-ay, aW, aH, offset)
        && !SDL_CollideTransparentPixel(bs , x-bx , y-by, bW, bH, offset1))
            return 1;
    }
}

return 0;

}

The using style is the same but now u have to give the width of set tile in the surface plus the offset of pixels it has in the image itself in form of an sdl_rect. (u could change the offset sdl_rect to x and y offset. i just used it because it fitted my project)