游戏编程(二) 动态图片

依样画葫芦的照着写了一个。

先把代码贴在这儿,随时查阅。

 

#pragma comment(lib,"dxguid.lib") 
#include <windows.h>
#include <windowsx.h> 
#include <mmsystem.h>
#include <iostream.h>
#include <conio.h>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h> 
#include <math.h>
#include <io.h>
#include <fcntl.h>
#include <ddraw.h>

#define KEYDOWN(key) ((GetAsyncKeyState(key) & 0x8000) ? 1 : 0)
#define KEYUP(key)   ((GetAsyncKeyState(key) & 0x8000) ? 0 : 1)
#define DD_INIT_STRUCT(ddstruct){memset(&ddstruct,0,sizeof(ddstruct));ddstruct.dwSize=sizeof(ddstruct);}
#define SCREEN_WIDTH    640
#define SCREEN_HEIGHT   480
#define SCREEN_BPP      8
#define SPEED_X			3
#define SPEED_Y			3
#define ANINUM			50
#define BITMAP_ID            0x4D42
#define MAX_COLORS_PALETTE   256

//图片结构体
typedef struct BITMAP_FILE_TAG
{
	BITMAPFILEHEADER bitmapfileheader;
	BITMAPINFOHEADER bitmapinfoheader;
	PALETTEENTRY     palette[256];
	UCHAR            *buffer;
} BITMAP_FILE, *BITMAP_FILE_PTR;

typedef struct ALIEN_OBJ_TYP
{
	LPDIRECTDRAWSURFACE7 frames[3];
	int x,y;
	int velocity;
	int current_frame;
	int counter;
} ALIEN_OBJ, *ALIEN_OBJ_PTR;

LPDIRECTDRAW7         lpdd         = NULL;   // dd4 object
LPDIRECTDRAWSURFACE7  lpddsprimary = NULL;   // dd primary surface
LPDIRECTDRAWSURFACE7  lpddsback    = NULL;   // dd back surface
LPDIRECTDRAWPALETTE   lpddpal      = NULL;   // a pointer to the created dd palette
LPDIRECTDRAWCLIPPER   lpddclipper  = NULL;   // dd clipper
PALETTEENTRY          palette[256];          // color palette
PALETTEENTRY          save_palette[256];     // used to save palettes
DDSURFACEDESC2        ddsd;                  // a direct draw surface description struct
DDBLTFX               ddbltfx;               // used to fill
DDSCAPS2              ddscaps;               // a direct draw surface capabilities struct
HRESULT               ddrval;                // result back from dd calls
DWORD                 start_clock_count = 0; // used for timing
BITMAP_FILE           bitmap;                // holds the bitmap
ALIEN_OBJ             aliens[3];             // 3 aliens, one on each level
LPDIRECTDRAWSURFACE7  lpddsbackground = NULL;// this will hold the background image
int window_closed=0;  

#define _RGB16BIT555(r,g,b) ((b&31)+((g&31)<<5)+((r&31)<<10))
#define _RGB16BIT565(r,g,b) ((b&31)+((g&63)<<5)+((r&31)<<11))
#define _RGB32BIT(a,r,g,b) ((b)+((g)<<8)+((r)<<16)+((a)<<24))


int gwidth  = -1;
int gheight = -1;

//从源表面拷贝一个矩形到桌面显示
int DDraw_Draw_Surface(LPDIRECTDRAWSURFACE7 source,int x, int y,int width,int height,LPDIRECTDRAWSURFACE7 dest,int transparent=1)
{
	RECT dest_rect,source_rect;
	dest_rect.left=x;
	dest_rect.top=y;
	dest_rect.right=x+width-1;
	dest_rect.bottom=y+height-1;
	source_rect.left=0;
	source_rect.top=0;
	source_rect.right=width-1;
	source_rect.bottom=height-1;
	if (transparent)
	{
		if (FAILED(dest->Blt(&dest_rect,source,&source_rect,(DDBLT_WAIT|DDBLT_KEYSRC),NULL)))
			return(0);
	}
	else
	{
		if (FAILED(dest->Blt(&dest_rect,source,&source_rect,(DDBLT_WAIT),NULL)))
			return(0);
	}
	return(1);
}

