Sign in to follow this  

Blitting a surface but reflected

This topic is 4354 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi I want to be able to draw surfaces reflected on the x axis somtimes in my game. I have made this function to do it, but I'm not convinced I did it in a good way and it doesn't seem to use colour keys when its flipped :(. What do you think of the way I did it / is there a better way? Thanks
void blitsurface(SDL_Surface *src_surface, SDL_Rect *src_rect, SDL_Surface *dest_surface, SDL_Rect *dest_rect, bool x_flip)
{
    if (x_flip == true)
    {
        SDL_Surface *flipped_surface;
        flipped_surface = SDL_CreateRGBSurface(SDL_SWSURFACE, src_rect->w, src_rect->h, 32, rmask, gmask, bmask, amask);

        if(flipped_surface == NULL)
        {
            cerr << "Failed to create surface for flipped image\n";
            exit(1);
        }

        // If the surfaces need to be locked, lock em
        if ( SDL_MUSTLOCK(src_surface) )
        {
            if ( SDL_LockSurface(src_surface) < 0 )
            {
                cerr << "Can't lock the surface.\n";
                exit(1);
            }
        }

        if ( SDL_MUSTLOCK(dest_surface) )
        {
            if ( SDL_LockSurface(dest_surface) < 0 )
            {
                cerr << "Can't lock the surface.\n";
                exit(1);
            }
        }
        
        // Actually do the reflected blit
        for (int i = 0; i < src_rect->h; i++)
        {
            for (int j = 0; j < src_rect->w; j++)
            {
                Uint32 pixel = getpixel(src_surface, j + src_rect->x,i + src_rect->y);
                putpixel(dest_surface, (src_rect->w - j) + dest_rect->x, i + dest_rect->y, pixel);
            }
        }

        // Make sure the surfaces are unlocked again
        if (SDL_MUSTLOCK(src_surface))
            SDL_UnlockSurface(src_surface);

        if (SDL_MUSTLOCK(dest_surface))
            SDL_UnlockSurface(dest_surface);
    }
    else
        SDL_BlitSurface(src_surface, src_rect, dest_surface, dest_rect);
}

Share this post


Link to post
Share on other sites
a few things:

1) you recreate a flipped surface every time you blit
2) you never use the flipped_surface...
3) you never free the flipped surface( easy to fix )
4) to keep the colourkey, you need to copy it to the new surface
5) if you use this as your main blit function, it will be slow



SDL_Surface *make_flipped_copy( SDL_Surface *original )
{
SDL_Surface *flipped_surface;
flipped_surface = SDL_CreateRGBSurface(SDL_SWSURFACE, original->w, original->h, 32, rmask, gmask, bmask, amask);
if(flipped_surface == NULL)
{
cerr << "Failed to create surface for flipped image\n";
exit(1);
}

// If the surfaces need to be locked, lock em
if ( SDL_MUSTLOCK(original) )
{
if ( SDL_LockSurface(original) < 0 )
{
cerr << "Can't lock the original surface.\n";
exit(1);
}
}
/*
this shouldnt be nessecary,as we requested a software surface.
leave it in though, you might migrate to hardware later
and forget to change this
*/

if ( SDL_MUSTLOCK(flipped_surface) )
{
if ( SDL_LockSurface(flipped_surface) < 0 )
{
cerr << "Can't lock flipped surface.\n";
exit(1);
}
}

// Actually do the reflected blit
for (int y = 0; y < original->h; y++)
{
for (int x = 0; x < original->w; x++)
{
Uint32 pixel = getpixel(original, x ,y);
putpixel(flipped_surface, (original->w - x), y, pixel);
}
}

// Make sure the surfaces are unlocked again
if (SDL_MUSTLOCK(original))
SDL_UnlockSurface(original);

if (SDL_MUSTLOCK(flipped_surface))
SDL_UnlockSurface(flipped_surface);
}
return flipped_surface;
}









seeing as you are using c++, you can encapsulate this into a class:

