animation?

Started by
12 comments, last by scourgez 17 years, 11 months ago
question for you all. when you animate your sprites, do you use a sprite sheet and iterate through all the different stills? if so, could someone please show me an example (i can't grasp this concept for some reason) or, do you predefine all your sprite locations in a header file / in the main code?
My tech blogEasy Tech Talk
Advertisement
Well if you have a sheet with all your animation frames just say a single frame is 32x32 or something, and then say the first frame is at the top left, the next frame is directly to the left of it and so on, when you reach the end of a row start at the left of the next.

Actually calculating the coordinates of a frame in an image given it's frame number is pretty easy, just do something like this, width is in sprite units (i.e. how many frames fit in a single width). Note the first frame is frame 0.

int frameX = frame % width;int frameY = frame / width;int pixelX = frameX * frameWidth;int pixelY = frameY * frameHeight;


well the thing is, the tutorials ive read predefine the rectangles around their images. but for a game like street fighter 3, where they have 12 frames for one animation, of one character, i highly doubt that they hardcode it.

im just trying to figure out how to scan through a bmp of frames for an animation. i can see it being a for loop, but the specifics are what get me.

btw im using SDL and C++ for this
My tech blogEasy Tech Talk
Street fighter may use sprite sheets, in which case you use the code I gave above to calculate where on the sprite sheet a particular frame is.

Another possiblity is having a seperate image per frame in which case you just store them in an array indexed by frame number.

To actually perform the animation you just have a variable with the current frame somewhere and then use that to draw the correct frame when performing your drawing. Every frame you'll also want to call an update method that will calculate the time that has passed since the last update and if it is over a certain amount increment the current frame.
The way I handle bitmap animation is to load a bitmap into a surface then calculate the rectangle position of each tile, each tile is arranged side by side in a bitmap file with no seperator lines.

The initialization of the tileset needs to know the width and height of tiles, I let the caller of the init function provide these.

The idea is to get an array of RECT's where 0 is the first image and the last is sizeof(rect)-1,

[0][1][2][3]
[4][5][6][7]
etc...

Then you can have a function

void Draw(int index, int x, int y)
{
Blt(&backbuffer, &rect[index], x, y);
}

//a call might look like this
Draw(player.get_frame(), player.x, player.y);

I have code that shows how this works on my other computer, and I will post later.
-----------------------------Language: C++API: Win32, DirectXCompiler: VC++ 2003
cool, thanks to both of you, its helping me understand a bit more on the subject.

i get how animation works but for some reason my brain doesn't wanna understand the coding. i think once i see the sample you speak of it will clarify it enough
thanks again and i await you next post on this :)
My tech blogEasy Tech Talk
The use of rectangular sprite cells is not your only option, and can even be inefficient. If, for instance, the dimensions of your sprites' bounding rectangles vary significantly, then there'll be a lot of "dead space" in the cells, which is just unnecessary memory consumption.

Another option is to use a specific color key in the image to define the bounding regions (if you're extracting them from a single sprite sheet) or per-cell images in a specialized editor, and use a hotspot to tie the positions of the sprites together for smooth animation.

Google for code. It was a very common extraction technique with indexed palette images (8-bit).
Quote:Original post by Oluseyi
The use of rectangular sprite cells is not your only option, and can even be inefficient. If, for instance, the dimensions of your sprites' bounding rectangles vary significantly, then there'll be a lot of "dead space" in the cells, which is just unnecessary memory consumption.

Another option is to use a specific color key in the image to define the bounding regions (if you're extracting them from a single sprite sheet) or per-cell images in a specialized editor, and use a hotspot to tie the positions of the sprites together for smooth animation.


Or define the bounding regions in a separate file, perhaps hacking together a tool to help edit that file. That allows you to avoid worrying about 'fixing' the colour-keyed pixels and to have your sprites fill their whole bounding rectangles (you could get around that with a colour-key approach, but you'd basically end up drawing boxes with the key colour around each sprite, still wasting a little space there). This is also useful with APIs that treat loaded images as write-(and blit-)only.
Here is something for you to chew on. [smile]

char* bmp_file;int bmp_width, bmp_height;IDirectDrawSurface7* lpdds;	RECT* tile_rect;int tile_width;int tile_height;int tile_rows;int tile_cols;int tile_num;void tileset::Load(char* arg_file, int arg_tilewidth, int arg_tileheight){    //Load bitmap	bmp_file = arg_file;	lpdds = ddgfx::LoadBitmapSurface(bmp_file);    //Get bitmap size	DDSURFACEDESC2 ddsd = {0};	ddsd.dwSize = sizeof(ddsd);	lpdds->GetSurfaceDesc(&ddsd);	bmp_width = ddsd.dwWidth;	bmp_height = ddsd.dwHeight;    //Compute rows and collums	tile_width = arg_tilewidth;	tile_height = arg_tileheight;	tile_cols = bmp_width / tile_width;	tile_rows = bmp_height / tile_height;		//Allocate an array of RECT's	tile_rect = new RECT[tile_rows * tile_cols];	tile_num = 0;    //Set the rects to the correct position	for(int y=0; y<tile_rows; y++)		for(int x=0; x<tile_cols; x++)		{			tile_rect[tile_num].left = x*tile_width;			tile_rect[tile_num].top = y*tile_height;			tile_rect[tile_num].right = tile_rect[tile_num].left + tile_width;			tile_rect[tile_num].bottom = tile_rect[tile_num].top + tile_height;			++tile_num;		}	}void tileset::Unload(){	delete[] tile_rect;	lpdds->Release();	lpdds = 0;}void tileset::Draw(int index, int x, int y){	RECT src = tile_rect[index];	RECT dst = { x, y, x + tile_width, y + tile_height};	lpddsback->Blt(&dst, lpdds, &src, DDBLT_WAIT, 0);	}
-----------------------------Language: C++API: Win32, DirectXCompiler: VC++ 2003
cool thanks. now i see that it is in DX7, is there any big difference that i should know about for putting it into DX9 other than changing IDirectDrawSurface7* lpdds; ?
My tech blogEasy Tech Talk

This topic is closed to new replies.

Advertisement