//得到一个包含所有目标矩形的剪贴板
LPDIRECTDRAWCLIPPER DDraw_Attach_Clipper(LPDIRECTDRAWSURFACE7 lpdds,int num_rects,LPRECT clip_list)
{
	int index;
	LPDIRECTDRAWCLIPPER lpddclipper;
	LPRGNDATA region_data;
	if (FAILED(lpdd->CreateClipper(0,&lpddclipper,NULL)))
		return(NULL);
	region_data=(LPRGNDATA)malloc(sizeof(RGNDATAHEADER)+num_rects*sizeof(RECT));
	memcpy(region_data->Buffer,clip_list,sizeof(RECT)*num_rects);
	region_data->rdh.dwSize=sizeof(RGNDATAHEADER);
	region_data->rdh.iType=RDH_RECTANGLES;
	region_data->rdh.nCount=num_rects;
	region_data->rdh.nRgnSize=num_rects*sizeof(RECT);
	region_data->rdh.rcBound.left=64000;
	region_data->rdh.rcBound.top=64000;
	region_data->rdh.rcBound.right=-64000;
	region_data->rdh.rcBound.bottom=-64000;
	for(index=0;index<num_rects;index++)
    {
		if (clip_list[index].left<region_data->rdh.rcBound.left)
			region_data->rdh.rcBound.left=clip_list[index].left;
		if (clip_list[index].right>region_data->rdh.rcBound.right)
			region_data->rdh.rcBound.right=clip_list[index].right;
		if (clip_list[index].top<region_data->rdh.rcBound.top)
			region_data->rdh.rcBound.top=clip_list[index].top;
		if (clip_list[index].bottom>region_data->rdh.rcBound.bottom)
			region_data->rdh.rcBound.bottom=clip_list[index].bottom;
    }
	if(FAILED(lpddclipper->SetClipList(region_data, 0)))
	{
		free(region_data);
		return(NULL);
	}
	if(FAILED(lpdds->SetClipper(lpddclipper)))
	{
		free(region_data);
		return(NULL);
	}
	free(region_data);
	return(lpddclipper);
}

//加载一副图片,图片路径:filename
int Flip_Bitmap(UCHAR *image, int bytes_per_line, int height)
{
	UCHAR *buffer;
	int index;
	if(!(buffer=(UCHAR*)malloc(bytes_per_line*height)))
		return 0;
	memcpy(buffer,image,bytes_per_line*height);
	for(index=0;index<height;index++)
		memcpy(&image[((height-1)-index)*bytes_per_line],&buffer[index*bytes_per_line],bytes_per_line);
	free(buffer);
	return(1);
}

int Load_Bitmap_File(BITMAP_FILE_PTR bitmap,char *filename)
{
	int file_handle,index;
	UCHAR *temp_buffer=NULL;
	OFSTRUCT file_data;
	if((file_handle=OpenFile(filename,&file_data,OF_READ))==-1)
		return(0);
	_lread(file_handle,&bitmap->bitmapfileheader,sizeof(BITMAPFILEHEADER));
	if(bitmap->bitmapfileheader.bfType!=BITMAP_ID)
	{
		_lclose(file_handle);
		return(0);
	}
	_lread(file_handle,&bitmap->bitmapinfoheader,sizeof(BITMAPINFOHEADER));
	if (bitmap->bitmapinfoheader.biBitCount==8)
	{
		_lread(file_handle,&bitmap->palette,MAX_COLORS_PALETTE*sizeof(PALETTEENTRY));
		for (index=0;index<MAX_COLORS_PALETTE;index++)
		{
			int temp_color=bitmap->palette[index].peRed;
			bitmap->palette[index].peRed=bitmap->palette[index].peBlue;
			bitmap->palette[index].peBlue=temp_color;
			bitmap->palette[index].peFlags=PC_NOCOLLAPSE;
		}
    }
	_lseek(file_handle,-(int)(bitmap->bitmapinfoheader.biSizeImage),SEEK_END);
	if (bitmap->bitmapinfoheader.biBitCount==8||bitmap->bitmapinfoheader.biBitCount==16||bitmap->bitmapinfoheader.biBitCount==24)
	{
		if(bitmap->buffer)
			free(bitmap->buffer);
		if(!(bitmap->buffer=(UCHAR *)malloc(bitmap->bitmapinfoheader.biSizeImage)))
		{
			_lclose(file_handle);
			return(0);
		}
		_lread(file_handle,bitmap->buffer,bitmap->bitmapinfoheader.biSizeImage);
	}
	else
	{
		return(0);
	}
#if 0
	printf("\nfilename:%s \nsize=%d \nwidth=%d \nheight=%d \nbitsperpixel=%d \ncolors=%d \nimpcolors=%d",
        filename,
        bitmap->bitmapinfoheader.biSizeImage,
        bitmap->bitmapinfoheader.biWidth,
        bitmap->bitmapinfoheader.biHeight,
		bitmap->bitmapinfoheader.biBitCount,
        bitmap->bitmapinfoheader.biClrUsed,
        bitmap->bitmapinfoheader.biClrImportant);
#endif
	_lclose(file_handle);
	Flip_Bitmap(bitmap->buffer, 
		bitmap->bitmapinfoheader.biWidth*(bitmap->bitmapinfoheader.biBitCount/8), 
		bitmap->bitmapinfoheader.biHeight);
	return(1);
}

