。。真不容易啊,被个素材搞到我吐血,本来是8位的显示模式,可是那效果太TMD的烂了,改了N小时,。。做了很多无用功
才改成32位模式。。那素材我纠结啊,1帧2帧扫描正常,3.4帧死活不能正常素描~,若有人知道是怎么回事,麻烦告知一下。
就是这玩意,第一行 1 。2帧都扫描正常。之后的全部不正常
键盘方向键控制最下面的角色,由于只扫描了2帧动画。看起来怪怪的- -。。我擦
// INCLUDES /////////////////////////////////////////////// #define WIN32_LEAN_AND_MEAN // just say no to MFC #define INITGUID #include <windows.h> // include important windows stuff #include <windowsx.h> #include <mmsystem.h> #include <iostream> // include important C/C++ stuff #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> // include directdraw // DEFINES //////////////////////////////////////////////// // defines for windows #define WINDOW_CLASS_NAME TEXT("WINCLASS1") // default screen size #define SCREEN_WIDTH 640 // size of screen #define SCREEN_HEIGHT 480 #define SCREEN_BPP 32 // bits per pixel #define BITMAP_ID 0x4D42 // universal id for a bitmap #define MAX_COLORS_PALETTE 256 #define _RGB32BIT(a,r,g,b) ((b) + ((g) << 8) + ((r) << 16) + ((a) << 24)) // TYPES ////////////////////////////////////////////////////// // basic unsigned types typedef unsigned short USHORT; typedef unsigned short WORD; typedef unsigned char UCHAR; typedef unsigned char BYTE; //BMP 位图容器 结构 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[2]; // 三帧的动画完整步行周期 int x,y; //外星人的位置 int velocity; //X坐标的速度 int current_frame; // 当前帧的动画 int counter; // 动画的使用时间 } ALIEN_OBJ, *ALIEN_OBJ_PTR; // PROTOTYPES ////////////////////////////////////////////// //翻转位图 int Flip_Bitmap(UCHAR *image, int bytes_per_line, int height); //读取位图 int Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char *filename); //释放内存 int Unload_Bitmap_File(BITMAP_FILE_PTR bitmap); //生成离屏表面 LPDIRECTDRAWSURFACE7 DDraw_Create_Surface(int width,int height,int mem_flags); //生成剪辑器 LPDIRECTDRAWCLIPPER DDraw_Attach_Clipper(LPDIRECTDRAWSURFACE7 lpdds,int num_rects,LPRECT clip_list); //填充表面 int DDraw_Fill_Surface(LPDIRECTDRAWSURFACE7 lpdds,int color); //扫描位图 int Scan_Image_Bitmap(BITMAP_FILE_PTR bitmap,LPDIRECTDRAWSURFACE7 lpdds,int cx, int cy); // MACROS ///////////////////////////////////////////////// #define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0) #define KEYUP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1) #define DDRAW_INIT_STRUCT(ddstruct) { memset(&ddstruct,0,sizeof(ddstruct)); ddstruct.dwSize=sizeof(ddstruct); } // GLOBALS //////////////////////////////////////////////// HWND main_window_handle = NULL; int window_closed = 0; HINSTANCE hinstance_app = NULL; // directdraw stuff LPDIRECTDRAW7 lpdd = NULL; // 申请接口对象 LPDIRECTDRAWSURFACE7 lpddsprimary = NULL; //主表面 LPDIRECTDRAWSURFACE7 lpddsback = NULL; //背面 LPDIRECTDRAWPALETTE lpddpal = NULL; //调色板指针 LPDIRECTDRAWCLIPPER lpddclipper = NULL; //剪切器 PALETTEENTRY palette[256]; // 调色板 PALETTEENTRY save_palette[256]; // 用于保存调色板 DDSURFACEDESC2 ddsd; // 直接绘制表面的描述结构 DDBLTFX ddbltfx; // 用来填充 DDSCAPS2 ddscaps; //直接绘制表面的功能结构 HRESULT ddrval; // result back from dd calls DWORD start_clock_count = 0; //用于定时 BITMAP_FILE bitmap; // holds the bitmap ALIEN_OBJ aliens[3]; //3个外星人 LPDIRECTDRAWSURFACE7 lpddsbackground=NULL; //这将保留背景图片 char buffer[80]; // general printing buffer int gwidth = -1; int gheight = -1; // FUNCTIONS //////////////////////////////////////////////// int Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char *filename) { //此函数打开一个位图文件,并加载数据导入位图 int file_handle, // 文件句柄 index; // 循环用的变量 UCHAR *temp_buffer = NULL; //用于把24位转换成16位的图像 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); // 返回 error return(0); } // end if //现在我们知道这是一个位图,所以在读取所有部分之前, // 首先是读取位图的 infoheader //现在载人位图文件头 _lread(file_handle, &bitmap->bitmapinfoheader,sizeof(BITMAPINFOHEADER)); // 最后,读取图像数据本身 _llseek(file_handle,-(int)(bitmap->bitmapinfoheader.biSizeImage),SEEK_END); //现在读的图像,如果图像是8位或16位则仅仅是读取它, //但如果是24位,就读入一个临时区域,然后将其转换为16位的图像 if (bitmap->bitmapinfoheader.biBitCount==8 || bitmap->bitmapinfoheader.biBitCount==16 || bitmap->bitmapinfoheader.biBitCount==24||bitmap->bitmapinfoheader.biBitCount==32) { // 删除最后的图像,如果有的话 if (bitmap->buffer) free(bitmap->buffer); // 为图像分配内存 if (!(bitmap->buffer = (UCHAR *)malloc(bitmap->bitmapinfoheader.biSizeImage))) { //分配失败,关闭文件 _lclose(file_handle); // 返回 error return(0); } // end if // 现在读取它 _lread(file_handle,bitmap->buffer,bitmap->bitmapinfoheader.biSizeImage); } // end if else { // 出现严重问题 return(0); } // end else #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); } // end Load_Bitmap_File /////////////////////////////////////////////////////////// int Unload_Bitmap_File(BITMAP_FILE_PTR bitmap) { // 这个函数释放与“位图“相关联的所有内存 if (bitmap->buffer) { // 释放内存 free(bitmap->buffer); //指针置空 bitmap->buffer = NULL; } // end if // return success return(1); } // end Unload_Bitmap_File /////////////////////////////////////////////////////////// int Flip_Bitmap(UCHAR *image, int bytes_per_line, int height) { //此函数是用来翻转自下而上的BMP图像 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 success return(1); } // end Flip_Bitmap LPDIRECTDRAWSURFACE7 DDraw_Create_Surface(int width,int height, int mem_flags) { // 这个函数创建一个简单的离屏表面 DDSURFACEDESC2 ddsd; LPDIRECTDRAWSURFACE7 lpdds;//临时用的表面 //清空并设置size值 DDRAW_INIT_STRUCT(ddsd); //设置宽,高,CAPS成员有效 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 0; } //设置色彩键 DDCOLORKEY color_key; color_key.dwColorSpaceLowValue=0; color_key.dwColorSpaceHighValue=0; //设置绑定 lpdds->SetColorKey(DDCKEY_SRCBLT,&color_key); return lpdds; } LPDIRECTDRAWCLIPPER DDraw_Attach_Clipper(LPDIRECTDRAWSURFACE7 lpdds, int num_rects, LPRECT clip_list) { //这个函数创建一个从发送剪辑列表Clipper和其附加到发送的表面 int index; // 循环变量 LPDIRECTDRAWCLIPPER lpddclipper; // 创建一个指向剪切器的指针 LPRGNDATA region_data; // 数据指针 // the header and clip list // 创建剪切器 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); // set up fields of header 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; // find bounds of all clipping regions for (index=0; index<num_rects; index++) { // test if the next rectangle unioned with the current bound is larger 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; } // end for index // now we have computed the bounding rectangle region and set up the data // now let's set the clipping list if (FAILED(lpddclipper->SetClipList(region_data, 0))) { // release memory and return error free(region_data); return(NULL); } // end if // now attach the clipper to the surface if (FAILED(lpdds->SetClipper(lpddclipper))) { // release memory and return error free(region_data); return(NULL); } // end if // all is well, so release memory and send back the pointer to the new clipper free(region_data); return(lpddclipper); } // end DDraw_Attach_Clipper int DDraw_Fill_Surface(LPDIRECTDRAWSURFACE7 lpdds,int color) { DDBLTFX ddbltfx; // 清空并设置size字段 DDRAW_INIT_STRUCT(ddbltfx); // 设置填充颜色 ddbltfx.dwFillColor = color; // 准备blt到表面 lpdds->Blt(NULL, // ptr to dest rectangle NULL, // ptr to source surface, NA NULL, // ptr to source rectangle, NA DDBLT_COLORFILL | DDBLT_WAIT, // fill and wait &ddbltfx); // ptr to DDBLTFX structure // return success return(1); } // end DDraw_Fill_Surface /////////////////////////////////////////////////////////////// int DDraw_Draw_Surface(LPDIRECTDRAWSURFACE7 source, // 要画的源表面 int x, int y, // 要绘制的位置 int width, int height, // 源表面的尺寸 LPDIRECTDRAWSURFACE7 dest, // 要画的目标表面 int transparent = 1) //透明颜色标志 { // draw a bob at the x,y defined in the BOB // on the destination surface defined in dest 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); } // end if else { //不启用色彩键 if (FAILED(dest->Blt(&dest_rect, source, &source_rect,(DDBLT_WAIT), NULL))) return(0); } // end if // return success return(1); } // end DDraw_Draw_Surface int Scan_Image_Bitmap(BITMAP_FILE_PTR bitmap, // 存放要扫描的位图文件的数据 LPDIRECTDRAWSURFACE7 lpdds, // 在表面存储数据 int cx, int cy) // 扫描图像的单元 { //此函数从位图文件中提取数据 UCHAR *source_ptr; // working pointers DWORD *dest_ptr; DDSURFACEDESC2 ddsd; // 直接绘制表面的描述 //获取到目标表面的内存地址 //设置结构的大小 ddsd.dwSize = sizeof(ddsd); // 锁定表面 lpdds->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, NULL); int ccx,ccy; // 计算开始扫描的位置 cx = cx*(ddsd.dwWidth) ; cy = cy*(ddsd.dwHeight) ; gwidth = ddsd.dwWidth; gheight = ddsd.dwHeight; // extract bitmap data source_ptr = bitmap->buffer + cy*bitmap->bitmapinfoheader.biWidth+cx; // assign a pointer to the memory surface for manipulation dest_ptr = (DWORD *)ddsd.lpSurface; // iterate thru each scanline and copy bitmap for (int index_y = 0; index_y < 80; index_y++) { for (int index_x = cx; index_x <cx+gwidth; index_x++) { // get BGR values UCHAR blue = (bitmap->buffer[index_y*640*4 + index_x*4 + 0]), green = (bitmap->buffer[index_y*640*4 + index_x*4 + 1]), red = (bitmap->buffer[index_y*640*4 + index_x*4 + 2]); // this builds a 32 bit color value in A.8.8.8 format (8-bit alpha mode) DWORD pixel = _RGB32BIT(0,red,green,blue); // write the pixel dest_ptr[index_x + (index_y*ddsd.lPitch >> 2)] = pixel; } // end for index_x } // end for index_y // unlock the surface lpdds->Unlock(NULL); // return success return(1); } // end Scan_Image_Bitmap
还有后面一部分,放在第二个文章里[/img]..