class Surface
{
private:
SDL_Surface *surface,*flipped_surface;
public:
Surface( std::string &file ):surface(0),flipped_surface(0)
{
surface = SDL_LoadBMP(file.c_str());
if(!surface) {/*do something*/}
}

void draw( int x, int y, bool flipped, SDL_Surface* dest = SDL_GetVideoSurface() )
{
//setup SDL_Rects...
if( flipped )
{
if(!flipped_surface )
{
flipped_surface = make_flipped_copy( SDL_Surface *original )
}
SDL_BlitSurface(flipped_surface,...);
}
SDL_BlitSurface(surface,...);
}
};






Disclaimer: i havent tested this, this is coded out of my head. make sure its all good first

Edit: oh, and you might aswell add in a destructor that frees the surfaces if required. can't believe i fogot that.

good Luck!

Share this post


Link to post
Share on other sites
Quote:
Original post by rip-off
a few things:

1) you recreate a flipped surface every time you blit
2) you never use the flipped_surface...
3) you never free the flipped surface( easy to fix )
4) to keep the colourkey, you need to copy it to the new surface
5) if you use this as your main blit function, it will be slow

*** Source Snippet Removed ***

seeing as you are using c++, you can encapsulate this into a class:
*** Source Snippet Removed ***

Disclaimer: i havent tested this, this is coded out of my head. make sure its all good first

Edit: oh, and you might aswell add in a destructor that frees the surfaces if required. can't believe i fogot that.

good Luck!


Cool thanks, nifty idea. It also has the added advantage of seperating me from SDL a bit incase I need to change library :). Thanks

Share this post


Link to post
Share on other sites
I just did what you suggested but I have found a bit of a problem. Say the image you load is a sprite sheet with some pictures of mario doing different stuff. You only want the surface to be loaded once for all the different sprites which is fine untill you try and make the flipped copy.

If you just flip the whole image the sprites are now at the other side of the image and you just get blank space when you try and draw them. If you flip just the relevant area, you now have to have a seperate surface for each sprite.. Ahhh

Share this post


Link to post
Share on other sites
Quote:
Original post by kzar
I just did what you suggested but I have found a bit of a problem. Say the image you load is a sprite sheet with some pictures of mario doing different stuff. You only want the surface to be loaded once for all the different sprites which is fine untill you try and make the flipped copy.

If you just flip the whole image the sprites are now at the other side of the image and you just get blank space when you try and draw them. If you flip just the relevant area, you now have to have a seperate surface for each sprite.. Ahhh


well, then change the flip function =).

okay. we have a surface of numx by numy sprites, each of size w and h

SDL_Surface *flipSpriteSheet( SDL_Surface *original, int numx,int numy, int w, int h )
{
SDL_Surface *flipped_sheet = SDL_CreateRGBSurface( ... );
);
// make sure the image is of the proper size...
assert( original->w == w * numx );
assert( original->h == h * numy );
if ( SDL_MUSTLOCK(original) )
{
if ( SDL_LockSurface(original) < 0 )
{
cout << "Can't lock the surface.\n";
exit(1);
}
}
if ( SDL_MUSTLOCK(flipped_sheet) )
{
if ( SDL_LockSurface(flipped_sheet) < 0 )
{
cout << "Can't lock the surface.\n";
exit(1);
}
}

for( int spritex = 0 ; spritex < numx ; ++spritex )
{
for( int spritey = 0 ; spritey < numy ; ++spritey )
{
for( int x = 0 ; x < w ; ++x )
{
for( int y = 0 ; y < h ; ++y )
{
Uint32 pixel = getpixel( original, (w*spritex) + x,(h*spritey) + y );
putpixel( flipped_sheet, (w*spritex) +(w-1-x) ,(h*spritey) + y, pixel );

}
}

}
}

if (SDL_MUSTLOCK(original))
SDL_UnlockSurface(original);
if (SDL_MUSTLOCK(flipped_sheet))
SDL_UnlockSurface(flipped_sheet);

return flipped_sheet;
}






Share this post


Link to post
Share on other sites

This topic is 4354 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this