//用调色板编号为color的颜色填充整个屏幕
int DDraw_Fill_Surface(LPDIRECTDRAWSURFACE7 lpdds,int color)
{
	DDBLTFX ddbltfx;
	DD_INIT_STRUCT(ddbltfx);
	ddbltfx.dwFillColor=color;
	lpdds->Blt(NULL,NULL,NULL,DDBLT_COLORFILL|DDBLT_WAIT,&ddbltfx);
	return(1);
}

//创建一个可以过滤颜色的表面
LPDIRECTDRAWSURFACE7 DDraw_Create_Surface(int width,int height,int mem_flags,int color_key=0)
{
	DDSURFACEDESC2 ddsd;
	LPDIRECTDRAWSURFACE7 lpdds;
	memset(&ddsd,0,sizeof(ddsd));
	ddsd.dwSize=sizeof(ddsd);
	ddsd.dwFlags=DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT;
	ddsd.dwWidth=width;
	ddsd.dwHeight=height;
	ddsd.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN|mem_flags;
	if(FAILED(lpdd->CreateSurface(&ddsd,&lpdds,NULL)))
		return(NULL);
	if(color_key>=0)
	{
		DDCOLORKEY color_key;
		color_key.dwColorSpaceLowValue=0;
		color_key.dwColorSpaceHighValue=0;
		lpdds->SetColorKey(DDCKEY_SRCBLT,&color_key);
	}
	return(lpdds);
}

//释放图片内存
int Unload_Bitmap_File(BITMAP_FILE_PTR bitmap)
{
	if (bitmap->buffer)
	{
		free(bitmap->buffer);
		bitmap->buffer=NULL;		
	}
	return(1);
}

//显示一张图片
int Scan_Image_Bitmap(BITMAP_FILE_PTR bitmap,LPDIRECTDRAWSURFACE7 lpdds,int cx,int cy)
{
	UCHAR *source_ptr,*dest_ptr;
	DDSURFACEDESC2 ddsd;
	ddsd.dwSize=sizeof(ddsd);
	lpdds->Lock(NULL,&ddsd,DDLOCK_WAIT|DDLOCK_SURFACEMEMORYPTR,NULL);
	cx=cx*(ddsd.dwWidth+1)+1;
	cy=cy*(ddsd.dwHeight+1)+1;
	gwidth=ddsd.dwWidth;
	gheight=ddsd.dwHeight;
	source_ptr=bitmap->buffer+cy*bitmap->bitmapinfoheader.biWidth+cx;
	dest_ptr=(UCHAR *)ddsd.lpSurface;
	for (int index_y=0;index_y<ddsd.dwHeight;index_y++)
    {
		memcpy(dest_ptr,source_ptr,ddsd.dwWidth);
		dest_ptr+=(ddsd.lPitch);
		source_ptr+=bitmap->bitmapinfoheader.biWidth;
    }
	lpdds->Unlock(NULL);
	return(1);
}

void Plot_Pixel_Faster32(int x,int y,int a,int r,int g,int b,UINT *video_buffer,int lpitch32)
{
	UINT color;
	color=_RGB32BIT(a,r,g,b);
	video_buffer[x+y*lpitch32]=color;
}

HWND hwd;
HINSTANCE hIns;
HDC hdc;

LRESULT CALLBACK WinSunProc(
	HWND hwnd,
	UINT uMsg,
	WPARAM wParam,
	LPARAM lParam
)
{
	HDC hdc;
	PAINTSTRUCT ps;
	switch(uMsg)
	{
	case WM_PAINT:
		hdc=BeginPaint(hwnd,&ps);

		EndPaint(hwnd,&ps);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		break;
	}
	return DefWindowProc(hwnd,uMsg,wParam,lParam);
}

