www.pudn.com > c_TANK_code.rar > SONBACK.C, change:2001-09-14,size:16826b


#include <io.h> 
#include <bios.h> 
#include <conio.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <dos.h> 
#include <bios.h> 
#include <fcntl.h> 
#include <mem.h> 
#include <math.h> 
#include <string.h> 
#include <malloc.h> 
#include <time.h> 
 
#define TANK_SPEED 4 
#define PI (float)3.14159 
 
#define sprite_SPEED 4 
 
#define SPRITE_DEAD 0 
#define SPRITE_ALIVE 1 
#define SCREEN_WIDTH 320 
#define SCREEN_HEIGHT 40 
#define SCREEN_WIDTH1 320 
#define SCREEN_HEIGHT1 200 
 
#define VGA256 0x13 
#define TEXT_MODE 0x03 
 
 
#define SPRITE_WIDTH 16 
#define SPRITE_HEIGHT 16 
 
#define MAX_SPRITE_FRAMES 8 
 
#define PALETTE_MASK 0x3c6 
#define PALETTE_REGISTER_RD 0x3c7 
#define PALETTE_REGISTER_WR 0x3c8 
#define PALETTE_DATA 0x3c9 
typedef struct RGB_color_typ 
{ 
unsigned char red; 
unsigned char green; 
unsigned char blue; 
}RGB_color,*RGB_color_ptr; 
 
 
unsigned char far *video_buffer=(char far *)0xA0000000L; 
 
void Delay(int clicks) 
{ 
unsigned int far *clock=(unsigned int far *)0x0000046CL; 
unsigned int now; 
now=*clock; 
while(abs(*clock-now)<clicks){} 
} 
 
 
void Set_Video_Mode(int mode) 
{ 
	union REGS inregs,outregs; 
	inregs.h.ah=0; 
	inregs.h.al=(unsigned char)mode; 
	int86(0x10,&inregs,&outregs); 
} 
 
 
void Set_Palette_Register(int index,RGB_color_ptr color) 
{ 
outp(PALETTE_MASK,0xff); 
outp(PALETTE_REGISTER_WR,index); 
outp(PALETTE_DATA,color->red); 
outp(PALETTE_DATA,color->green); 
outp(PALETTE_DATA,color->blue); 
} 
 
void Plot_Pixel_Fast(int x,int y,char color) 
{ 
video_buffer[((y<<8)+(y<<6))+x]=color; 
} 
 
typedef struct pcx_header_typ 
	{ 
	char manufacturer; 
	char version; 
	char encoding; 
	char bits_per_pixel; 
	int x,y; 
	int width,height; 
	int horz_res; 
	int vert_res; 
	char ega_palette[48]; 
	char reserved; 
	char num_color_planes; 
	int bytes_per_line; 
	int palette_type; 
	char padding[58]; 
 
} pcx_header, *pcx_header_ptr; 
 
typedef struct pcx_picture_typ 
	{ 
	pcx_header header; 
	RGB_color palette[256]; 
	char far *buffer; 
 
	} pcx_picture, *pcx_picture_ptr; 
 
 
void PCX_Init(pcx_picture_ptr image) 
{ 
unsigned int a=(unsigned int)(SCREEN_WIDTH * SCREEN_HEIGHT + 1); 
// this function allocates the buffer region needed to load a pcx file 
if((image->buffer = (char far *)malloc(a))==NULL) 
{ 
   printf("\ncouldn't allocate screen buffer"); 
 exit(1); 
 } 
} // end PCX_Init 
 
////////////////////////////////////////////////////////////////////////////// 
 
 
void PCX_Delete(pcx_picture_ptr image) 
{ 
// this function de-allocates the buffer region used for the pcx file load 
 
free(image->buffer); 
 
} // end PCX_Delete 
 
////////////////////////////////////////////////////////////////////////////// 
 
