How to make an awesome sprite engine

Started by
7 comments, last by Muzlack 21 years, 5 months ago
Ok, I made a sprite engine that I plan on improving pretty soon here. Let me describe it. The engine has loads a bitmap onto a directdraw surface. Then it has an x and y of where it is on screen. It also has an array of rects that holds a rectangle for each fram on the bitmap. I know people have done this b4. The image is divided into a grid. I have a function called CFFromCell which will do what it says, create frame from cells. You pass it the cell x and y and it will figure out based on width and height where it is. Here''s an example image. Now, you also have to give the frame a #, so I have a total of a maximum of 100 frames. So in this, frame 0,0 is 0 1,0 is 1 etc. Next, you can make animations by doing this: int anim[]={0,1,0,1}; CreateAnim(sprite,0, Anim); This will make an animation 0 = 0 1 0 1 and it will display in this order. Now, here''s what I want to do. I want to make it automatically load up the frames by doing some math calculation. What I mean is, I would like it to be able to determine where the rectangles are. that way it will automatically fill in the information. How would you suggest doing this? Secondly, is there a way that I can make it load the animations as well without being extremely complex? Lastly, I could make a really simple program that would ouput a file like Sprite.dat with the information of a sprite. I could make a program called spritemaker and you could develop sprites from an image file and assign all the variables beforehand. The only problem would be that I can''t figure out how to save a directdraw surface. How I would plan to do this would be to use the fwrite command to save the entire structure onto the file. However, this would not work because the directdraw surface can''t be loaded by fread. How can I get a surface to load from a file? My last plan for improvement is the complete port to direct3d. So I''d need to know how to do the above with direct3d too. --Muzlack
--Muzlack
Advertisement
It looks like your frames are a uniform size. What I''ve done with this in the past is written a sprite object that loads the bitmap into a surface, like you''re doing, but I''ve arranged the cells next to each other. When blitting, all I have to do then is just change the source rectangle by multiplying the frame number by the width of the cell, something like this:

src_rect.Left = frame * cell_width;
src_rect.Top = 0;
src_rect.Right = src_rect.Left + cell_width;
src_rect.Bottom = cell_height;


To do animations, just set the frame to the number you want.
Instead of writing the surface to the file, you might just write the location of the bitmap and create the surface at runtime.
Hope this helps....

I am a Jedi, like my father before me.
I''m sorry, I may have not been clear enough, I already do do that, DukeAtreides076. What I want is to be able to have ununiformed size cells. And, I want the engine to automatically pick up the rectangles from the ununimormed size rectangles. Maybe the color 255,0,255 in the corners? I''m not sure. Anyways, I also wanted to know how I could store a directdraw surface into a file so that the whole thing can be fread.
--Muzlack
Why not make lots of small pictures instead of one big one? Each animation frame would be one picture. Then you''d have no trouble determining how big the sprites are.
The problem with having lots of small pictures is that you would have to make a separate surface for each one... and that would take alot of memory... when using cells that aren''t uniform, you might want to use a lookup table for the rectangles that is loaded when the app starts. To get the rectangles from the bitmap, you could do something like you said, put dots in the corners or a border and read it, or you could write all the locations and frame numbers to a file beforehand and read it at runtime.
I don''t think you can write an entire surface to a file and read it, but you could write data about it and then just create it from that.

I am a Jedi, like my father before me.
quote:Original post by DukeAtreides076
The problem with having lots of small pictures is that you would have to make a separate surface for each one... and that would take alot of memory...


I think the memory stays the same because of the way bitmaps are stored. I mean 2 32x32 bitmaps are the same as 1 64x64 bitmap. Anyway, it''s not the memory, but the variables! I can''t imagine if you have 100 sprites, you have 100 different variables!



My compiler generates one error message: "does not compile."
quote:Original post by alnite
Original post by DukeAtreides076
I mean 2 32x32 bitmaps are the same as 1 64x64 bitmap.

The same as 4 32x32 bitmaps. If you''re writing a software blitter it''s not really a problem, if you''re using 3D hardware then you''ll want to store as many images as possible in a single texture in order to minimize texture switches, even though for a sprite based game the performance hit shouldn''t be too bad, depending on what you''re doing and how you''re doing things.

but what is important is I want to not have to include the bitmap. So I need to make sure the bitmap information is intact;

--Muzlack
Ok, let me post some code:

this is my sprite struct:

  typedef struct tagSPRITE {	int x,y; //x and y of sprite	int fullwidth,fullheight; //width and height of image	short *surfacedata; //used for saving	bool animate; //is it animated?	int width,height; //width and height of sprite TODO add arrays	RECT frames[150]; //frames	int counter; //counter for animation	int updatecounter; //how many runthroughs	int state; //the current state it is in	int curframe; //current frame (from rect frames[150]	int curanim; //current animation from anims[20]	int *anims[20]; //the animations	int curanimframes; //how many frames in the current anim	int indexinanim; //which frame in the animation are we in?	int runthroughs; //how many times have we run through the animation	LPDIRECTDRAWSURFACE7 surf;} SPRITE, *SPRITEPTR;  


I think most of it speaks for itself
here is my saving/loading code:

  void SaveSprite(SPRITEPTR sprite, char *filename) {	FILE *fp=fopen(filename,"wb");	FILE *fp2=fopen("debug2.txt","w");	fprintf(fp2,"%d %d",sprite->fullwidth,sprite->fullheight);	fclose(fp2);	sprite->surf->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR| DDLOCK_WAIT, NULL); 	sprite->surfacedata=(short *)ddsd.lpSurface;	fwrite(&sprite,sizeof(sprite),1,fp);	sprite->surf->Unlock(NULL);	fclose(fp);}  

notice the fp2. I''ve tested it and this DOES have the corrent surface width and surface height
Next, we load it.

  void LoadSprite(SPRITEPTR sprite, char *filename) {	FILE *fp=fopen(filename,"rb");	fread(&sprite,sizeof(sprite),1,fp);	FILE *fp2=fopen("debug2.txt","w");	fprintf(fp2,"%d %d",sprite->fullwidth,sprite->fullheight);	fclose(fp2);	CreateSurf(sprite->fullwidth,sprite->fullheight, 0);	sprite->surf->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR| DDLOCK_WAIT, NULL); 	short *surfacedata=(short *)ddsd.lpSurface;	memcpy(surfacedata,sprite->surfacedata,sizeof(sprite->surfacedata));	//surfacedata=sprite->surfacedata;	sprite->surf->Unlock(NULL);	fclose(fp);}  

This, however has 0 and 0 for the surface width and surfaceheight

Why would this happen? I am still don''t understand how to save and load binary files, so I''ll need some help crakin'' this.

[/source]


--Muzlack
--Muzlack

This topic is closed to new replies.

Advertisement