void Blt_Clip(int x,int y,int width,int height,UCHAR *bitmap,UCHAR *video_buffer,int mempitch)
{
	if((x>=SCREEN_WIDTH)||(y>=SCREEN_HEIGHT)||((x+width)<=0)||((y+height)<=0))
		return;
	int x1=x;
	int y1=y;
	int x2=x+width-1;
	int y2=y+height-1;
	if(x1<0)
		x1=0;
	if(y1<0)
		y1=0;
	if(x2>SCREEN_WIDTH)
		x2=SCREEN_WIDTH;
	if(y2>SCREEN_HEIGHT)
		y2=SCREEN_HEIGHT;
	int x_off=x-x1;
	int y_off=y-y1;
	int dx=x2-x1+1;
	int dy=y2-y1+1;
	video_buffer=video_buffer+(x1+y1*mempitch);
	bitmap=bitmap+(x_off+y_off*width);
	int i,j;
	UCHAR pixel;
	for(j=0;j<dy;j++)
	{
		for(i=0;i<dx;i++)
		{
			pixel=bitmap[i];
			video_buffer[i]=pixel;
		}
		video_buffer=video_buffer+mempitch;
		bitmap=bitmap+width;
	}
}

void Game_Init()
{
	if(FAILED(DirectDrawCreateEx(NULL,(void**)&lpdd,IID_IDirectDraw7,NULL)))
		return;
	if(FAILED(lpdd->SetCooperativeLevel(hwd,DDSCL_FULLSCREEN|DDSCL_ALLOWMODEX|DDSCL_EXCLUSIVE|DDSCL_ALLOWREBOOT)))
		return;
	if(FAILED(lpdd->SetDisplayMode(SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_BPP,0,0)))
		return;
	DD_INIT_STRUCT(ddsd);
	ddsd.dwFlags=DDSD_CAPS|DDSD_BACKBUFFERCOUNT;
	ddsd.dwBackBufferCount=1;
	ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE|DDSCAPS_COMPLEX|DDSCAPS_FLIP;
	if(FAILED(lpdd->CreateSurface(&ddsd,&lpddsprimary,NULL)))
		return;
	ddsd.ddsCaps.dwCaps=DDSCAPS_BACKBUFFER;
	if(FAILED(lpddsprimary->GetAttachedSurface(&ddsd.ddsCaps,&lpddsback)))
		return;
	int i;
	for(i=1;i<=254;i++)
	{
		palette[i].peRed=rand()%256;
		palette[i].peGreen=rand()%256;
		palette[i].peBlue=rand()%256;
		palette[i].peFlags=PC_NOCOLLAPSE;
	}
	palette[0].peRed=0;
	palette[0].peGreen=0;
	palette[0].peBlue=0;
	palette[0].peFlags=PC_NOCOLLAPSE;
	palette[255].peRed=255;
	palette[255].peGreen=255;
	palette[255].peBlue=255;
	palette[255].peFlags=PC_NOCOLLAPSE;
	if(FAILED(lpdd->CreatePalette(DDPCAPS_8BIT|DDPCAPS_ALLOW256|DDPCAPS_INITIALIZE,palette,&lpddpal, NULL)))
		return;
	if(FAILED(lpddsprimary->SetPalette(lpddpal)))
		return;
	RECT screen_rect={0,0,SCREEN_WIDTH-1,SCREEN_HEIGHT-1};
	lpddclipper=DDraw_Attach_Clipper(lpddsback,1,&screen_rect);
	if(!Load_Bitmap_File(&bitmap,"alley8.bmp"))
		return;
	if(FAILED(lpddpal->SetEntries(0,0,MAX_COLORS_PALETTE,bitmap.palette)))
		return;
	DDraw_Fill_Surface(lpddsback,0);
	DDraw_Fill_Surface(lpddsprimary,0);
	lpddsbackground=DDraw_Create_Surface(SCREEN_WIDTH,SCREEN_HEIGHT,0,-1);
	lpddsbackground->Lock(NULL,&ddsd,DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT,NULL);
	UCHAR* image_buffer=(UCHAR*)ddsd.lpSurface;
	if(ddsd.lPitch==SCREEN_WIDTH)
	{
		memcpy((void*)image_buffer,(void*)bitmap.buffer,SCREEN_WIDTH*SCREEN_HEIGHT);
	}
	else
	{
		UCHAR *dest=image_buffer;
		UCHAR *scr=bitmap.buffer;
		for(i=0;i<SCREEN_HEIGHT;i++)
		{
			memcpy((void*)dest,(void*)scr,SCREEN_WIDTH);
			dest=dest+ddsd.lPitch;
			scr=scr+SCREEN_WIDTH;
		}
	}
	if(FAILED(lpddsbackground->Unlock(NULL)))
		return;
	Unload_Bitmap_File(&bitmap);
	srand(GetTickCount());
	aliens[0].x=rand()%SCREEN_WIDTH;
	aliens[0].y=116-72;
	aliens[0].velocity=2+rand()%4;
	aliens[0].current_frame=0;
	aliens[0].counter=0;

	aliens[1].x=rand()%SCREEN_WIDTH;
	aliens[1].y=246-72;
	aliens[1].velocity=2+rand()%4;
	aliens[1].current_frame=0;
	aliens[1].counter=0;

	aliens[2].x=rand()%SCREEN_WIDTH;
	aliens[2].y=382-72;
	aliens[2].velocity=2+rand()%4;
	aliens[2].current_frame=0;
	aliens[2].counter=0;

	if(!Load_Bitmap_File(&bitmap,"dedsp0.bmp"))
		return;

	for(i=0;i<3;i++)
	{
		aliens[0].frames[i]=DDraw_Create_Surface(72,80,0);
		Scan_Image_Bitmap(&bitmap,aliens[0].frames[i],i,0);
	}

	Unload_Bitmap_File(&bitmap);
	for(i=0;i<3;i++)
		aliens[1].frames[i]=aliens[2].frames[i]=aliens[0].frames[i];
	return;
}

