Archived

This topic is now archived and is closed to further replies.

Muzlack

How to make an awesome sprite engine

Recommended Posts

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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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."

Share this post


Link to post
Share on other sites
quote:
Original post by alnite
[quote]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.

Share this post


Link to post
Share on other sites
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;

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites