Jump to content
  • Advertisement
Sign in to follow this  
rpgman15

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.

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

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 this post


Link to post
Share on other sites
Advertisement
Quote:
Original post by DevLiquidKnight
A 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 this post


Link to post
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 this post


Link to post
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 in
let screen = Sdlvideo.set_video_mode ~w: 640 ~h: 480 ~bpp: 16 [] in
oursprite#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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 10
int 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 this post


Link to post
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!