void PCX_Load(char *filename, pcx_picture_ptr image,int enable_palette) 
{ 
// this function loads a pcx file into a picture structure, the actual image 
// data for the pcx file is decompressed and expanded into a secondary buffer 
// within the picture structure, the separate images can be grabbed from this 
// buffer later.  also the header and palette are loaded 
 
FILE *fp; 
int num_bytes,index; 
unsigned int count; 
unsigned char data; 
char far *temp_buffer; 
 
// open the file 
 
fp = fopen(filename,"rb"); 
 
// load the header 
 
temp_buffer = (char far *)image; 
 
for (index=0; index<128; index++) 
    { 
    temp_buffer[index] = getc(fp); 
    } // end for index 
 
// load the data and decompress into buffer 
count=0; 
 
 
while(count<=(unsigned int)SCREEN_WIDTH * SCREEN_HEIGHT) 
	 { 
	 // get the first piece of data 
 
	 data = getc(fp); 
 
	 // is this a rle? 
 
     if (data>=192 && data<=255) 
	{ 
        // how many bytes in run? 
 
        num_bytes = data-192; 
 
	// get the actual data for the run 
 
	data  = getc(fp); 
 
		// replicate data in buffer num_bytes times 
 
        while(num_bytes-->0) 
             { 
             image->buffer[count++] = data; 
 
             } // end while 
 
        } // end if rle 
     else 
	{ 
        // actual data, just copy it into buffer at next location 
 
        image->buffer[count++] = data; 
 
        } // end else not rle 
 
     } // end while 
 
// move to end of file then back up 768 bytes i.e. to begining of palette 
 
fseek(fp,-768L,SEEK_END); 
 
// load the pallete into the palette 
 
for (index=0; index<256; index++) 
    { 
    // get the red component 
 
    image->palette[index].red   = (getc(fp) >> 2); 
 
    // get the green component 
 
    image->palette[index].green = (getc(fp) >> 2); 
 
    // get the blue component 
 
    image->palette[index].blue  = (getc(fp) >> 2); 
 
    } // end for index 
 
fclose(fp); 
 
// change the palette to newly loaded palette if commanded to do so 
 
if (enable_palette) 
   { 
 
   for (index=0; index<256; index++) 
       { 
 
       Set_Palette_Register(index,(RGB_color_ptr)&image->palette[index]); 
 
       } // end for index 
 
   } // end if change palette 
 
} // end PCX_Load 
 
////////////////////////////////////////////////////////////////////////////// 
 
 
void PCX_Load_Screen(char *filename,int enable_palette) 
{ 
// this function loads a pcx file into a picture structure, the actual image 
// data for the pcx file is decompressed and expanded into a secondary buffer 
// within the picture structure, the separate images can be grabbed from this 
// buffer later.  also the header and palette are loaded 
 
FILE *fp; 
int num_bytes,index; 
unsigned int count; 
unsigned char data; 
RGB_color palette[256]; 
// open the file 
 
 
fp = fopen(filename,"rb"); 
 
 
fseek(fp,128L,SEEK_SET); 
// load the data and decompress into buffer 
count=0; 
 
 
while(count<=(unsigned int)SCREEN_WIDTH * SCREEN_HEIGHT1) 
	 { 
	 // get the first piece of data 
 
	 data = getc(fp); 
 
	 // is this a rle? 
 
     if (data>=192 && data<=255) 
	{ 
	// how many bytes in run? 
 
        num_bytes = data-192; 
 
	// get the actual data for the run 
 
	data  = getc(fp); 
 
		// replicate data in buffer num_bytes times 
 
        while(num_bytes-->0) 
	     { 
//             image->buffer[count++] = data; 
  video_buffer[count++]=data; 
	     } // end while 
 
	} // end if rle 
     else 
	{ 
	// actual data, just copy it into buffer at next location 
 
	//image->buffer[count++] = data; 
	  video_buffer[count++]=data; 
	} // end else not rle 
 
     } // end while 
for (index=0; index<256; index++) 
    { 
    // get the red component 
 
    palette[index].red   = (getc(fp) >> 2); 
 
    // get the green component 
 
    palette[index].green = (getc(fp) >> 2); 
 
    // get the blue component 
 
    palette[index].blue  = (getc(fp) >> 2); 
 
    } // end for index 
 
fclose(fp); 
 
// change the palette to newly loaded palette if commanded to do so 
 
if (enable_palette) 
   { 
 
   for (index=0; index<256; index++) 
       { 
 
       Set_Palette_Register(index,(RGB_color_ptr)&palette[index]); 
 
       } // end for index 
 
   } // end if change palette 
 
} // end PCX_Load 
 
 
typedef struct key 
{ 
char up; 
char down; 
char left; 
char right; 
char stop; 
char quit; 
char fight; 
}key,key_ptr; 
 
