Public Group

# Blitting a surface but reflected

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

## 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;

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 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 on other sites
Quote:
 Original post by rip-offa few things:1) you recreate a flipped surface every time you blit2) 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 surface5) 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 firstEdit: 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 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 on other sites
Quote:
 Original post by kzarI 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;}

1. 1
Rutin
39
2. 2
3. 3
4. 4
5. 5

• 12
• 17
• 12
• 14
• 9
• ### Forum Statistics

• Total Topics
633358
• Total Posts
3011509
• ### Who's Online (See full list)

There are no registered users currently online

×