[SDL] grabframe

David Olofson david at olofson.net
Sun Jan 23 02:29:47 PST 2005

On Sunday 23 January 2005 01.25, NighTiger wrote:
> Hi guys,
> I studied from a book a good function that grabs the frame of
> sprite. This function is write using the allegro libraries, so I
> translated it in SDL:
> SDL_Surface *grabframe(SDL_Surface *source, int width, int height,
> int startx, int starty,
>                       int columns, int frame)
> {
>   SDL_Surface *temp = NULL;
>   int x = startx + (frame % columns) * width;
>   int y = starty + (frame / columns) * height;
>   src.w = width;
>   src.h = height;
>   src.x = x;
>   src.y = y;
>   dest = src;
>   SDL_BlitSurface(source,&src,temp,&dest);
>   return temp;
> }
> now I've a problem... when I use the function in this way
> SDL_BlitSurface(grabframe(tiles, TILEW, TILEH, 0, 0, COLS, 1),
> NULL, scr, NULL);
> that doesn't work...
> Anybody can say me why?

You're blitting to a NULL pointer rather than a destination surface. A 
segfault/GP fault is to be expected. Also, that function shouldn't 
even compile, unless 'src' and 'dest' are global temporary variables 
- which would be a shooting offence! :-)

You should replace 'NULL' in the first line with a call to 
SDL_CreateRGBSurface(), or otherwise create a surface of the right 
size (one sprite frame) and pixel format. You should also replace the 
line "dest = src;" with something like "dest.x = dest.y = 0;", or 
you'll just blit all except the first frame outside the temp surface, 
for no effect.

Furthermore, you should use this function only once per sprite frame 
(at load time), and you should use SDL_DisplayFormat() or 
SDL_DisplayFormatAlpha(). Otherwise, all you achieve is adding a lot 
of overhead instead of avoiding the (potentially expensive) "source 
surface clip", which is one of very few reasons to do anything like 
this at all.

If you aren't optimizing for speed, are blitting opaque rectangles, or 
have the luxury of controlling exactly what platform and hardware 
your code will run on, you can just blit directly from the source 
"palette" surface to the screen:

void blitframe(SDL_Surface *source, int fwidth, int fheight, int 
frame, SDL_Surface *dest, int x, int y)
 SDL_Rect sr;
 SDL_Rect dr;
 int columns = source->width / fwidth;
 sr.x = (frame % columns) * fwidth;
 sr.y = (frame / columns) * fheight;
 sr.w = fwidth;
 sr.h = fheight;
 dr.x = x;
 dr.y = y;
 SDL_BlitSurface(source, &sr, dest, &dr);

(Not tested - beware of typos.)

//David Olofson - Programmer, Composer, Open Source Advocate

.- Audiality -----------------------------------------------.
|  Free/Open Source audio engine for games and multimedia.  |
| MIDI, modular synthesis, real time effects, scripting,... |
`-----------------------------------> http://audiality.org -'
   --- http://olofson.net --- http://www.reologica.se ---

More information about the SDL mailing list