Animating a Sprite in SDL

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

Recommended Posts

Ok I read the tutorial on it cone3d.gamedev.net. So do the sprites I want to animate have to be a animated gif or can it be a series of bitmaps?

Share on other sites
A series of bitmaps is how I would do it. Its much easier then extracing the gif data.

Share on other sites
Quote:
 Original post by DevLiquidKnightA series of bitmaps is how I would do it. Its much easier then extracing the gif data.

In addition, not just a series of seperate files, but rather a BMP sheet of the sprites could be an effecient way to do it as well. With SDL, it's really easy to use sprite sheets too.

Share on other sites
To elaborate a bit on the previous post, for a sprite sheet all you need to do to animate it is, instead of resetting the sprite variable or iterating through an array, just make a class or structure so that telling it to switch to a different frame results in the image's src_rect being moved to the appropriate section of the image.

Share on other sites
Could you tell me what SDL function would be best for this? Or how I would exactly do this?

Share on other sites
Ummmm. The only example of actual code I have on hand is in O'Caml. I would translate it to C, but knowing me I'd mess something up and only confuse you more. But here goes...

class sprite =object (self)  val img = loadBMP "image.bmp"  val imgw = (* whatever the total image width is *)  val imgh = (* whatever the total image height is *)  val mutable numframes = (* However many frames you have *)  val mutable currentframe = 0  (* This is the SDL_rect that tells us where on img we want to blit from      We're going to "scroll" this back and forth along the image's X axis to change     frames in the animation *)  val frame = {r_x = 0; r_y = 0; r_w = 0; r_h = 0}  (* This is the SDL_rect that tells us where on whatever surface we want to blit to *)  val dest = {r_x = 0; r_y = 0; r_w = 0; r_h = 0}  (* We initialize the rects with the correct width and height... we're only going to     be moving the frame along the X axis, since it's simpler  *)  initializer    frame.r_w <- imgw / numframes;    frame.r_h <- imgh;    dest.r_w <- frame.r_w;    dest.r_h <- imgh;	  (* Methods to get current animation index and to move the frame to a new animation *)  method getCurrentFrame = currentframe  method setFrame n =     currentframe <- n mod numframes;    frame.r_x <- currentframe * frame.r_w  method nextFrame =    currentframe <- (currentframe + 1) mod numframes;    self#setFrame currentframe  method prevFrame =    currentframe <- abs ((currentframe - 1) mod numframes);    self#setFrame currentframe      (* Sets the destination rect to wherever we want *)  method moveTo x y =    dest.r_x <- x;    dest.r_y <- y  (* This actually blits our image to the given surface *)  method blit dst =    (* We make sure the destination coordinates are actually inside the surface *)    let dstw, dsth, _ = (surface_dims dst) in      if dest.r_x > dstw || dest.r_y > dsth then	()      else	blit_surface ~src: img ~src_rect: frame ~dst: dst ~dst_rect: dest ();end;;

So to actually use this we'd do something like
(* Set up video mode, yadda yadda *)Sdl.init [EVERYTHING];let oursprite = new sprite inlet screen = Sdlvideo.set_video_mode ~w: 640 ~h: 480 ~bpp: 16 [] inoursprite#moveto 100 100;while true do   oursprite#nextFrame;   oursprite#blit screen;   flip screen;done;Sdl.quit ();

Then image.bmp is just a single bitmap that has all the different animation frames you want for whatever particular effect.

Hope that helps. I apologize for the obscure code, but I can't stand C++.

Share on other sites
If you take a look at the SDL_BlitSurface function, you notice a couple things:
int SDL_BlitSurface(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect);
See the srcrect parameter? You can use this to denote where on the surface you are going to be blitting from. If you make a new rectangle object and set it to the individual tile on the surface, you can effectively make it blit only one segment of the sprite tile sheet. I'll let you figure out your own implementation of it as that's the only way you'll truly learn [smile].

Share on other sites
Awhile ago I wrote a c++ class for dealing with SDL_Surface. You can take a look at it here. It comes with a example app showing a basic way to do some animation with a sprite sheet.

It only has a Makefile, so if you're not using some form of unix you'll probably need to create your own project in whatever dev environment you're using.

I'm also planning on cleaning it up at some point in the future - the graphics could definately use some work, but feel free to learn from it or use it.

Share on other sites
@WillF

I tried to compile your code but when it exucutes it just flashes the window and closes itself

@Rob I tried what you said and got it to blit each frame if I changed the CURRENT_FRAME value manually before I compile but when I try to advance the frame in my while loop it does nothing. I'm going to post my code to see if you can see what's wrong.

#include stdio.h;#include stdlib.h;#include SDL/SDL.h;SDL_Surface *back;SDL_Surface *screen; #define NUM_FRAMES  10int CURRENT_FRAME = 0;int xpos2 = 27 * CURRENT_FRAME;int ypos2 = 3;int xpos  = 300;int ypos  = 400;int InitImages(){  back = SDL_LoadBMP("Gfx/A_WALK_D.bmp");         return 0;}void DrawIMG(SDL_Surface *img, int x, int y, int w, int h, int x2, int y2){  SDL_Rect dest;  dest.x = x;  dest.y = y;  SDL_Rect dest2;  dest2.x = x2;  dest2.y = y2;  dest2.w = w;  dest2.h = h;  SDL_BlitSurface(back, &dest2, screen, &dest);}void DrawSprite(){  DrawIMG(back, xpos, ypos,27,46,xpos2,ypos2);   }void AdvanceFrame(){  CURRENT_FRAME plusplus;    if(CURRENT_FRAME &gt; 10) { CURRENT_FRAME = 0;}}   void DrawScene(){ DrawSprite();  AdvanceFrame();}int main(int argc, char *argv[]){  Uint8* keys;        InitImages();        if ( SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO) &lt; 0 )  {    printf("Unable to init SDL: %s\n", SDL_GetError());    exit(1);  }  atexit(SDL_Quit);    SDL_WM_SetCaption("DarkSword","darksword");   screen=SDL_SetVideoMode(800,600,32,SDL_HWSURFACE|SDL_DOUBLEBUF);  if ( screen == NULL )  {    printf("Unable to set 800x600 video: %s\n", SDL_GetError());    exit(1);  }    DrawScene();  int done=0;      SDL_Event event;     while(done == 0)             while ( SDL_PollEvent(&event) )    {      if ( event.type == SDL_QUIT )  {  done = 1;  }      if ( event.type == SDL_KEYDOWN )            {                   if ( event.key.keysym.sym == SDLK_ESCAPE ) { done = 1; }                              }          DrawScene();         }             return 0;}`

[Edited by - rpgman15 on July 20, 2005 5:17:22 PM]

Share on other sites
It's been a couple days and I still haven't figured it out. It has me burnt out trying to figure it out on my own so I would appreciate a lil more guidance.

1. 1
2. 2
Rutin
19
3. 3
khawk
15
4. 4
A4L
13
5. 5

• 13
• 26
• 10
• 11
• 44
• Forum Statistics

• Total Topics
633744
• Total Posts
3013657
×