typedef struct sprite_type 
{ 
int x,y; 
int x_old,y_old; 
int width,height; 
int anim_clock; 
int anim_speed; 
int motion_clock; 
int motion_speed; 
char far *frames[MAX_SPRITE_FRAMES]; 
int curr_frame; 
int num_frames; 
int state; 
char far *background; 
void far *extra_data; 
struct sprite_type *next; 
void (far *spr)(struct sprite_type *spr); 
key key; 
}sprite,*sprite_ptr; 
 
sprite_ptr head,now,pre; 
char get_key; 
 
void PCX_Grab_Bitmap(pcx_picture_ptr image, 
		    sprite_ptr sprite, 
		    int sprite_frame, 
		    int grab_x, int grab_y) 
 
{ 
// this function will grap a bitmap from the pcx frame buffer. it uses the 
// convention that the 320x200 pixel matrix is sub divided into a smaller 
// matrix of 12x8 adjacent squares each being a 24x24 pixel bitmap 
// the caller sends the pcx picture along with the sprite to save the image 
// into and the frame of the sprite.  finally, the position of the bitmap 
// that should be grabbed is sent 
 
int x_off,y_off, x,y, index; 
char far *sprite_data; 
 
// first allocate the memory for the sprite in the sprite structure 
 
sprite->frames[sprite_frame] = (char far *)malloc(SPRITE_WIDTH * SPRITE_HEIGHT); 
 
// create an alias to the sprite frame for ease of access 
 
sprite_data = sprite->frames[sprite_frame]; 
 
// now load the sprite data into the sprite frame array from the pcx picture 
 
// we need to find which bitmap to scan, remember the pcx picture is really a 
// 12x8 matrix of bitmaps where each bitmap is 24x24 pixels. note:0,0 is upper 
// left bitmap and 11,7 is the lower right bitmap. 
 
x_off = (SPRITE_WIDTH) * grab_x; 
y_off = (SPRITE_HEIGHT) * grab_y ; 
 
// compute starting y address 
 
y_off = y_off * 320; 
 
for (y=0; y<SPRITE_HEIGHT; y++) 
    { 
 
    for (x=0; x<SPRITE_WIDTH; x++) 
	{ 
 
	// get the next byte of current row and place into next position in 
	// sprite frame data buffer 
 
	sprite_data[y*SPRITE_WIDTH + x] = image->buffer[y_off + x_off + x]; 
 
	} // end for x 
 
	// move to next line of picture buffer 
 
	y_off+=320; 
 
    } // end for y 
 
// increment number of frames 
 
sprite->num_frames++; 
 
// done!, let's bail! 
 
} // end PCX_Grap_Bitmap 
 
 
void Sprite_Init(sprite_ptr sprite,int x,int y,int ac,int as,int mc,int ms,void (far *spr),char key[7]) 
{ 
// this function initializes a sprite with the sent data 
 
int index; 
 
sprite->x            = x; 
sprite->y            = y; 
sprite->x_old        = x; 
sprite->y_old        = y; 
sprite->width        = SPRITE_WIDTH; 
sprite->height       = SPRITE_HEIGHT; 
sprite->anim_clock   = ac; 
sprite->anim_speed   = as; 
sprite->motion_clock = mc; 
sprite->motion_speed = ms; 
sprite->curr_frame   = 0; 
sprite->state        = SPRITE_DEAD; 
sprite->num_frames   = 0; 
sprite->background   = (char far *)malloc(SPRITE_WIDTH * SPRITE_HEIGHT+1); 
sprite->spr=spr; 
sprite->key.up=key[0]; 
sprite->key.down=key[1]; 
sprite->key.left=key[2]; 
sprite->key.right=key[3]; 
sprite->key.stop=key[4]; 
sprite->key.quit=key[5]; 
sprite->key.fight=key[6]; 
// set all bitmap pointers to null 
 
for (index=0; index<MAX_SPRITE_FRAMES; index++) 
    sprite->frames[index] = NULL; 
 
} // end Sprite_Init 
 
////////////////////////////////////////////////////////////////////////////// 
 
void Sprite_Delete(sprite_ptr sprite) 
{ 
// this function deletes all the memory associated with a sprire 
 
int index; 
 
farfree(sprite->background); 
 
// now de-allocate all the animation frames 
 
for (index=0; index<MAX_SPRITE_FRAMES; index++) 
    farfree(sprite->frames[index]); 
free(sprite); 
} // end Sprite_Delete 
 