void Game_Main()
{
	static int animation_seq[4]={0,1,0,2};
	if(window_closed)
		return;
	if(KEYDOWN(VK_ESCAPE))
	{
		PostMessage(hwd,WM_CLOSE,0,0);
		window_closed=1;
	}
	DDraw_Draw_Surface(lpddsbackground,0,0,SCREEN_WIDTH,SCREEN_HEIGHT,lpddsback,0); 
	int i;
	for(i=0;i<3;i++)
	{
		aliens[i].x++;
		if(aliens[i].x>SCREEN_WIDTH)
			aliens[i].x=-80;
		if(++aliens[i].counter>=(8-aliens[i].velocity))
		{
			aliens[i].counter=0;
			if(++aliens[i].current_frame>3)
				aliens[i].current_frame=0;
		}
	}
	for(i=0;i<3;i++)
	{
		DDraw_Draw_Surface(aliens[i].frames[animation_seq[aliens[i].current_frame]],
							aliens[i].x,aliens[i].y,
							72,80,
							lpddsback);
	}

	while(FAILED(lpddsprimary->Flip(NULL,DDFLIP_WAIT)));
	Sleep(30);
	return;
}

void Game_Shut()
{
	if(lpddpal)
	{
		lpddpal->Release();
		lpddpal=NULL;
	}
	if(lpddsprimary)
	{
		lpddsprimary->Release();
		lpddsprimary=NULL;
	}
	if(lpdd)
	{
		lpdd->Release();
		lpdd=NULL;
	}
}

int WINAPI WinMain(
	HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPSTR lpCmdline,
	int nShowCmd
)
{
	WNDCLASS wndclass;
	wndclass.cbClsExtra=0;
	wndclass.cbWndExtra=0;
	wndclass.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
	wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
	wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
	wndclass.hInstance=hInstance;
	wndclass.lpfnWndProc=WinSunProc;
	wndclass.lpszClassName="bingshen";
	wndclass.lpszMenuName=NULL;
	wndclass.style=CS_HREDRAW|CS_VREDRAW;	
	
	ShowCursor(FALSE);
	HWND hwnd;
	RegisterClass(&wndclass);
	hwnd=CreateWindow("bingshen","-------bingshen",WS_POPUP|WS_VISIBLE,
		0,0,SCREEN_WIDTH,SCREEN_HEIGHT,
		NULL,NULL,hInstance,NULL);
	hwd=hwnd;
	hdc=GetDC(hwnd);

	hIns=hInstance;

	Game_Init();
	MSG msg;
	while(true)
	{
		if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
		{
			if(msg.message==WM_QUIT)
				break;
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		Game_Main();
	}
	Game_Shut();
	ReleaseDC(hwnd,hdc);
	return msg.wParam;
}



 


 

你可能感兴趣的:(游戏,编程,File,null,buffer,colors)