。。真不容易啊,被個素材搞到我吐血,本來是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
還有後面一部分,放在第二個文章裡
本文出自 “Chaos代碼空間” 博客,請務必保留此出處http://flzt5354.blog.51cto.com/1568074/589804