void Draw_Sprite(sprite_ptr sprite) 
{ 
 
// this function draws a sprite on the screen row by row very quickly 
// note the use of shifting to implement multplication 
 
char far *work_sprite; 
int work_offset=0,offset,x,y; 
//unsigned char data; 
 
// alias a pointer to sprite for ease of access 
 
work_sprite = sprite->frames[sprite->curr_frame]; 
 
// compute offset of sprite in video buffer 
 
offset = ((sprite->y) << 8) + ((sprite->y) << 6) + sprite->x; 
 
for (y=0; y<SPRITE_HEIGHT; y++) 
    { 
    // copy the next row into the screen buffer using memcpy for speed 
 
    for (x=0; x<SPRITE_WIDTH; x++) 
	{ 
 
	// test for transparent pixel i.e. 0, if not transparent then draw 
      if(work_sprite[work_offset+x]) 
 
	 //data==(unsigned char)work_sprite[work_offset+x]; 
// if(data) 
//	     video_buffer[offset+x] =data; 
     video_buffer[offset+x]=work_sprite[work_offset+x]; 
	} // end for x 
 
    // move to next line in video buffer and in sprite bitmap buffer 
 
    offset      += SCREEN_WIDTH; 
    work_offset += SPRITE_WIDTH; 
 
    } // end for y 
 
} // end Draw_Sprite 
 
 
void Behind_Sprite(sprite_ptr sprite) 
{ 
 
// this function scans the background behind a sprite so that when the sprite 
// is draw, the background isnn'y obliterated 
 
char far *work_back; 
int work_offset=0,offset,y; 
 
// alias a pointer to sprite background for ease of access 
 
work_back = sprite->background; 
 
// compute offset of background in video buffer 
 
offset = (sprite->y << 8) + (sprite->y << 6) + sprite->x; 
 
for (y=0; y<SPRITE_HEIGHT; y++) 
    { 
    // copy the next row out off screen buffer into sprite background buffer 
 
    _fmemmove((void far *)&work_back[work_offset], 
	     (void far *)&video_buffer[offset], 
	     SPRITE_WIDTH); 
 
    // move to next line in video buffer and in sprite background buffer 
 
    offset      += SCREEN_WIDTH; 
    work_offset += SPRITE_WIDTH; 
 
    } // end for y 
 
} // end Behind_Sprite 
 
////////////////////////////////////////////////////////////////////////////// 
 
 
void Erase_Sprite(sprite_ptr sprite) 
{ 
// replace the background that was behind the sprite 
 
// this function replaces the background that was saved from where a sprite 
// was going to be placed 
 
char far *work_back; 
int work_offset=0,offset,y; 
 
// alias a pointer to sprite background for ease of access 
 
work_back = sprite->background; 
 
// compute offset of background in video buffer 
 
offset = (sprite->y << 8) + (sprite->y << 6) + sprite->x; 
 
for (y=0; y<SPRITE_HEIGHT; y++) 
    { 
    // copy the next row out off screen buffer into sprite background buffer 
 
    _fmemmove((void far *)&video_buffer[offset], 
	     (void far *)&work_back[work_offset], 
	     SPRITE_WIDTH); 
 
    // move to next line in video buffer and in sprite background buffer 
 
    offset      += SCREEN_WIDTH; 
    work_offset += SPRITE_WIDTH; 
 
    } // end for y 
 
 
} // end Erase_Sprite 
 
 
void Fill_Screen(int value) 
{ 
_fmemset(video_buffer,(char)value,SCREEN_WIDTH*SCREEN_HEIGHT1+1); 
} 
 
 
void Clear_Key_Buffer(void) 
{ 
int offset; 
offset=peek(0x40,0x1a); 
pokeb(0x40,0x1c,offset); 
} 
 
void Sheer(void) 
{ 
long index; 
int x,y; 
x=rand()%320; 
y=rand()%200; 
for(index=0;index<100000;index++) 
{ 
x+=17; 
y+=13; 
if(x>319) 
x=x-319; 
if(y>199) 
y=y-199; 
Plot_Pixel_Fast(x,y,0); 
} 
} 
 
void spr(sprite_ptr sprite) 
{ 
static int sprite_direction=0; 
static float dx,dy,dxx=0,dyy=0,angle; 
static int i,j=2,k,l=1; 
char get_key; 
l=-l; 
k=0; 
 
Erase_Sprite(sprite); 
 
if(l==1) 
{ 
if(kbhit()) 
{ 
get_key=getch(); 
Clear_Key_Buffer(); 
k=1; 
dx=dy=0; 
 
if(get_key==sprite->key.up) 
{ 
sprite_direction=0; 
angle=(90+360-360/(MAX_SPRITE_FRAMES/2)*(float)sprite_direction); 
dxx=dx=sprite_SPEED*cos(PI*angle/180); 
dyy=dy=sprite_SPEED*sin(PI*angle/180); 
} 
if(get_key==sprite->key.right) 
{ 
sprite_direction=1; 
angle=(90+360-360/(MAX_SPRITE_FRAMES/2)*(float)sprite_direction); 
dxx=dx=sprite_SPEED*cos(PI*angle/180); 
dyy=dy=sprite_SPEED*sin(PI*angle/180); 
} 
if(get_key==sprite->key.down) 
{ 
sprite_direction=2; 
angle=(90+360-360/(MAX_SPRITE_FRAMES/2)*(float)sprite_direction); 
dxx=dx=sprite_SPEED*cos(PI*angle/180); 
dyy=dy=sprite_SPEED*sin(PI*angle/180); 
} 
if(get_key==sprite->key.left) 
{ 
sprite_direction=3; 
angle=(90+360-360/(MAX_SPRITE_FRAMES/2)*(float)sprite_direction); 
dxx=dx=sprite_SPEED*cos(PI*angle/180); 
dyy=dy=sprite_SPEED*sin(PI*angle/180); 
} 
 
if(get_key==sprite->key.quit) 
{ 
Sprite_Delete(sprite); 
 
Sheer(); 
Set_Video_Mode(TEXT_MODE); 
exit(1); 
} 
 
sprite->x+=(int)(dx+.5); 
if(sprite->x>319-(int)SPRITE_WIDTH) 
sprite->x=319-(int)SPRITE_WIDTH; 
else if(sprite->x<0) 
sprite->x=0; 
 
sprite->y-=(int)(dy+.5); 
 
 
 
if(sprite->y>199-(int)SPRITE_HEIGHT) 
sprite->y=199-(int)SPRITE_HEIGHT; 
else if(sprite->y<0) 
sprite->y=0; 
sprite->curr_frame=sprite_direction; 
} 
 
if(k==0) 
if(get_key!=sprite->key.stop) 
{ 
sprite->x+=(int)(dxx+.5); 
if(sprite->x>319-(int)SPRITE_WIDTH) 
sprite->x=319-(int)SPRITE_WIDTH; 
else if(sprite->x<0) 
sprite->x=0; 
 
sprite->y-=(int)(dyy+.5); 
if(sprite->y>199-(int)SPRITE_HEIGHT) 
sprite->y=199-(int)SPRITE_HEIGHT; 
else if(sprite->y<0) 
sprite->y=0; 
sprite->curr_frame=sprite_direction; 
 
} 
} 
 
else 
{ 
j=-j; 
sprite->curr_frame=sprite_direction+2+j; 
} 
 
 
Behind_Sprite(sprite); 
 
Draw_Sprite(sprite); 
 
Delay(2); 
 
} 
 
void Judge_Sprite(void) 
{ 
sprite_ptr sprite; 
sprite=head; 
do{ 
	sprite->spr(sprite); 
	sprite=sprite->next; 
}while(sprite!=NULL); 
} 
 
 
void main(void) 
{ 
long index; 
pcx_picture background_pcx,objects_pcx; 
char key[7]={'8','2','4','6','5','q','0'}; 
 
Set_Video_Mode(VGA256); 
PCX_Init((pcx_picture_ptr)&objects_pcx); 
 
PCX_Load_Screen("poem.pcx",1); 
PCX_Load("attank2.pcx",(pcx_picture_ptr)&objects_pcx,1); 
 
now=pre=(struct sprite *)malloc(sizeof(struct sprite_type)); 
head=now; 
Sprite_Init(now,0,0,0,0,0,0,spr,key); 
pre->next=NULL; 
 
for(index=0;index<MAX_SPRITE_FRAMES;index++) 
{ 
 PCX_Grab_Bitmap((pcx_picture_ptr)&objects_pcx,now,index,index,0); 
} 
 
PCX_Delete((pcx_picture_ptr)&objects_pcx); 
 
 
Behind_Sprite(now); 
 
while(1){ 
	Judge_Sprite(); 
} 
}