这个程式,是大三时期,为了做学校专题而做的练习
那时候利用DirectX做了萤幕保护程式
使用VC++6.0 + DirectX, Win32 SDK项目
/* 此為全螢幕模式框架,供遊戲設計使用。 請看Init()函式 */ #include "CDirectX.h"//引入自訂.h檔 /* 全域變數 */ int Init(); int Main(); int error; int ready=0; CDirectDraw xdraw; CSprite sghost1,sghost2,shappy,sghost_sleep; CTimer time; int move_x=3,move_y=3; ////////////////////////////////// #include <windows.h> LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM); int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPreInSTANCE,PSTR pCmdLine, int iCmdShow) { static TCHAR szAppName[]=TEXT("LoadImage"); HWND hwnd; MSG msg; WNDCLASS wndclass; wndclass.style=CS_DBLCLKS; wndclass.lpfnWndProc=WndProc; wndclass.cbClsExtra=0; wndclass.cbWndExtra=0; wndclass.hInstance=hInstance; wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION); wndclass.hCursor=LoadCursor(NULL,IDC_ARROW); wndclass.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);//TEST wndclass.lpszMenuName=NULL; wndclass.lpszClassName=szAppName; if(!RegisterClass(&wndclass)){ MessageBox(NULL,TEXT("視窗註冊錯誤"),0,MB_ICONERROR); return 0; } hwnd=CreateWindow(szAppName,TEXT("讀取圖片"), //修改視窗名稱 WS_POPUP,0,0,GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),0,0,hInstance,0); /*在此區初始化遊戲資訊*/ xdraw.SetMainHandle(hwnd,hInstance); //////////////////////// ShowWindow(hwnd,iCmdShow); UpdateWindow(hwnd); Init(); while(1){ if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { if(msg.message==WM_QUIT) break; TranslateMessage(&msg); DispatchMessage(&msg); } else { /* 進入遊戲主程式 */ Main(); } //////////////////////// } return msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam) { switch(message) { case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd,message,wParam,lParam); } int Init() { xdraw.DDraw_Init(640,480,16,false); xdraw.Fill_Primary_Surface(); xdraw.Fill_Back_Surface(); ///////////////////////////////////////////////////////////// // 本區為測試函數是否成功用 CBmp_File ghost1,ghost2,ghost3,ghost4,bhappy[2],bsleep[2]; ghost1.Load_Bmp_File("ghost1.bmp"); ghost2.Load_Bmp_File("ghost2.bmp"); ghost3.Load_Bmp_File("ghost3.bmp"); ghost4.Load_Bmp_File("ghost4.bmp"); bhappy[0].Load_Bmp_File("ghost5.bmp"); bhappy[1].Load_Bmp_File("ghost6.bmp"); bsleep[0].Load_Bmp_File("ghost7.bmp"); bsleep[1].Load_Bmp_File("ghost8.bmp"); sghost1.SetInfo(78,69,2); sghost2.SetInfo(78,69,2); shappy.SetInfo(78,69,2); sghost_sleep.SetInfo(78,69,2); for(int i=0;i<2;i++) { xdraw.Create_Surface(sghost1.image[i],78,69, //建立Offscreen Surface DDSCAPS_VIDEOMEMORY, ((USHORT *)ghost1.bitmap->buffer)[0]); xdraw.Create_Surface(sghost2.image[i],78,69, //建立Offscreen Surface DDSCAPS_VIDEOMEMORY, ((USHORT *)ghost1.bitmap->buffer)[0]); xdraw.Create_Surface(shappy.image[i],78,69, //建立Offscreen Surface DDSCAPS_VIDEOMEMORY, ((USHORT *)bhappy[i].bitmap->buffer)[0]); xdraw.Scan_Bmp(shappy.image[i],bhappy[i].bitmap,0,0); //測試Scan_Bmp xdraw.Create_Surface(sghost_sleep.image[i],78,69, //建立Offscreen Surface DDSCAPS_VIDEOMEMORY, ((USHORT *)bsleep[i].bitmap->buffer)[0]); xdraw.Scan_Bmp(sghost_sleep.image[i],bsleep[i].bitmap,0,0); //測試Scan_Bmp } xdraw.Scan_Bmp(sghost1.image[0],ghost1.bitmap,0,0); //測試Scan_Bmp xdraw.Scan_Bmp(sghost1.image[1],ghost2.bitmap,0,0); //測試Scan_Bmp xdraw.Scan_Bmp(sghost2.image[0],ghost3.bitmap,0,0); //測試Scan_Bmp xdraw.Scan_Bmp(sghost2.image[1],ghost4.bitmap,0,0); //測試Scan_Bmp sghost1.MoveTo(100,100); sghost2.MoveTo(100,100); shappy.MoveTo(300,300); sghost_sleep.MoveTo(400,200); srand(time.Start_Clock()); ///////////////////////////////////////////////////////////// return 1; } int Main() { time.Start_Clock(); static text_x=100,move_text=3; xdraw.Fill_Back_Surface(); if(text_x>450||text_x<80) { move_text=-move_text; } xdraw.Draw_Text_GDI("請按ESC結束程式 ^0^",text_x+=move_text,200,RGB(0,255,255)); static k=0; if( sghost1.Get_X()<0 || ( sghost1.Get_X()+sghost1.Get_Width() ) > 640 ) { move_x=-move_x; } if(sghost1.Get_Y()<0|| ( sghost1.Get_Y()+sghost1.Get_Height() ) > 480 ) { move_y=-move_y; } if(move_x>0) { //顯示往又跑的圖 //sghost1.Action(); sghost1.Move(move_x,move_y); sghost2.Move(move_x,move_y); xdraw.Blt_Back_Surface(sghost1.image[sghost1.num_frame], sghost1.Get_X(),sghost1.Get_Y(),78,69); sghost1.Action(); } else { //顯示往左跑的圖 sghost2.Action(); sghost1.Move(move_x,move_y); sghost2.Move(move_x,move_y); xdraw.Blt_Back_Surface(sghost2.image[sghost2.num_frame], sghost1.Get_X(),sghost1.Get_Y(),78,69); } static int a=0; if(a==8) { shappy.MoveTo(rand()%560,rand()%400); a=0; } else { a++; } shappy.Action(); xdraw.Blt_Back_Surface(shappy.image[shappy.num_frame], shappy.Get_X(),shappy.Get_Y(),78,69); xdraw.Blt_Back_Surface(sghost_sleep.image[shappy.num_frame], sghost_sleep.Get_X(),sghost_sleep.Get_Y(),78,69); if( KEY_DOWN(VK_ESCAPE) ) { k = 1; PostMessage(xdraw.GetHWND(),WM_DESTROY,0,0); } /*if( k && k < 32 ) { //測試顏色遮罩 int a; //漸漸變白色 USHORT *buff0=(USHORT *)xdraw.Lock_Back_Surface(a); USHORT *buff; DWORD dwCrSrc; for(int i=0;i<480;i++) { buff = buff0 + i*640; for(int j=0;j<640;j++) { dwCrSrc = *buff; dwCrSrc = ( dwCrSrc | ( dwCrSrc << 16 ) ) & 0x07E0F81F; dwCrSrc = ( ( k*(0x07E0F81F - dwCrSrc) + (dwCrSrc << 5) ) >> 5 ) & 0x07E0F81F; *buff++ = (USHORT)(dwCrSrc | ( dwCrSrc >> 16 )); } } xdraw.UnLock_Back_Surface(); if( k < 32 ) k++; }*/ xdraw.Flip_Primary(); time.Wait_Clock(120); return 1; }
CDirectX.h
/* 最後修改:04-14-2002 版本:4.0 功能:為製做遊戲而開發的引擎 製作人:許靖昕 參考資料: C++Primer、Tirck of Windows Game Programming of Gurus 附註: 本程式可修改、拷貝使用,但不可竄改作者。 */ /*///////////////////////////////////////////////////////////// 本類別使用方式,建立類別後必須先呼叫SetMainHandle() 設定視窗參數,因為建立DirectDraw需要視窗代號。 之後方可呼叫DDraw_Init()初始化DirectDraw。 *****本類別使用DirectX7.0版本***** /////////////////////////////////////////////////////////////*/ // 使用說明 // /* ***** 必要link ***** ddraw.lib dxguid.lib CDirectDraw:必須先呼叫SetMainHandle(),要將視窗代號傳入, 因為SetCooperativeLevel()需要視窗代號做參數。故須先設定。 第二步呼叫DDraw_Init(),建立DirectDraw畫面。 CBmp_File:建立後僅須呼叫Load_Bmp_File()讀取圖片即可。 CSprite:Sprite物件。基本建構完成。首先呼叫SetInfo()設定資 訊,然後便可以用CDirectDraw的Create_Surface()建立 Offscreen Surface。再利用Scan_Bmp將圖片資訊存入繪圖頁。 CTimer:計時器物件。先呼叫Start_Clock()取得開始時間。 然後呼叫Wait_Clock()決定暫停時間。 */ #ifndef _CDIRECTX_H #define _CDIRECTX_H /////////////////////////////////////////////////////////////// /* 定義類別 */ class CDirectDraw; //DirectDraw類別 class CBmp_File; //讀取16-bit和24-bitBMP的類別 class CSprite; //遊戲物件的類別 class CTimer; //計時器類別 /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// /* 引入檔 */ #include <windows.h> //因為HWND,所以須引入 #include <ddraw.h> //DirectDraw物件引入檔 #include <string> using namespace std; /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// /* 定義常用巨集 */ #define RELEASE(x) {if (x != NULL) {x->Release(); x = NULL;}}//釋放DirectX #define DD_INIT_STRUCT(x) {memset(&x,0,sizeof(x));x.dwSize=sizeof(x);}//初始化結構 #define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)//取得按鍵按下狀態 #define KEY_UP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)//取得按鍵放開狀態 #define _RGB16BIT555(r,g,b) ((b%32)+((g%32)<<5)+((r%32)<<10))//16BIT 555模式 #define _RGB16BIT565(r,g,b) ((b%32)+((g%64)<<6)+((r%32)<<11))//16BIT 565模式 #define _RGB32BIT(a,r,g,b) ((b) + ((g) << 8) + ((r) << 16) + ((a) << 24))//32-bit ARGB模式 #define BITMAP_ID 0x4D42//BMP檔的檔頭 #define MAX_IMAGE 16 //定義動畫張數的最大量 #define RED RGB(255,0,0) /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// /* 全域變數 */ /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// /* 定義資料結構 */ typedef struct _tgaSCREEN //定義儲存螢幕解析度及色彩之結構 { //同時儲存判斷DirectDraw是否為視窗模式 int width; int height; int bpp; bool windowed; }SCREEN; typedef struct BITMAP_FILE_TAG //定義BMP圖形檔案結構 { BITMAPFILEHEADER bmpfileheader; BITMAPINFOHEADER bmpinfoheader; PALETTEENTRY palette[256]; UCHAR *buffer; }BITMAP_FILE,*BITMAP_FILE_PTR; /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// /* DirectDraw物件 */ /* 版本:2.1 功能:建構DirectDraw。 附註:目前僅為全螢幕版本,視窗版本尚未測試。 使用說明:必須先呼叫SetMainHandle(),要將視窗代號傳入, 因為SetCooperativeLevel()需要視窗代號做參數, 故須先設定。第二步呼叫DDraw_Init(),建立 DirectDraw畫面。 */ class CDirectDraw { private: HWND main_hwnd; //視窗代號 HINSTANCE main_instance; //執行主體代號 SCREEN main_screen; //儲存顯示狀態之結構 LPDIRECTDRAW7 lpdd7; //DirectDraw物件 LPDIRECTDRAWSURFACE7 lpddsprimary, //SURFACE物件,Primary Surface lpddsback; //Back Surface DDSURFACEDESC2 ddsd; //DDSD2結構 LPDIRECTDRAWCLIPPER lpddclipper, lpddclipperwin; //Clipper物件 public: CDirectDraw(); //建構子設定所有data member為NULL CDirectDraw(HWND hwnd,HINSTANCE hInstance); //利用建購子設定視窗代號與執行主體代號 HWND GetHWND(); //傳回視窗代號 LPDIRECTDRAW7 GetDirectDraw(); //傳回DirectDraw物件 LPDIRECTDRAWSURFACE7 GetPrimarySurface();//傳回Primary Surface LPDIRECTDRAWSURFACE7 GetBackSurface(); //傳回Back Surface void SetMainHandle(HWND hwnd,HINSTANCE hInstance);//設定視窗代號與執行主體代號 int DDraw_Init(int width=640, int height=480, int bpp=16,bool windowed=false);//DDraw初始化 UCHAR *Lock_Primary_Surface(int &lpitch); //Lock主繪圖頁 UCHAR *Lock_Back_Surface(int &lpitch); //Lock副繪圖頁 int UnLock_Primary_Surface(); //UnLock主繪圖頁 int UnLock_Back_Surface(); //UnLock副繪圖頁 int Blt_Primary_Surface(RECT dest,RECT source); //Blt主繪圖頁,須修改 int Blt_Back_Surface(LPDIRECTDRAWSURFACE7 source, int x,int y,int width,int height); //Blt副繪圖頁,須修改 int Fill_Primary_Surface(RECT dest,USHORT color); //填充主繪圖頁區域 int Fill_Back_Surface(RECT dest,USHORT color); //填充副繪圖頁區域 int Fill_Primary_Surface(); //清除主繪圖頁 int Fill_Back_Surface(); //清除副繪圖頁 int Flip_Primary(); //Flip主繪圖頁 int Scan_Image(const CBmp_File &bmp,LPDIRECTDRAWSURFACE7 lpdds,int cx,int cy);//將圖片讀到Surface LPDIRECTDRAWCLIPPER DDraw_Attach_Clipper(LPDIRECTDRAWSURFACE7 lpdds, int num_rect, LPRECT clip_list); //附加Clipper物件 int Scan_Bmp(LPDIRECTDRAWSURFACE7 &lpdds, //掃圖檔進Surface BITMAP_FILE_PTR bitmap,int x,int y); BYTE Create_Surface(LPDIRECTDRAWSURFACE7 &plpdds, int width=0,int height=0, int mem_flags=DDSCAPS_VIDEOMEMORY,USHORT color=0);//建立Offscreen Surface int Draw_Text_GDI(const char *text=NULL, int x=0,int y=0, COLORREF color=RED); //顯示文字到Back Surface,顏色使用RGB() int Draw_Sprite(const CSprite &sprite); //繪製精靈到back surface ~CDirectDraw(); }; /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// /* 圖形檔案物件 */ /* 版本:2.0 功能:讀取Bmp檔 附註: 曾經出現配置bitmap錯誤的問題 必須配置malloc(sizeof(BITMAP_FILE)) 已由instant發現修正。 使用說明:建立後僅須呼叫Load_Bmp_File()讀取圖片即可。 */ class CBmp_File { protected: int Flip_Bmp(UCHAR *image, int bytes_per_line, int height);//翻轉圖片 public: CBmp_File();//不做任何事 int Load_Bmp_File(const char *filename);//讀取圖片 ~CBmp_File();//釋放圖片 BITMAP_FILE_PTR bitmap;//圖片指標結構 int Unload_Bmp_File();//釋放圖片 }; /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// /* CSprite類別 */ /* 版本:1.2 功能:建立遊戲的動畫物件 附註: 已利用符鬼圖片測試完畢。 使用說明: 首先呼叫SetInfo()設定資訊,然後便可以用 CDirectDraw的Create_Surface()建立 Offscreen Surface。再利用Scan_Bmp將圖片資訊存入繪圖頁。 */ class CSprite { protected: //因為遊戲物件可能要由sprite再繼承修改 //所以宣告為protected int x,y, //Sprite在螢幕的座標(圖形最左上角) width,height,//Sprite的寬高 //num_frame, //現在的frame數 frames; //Sprite的圖片總數 public: //單一動畫的規劃 CSprite(); //建構子,初始化物件 int num_frame; void Action(); //動畫循環播放 int Get_X(); //取得X座標 int Get_Y(); //取得Y座標 int Get_Width(); //取得圖片寬度 int Get_Height(); //取得圖片高度 int Get_Frames(); //取得動畫張數 int Get_Num_Frame(); //取得現在的動畫 void Move(int _x=0,int _y=0); //原始座標加上傳入位置 void MoveTo(int _x=0,int _y=0); //移動Sprite的到傳入的位置 void SetInfo(int _width,int _height,int _frames); LPDIRECTDRAWSURFACE7 image[MAX_IMAGE]; //根據動畫圖片張數配置動態陣列大小 //為OffScreen Surface ~CSprite(); //解構子,釋放配置的記憶體 }; /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// /* CTimer物件 */ /* 版本:1.0 功能:計時器物件。 附註: 使用說明:計時器物件。先呼叫Start_Clock()取得開始時間。 然後呼叫Wait_Clock()決定暫停時間。 */ class CTimer { private: DWORD start_clock_count; //紀錄開始的時間 DWORD Get_Clock(); //取得現在時間 public: DWORD Start_Clock(); //計時開始 DWORD Wait_Clock(DWORD count=30); //等待傳入的時間 }; /////////////////////////////////////////////////////////////// #endif
CDirectX.cpp
#include "CDirectX.h" //物件皆宣告在CDirectX.h #include <windows.h> //Windows程式必備引入檔 #include <io.h> #include <memory.h> //要使用malloc配置記憶體,free釋放 #include <ddraw.h> //DirectDraw引入檔 #include <stdio.h> //fopen的檔案I/O控制 ///////////////////////////////////////////////////////////////////// /* CDirectDraw類別 */ //CDirectDraw::lpdd7=NULL; //CDirectDraw::lpddsprimary=NULL; //CDirectDraw::lpddsback=NULL; CDirectDraw::CDirectDraw() //建構子,不傳入參數 { //初始化class data member //將全部設為NULL main_hwnd=NULL; main_instance=NULL; lpddclipper=NULL; lpdd7=NULL; lpddsprimary=NULL; lpddsback=NULL; } CDirectDraw::CDirectDraw(HWND hwnd,HINSTANCE hInstance)//建構子,傳入2參數 { //初始化class data member main_hwnd=hwnd; main_instance=hInstance; lpddclipper=NULL; lpdd7=NULL; lpddsprimary=NULL; lpddsback=NULL; } LPDIRECTDRAW7 CDirectDraw::GetDirectDraw() { return lpdd7; } HWND CDirectDraw::GetHWND() //傳回視窗代號HWND { return main_hwnd; } LPDIRECTDRAWSURFACE7 CDirectDraw::GetPrimarySurface()//傳回Primary Surface { return lpddsprimary; //傳回主繪圖頁 } LPDIRECTDRAWSURFACE7 CDirectDraw::GetBackSurface() //傳回Back Surface { return lpddsback; //傳回副繪圖頁 } void CDirectDraw::SetMainHandle(HWND hwnd,HINSTANCE hInstance)//設定視窗主體 { main_hwnd=hwnd; //指令視窗代號 main_instance=hInstance; //指令主體代號 } int CDirectDraw::DDraw_Init(int width,int height,int bpp,bool windowed)//初始化DirectDraw { LPDIRECTDRAW lpdd_tmp=NULL; //利用一個暫存LPDIRECTDRAW物件建立更新版物件 if(DirectDrawCreate(NULL,&lpdd_tmp,NULL)!=DD_OK)//建立DirectDraw物件 return 0; if(FAILED(lpdd_tmp->QueryInterface(IID_IDirectDraw7,(LPVOID *)&lpdd7))) return 0; RELEASE(lpdd_tmp); /////////////////////////////////////////////////////////////// main_screen.width=width; //儲存顯示狀態的資訊 main_screen.height=height; main_screen.bpp=bpp; main_screen.windowed=windowed; ////////////////////////////////////////////////////////////// if(main_screen.windowed) //設定為視窗模式 { if (FAILED(lpdd7->SetCooperativeLevel(main_hwnd,DDSCL_NORMAL))) return 0; } else //設定為全螢幕模式 { if (FAILED(lpdd7->SetCooperativeLevel(main_hwnd, DDSCL_ALLOWMODEX | DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT))) return(0); if (FAILED(lpdd7->SetDisplayMode(width,height,bpp,0,0))) return(0); } ////////////////////////////////////////////////////////////// /* 建立主副繪圖頁 */ DD_INIT_STRUCT(ddsd); if( !main_screen.windowed ) { //設定全螢幕模式的ddsd結構 ddsd.dwFlags=DDSD_CAPS|DDSD_BACKBUFFERCOUNT;//設定旗標為有效 ddsd.dwBackBufferCount=1; //back buffer數 //設定參數 ddsd.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE|DDSCAPS_COMPLEX|DDSCAPS_FLIP; } else { ddsd.dwFlags = DDSD_CAPS; //設定視窗模式時的ddsd結構 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; } if(FAILED(lpdd7->CreateSurface(&ddsd,&lpddsprimary,NULL)))//建立primary buffer return 0; if( !main_screen.windowed ) { //若為全螢幕模式,附加back surface到primary surface ddsd.ddsCaps.dwCaps=DDSCAPS_BACKBUFFER; //定義back buffer if(FAILED(lpddsprimary->GetAttachedSurface(&ddsd.ddsCaps,&lpddsback)))//附加back buffer到primary buffer return 0; } else { //建立一個雙重緩衝區供主繪圖頁使用 Create_Surface(lpddsback,main_screen.width, main_screen.height,0,0); } if( !main_screen.windowed ) { //將全螢幕的繪圖頁清空 Fill_Primary_Surface(); Fill_Back_Surface(); } else { //清空視窗模式的緩衝區 Fill_Back_Surface(); } ////////////////////////////////////////////////////////////// /* 附加Clipper(範圍為螢幕大小)物件Back Surface */ RECT screen_rect = {0,0,main_screen.width,main_screen.height}; lpddclipper = DDraw_Attach_Clipper(lpddsback,1,&screen_rect); if(main_screen.windowed) { //建立視窗Clipper if (FAILED(lpdd7->CreateClipper(0,&lpddclipperwin,NULL))) return(0); if (FAILED(lpddclipperwin->SetHWnd(0, main_hwnd))) return(0); if (FAILED(lpddsprimary->SetClipper(lpddclipperwin))) return(0); } ////////////////////////////////////////////////////////////// return 1; } UCHAR *CDirectDraw::Lock_Primary_Surface(int &lpitch)//Lock主繪圖頁 { //傳回一指標接收被lock的繪圖頁,然後進行修改 DD_INIT_STRUCT(ddsd); lpddsprimary->Lock(NULL,&ddsd,DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR,NULL); lpitch=ddsd.lPitch; return ((UCHAR *)ddsd.lpSurface); //傳回繪圖頁記憶體指標 } UCHAR *CDirectDraw::Lock_Back_Surface(int &lpitch)//Lock副繪圖頁 { //傳回一指標接收被lock的繪圖頁,然後進行修改 DD_INIT_STRUCT(ddsd); lpddsback->Lock(NULL,&ddsd,DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR,NULL); lpitch=ddsd.lPitch; return ((UCHAR *)ddsd.lpSurface); //傳回繪圖頁記憶體指標 } int CDirectDraw::UnLock_Primary_Surface() { //Unlock PrimarySurface lpddsprimary->Unlock(NULL); return 1; } int CDirectDraw::UnLock_Back_Surface() { //Unlock BackSurface lpddsback->Unlock(NULL); return 1; } int CDirectDraw::Flip_Primary() { //對Primary Surface 做 Page Flip while(FAILED(lpddsprimary->Flip(NULL, DDFLIP_WAIT))); return 1; } int CDirectDraw::Blt_Primary_Surface(RECT dest,RECT source) { if(FAILED(lpddsprimary->Blt(&dest, NULL, &source, DDBLT_WAIT, NULL))) return 0; return 1; } int CDirectDraw::Blt_Back_Surface(LPDIRECTDRAWSURFACE7 source, int x,int y,int width,int height) //將圖片畫到Back Surface { RECT dest_rt={x,y,x+width,y+height}, source_rt={0,0,width-1,height-1}; if(FAILED(lpddsback->Blt(&dest_rt, source, &source_rt, DDBLT_WAIT|DDBLT_KEYSRC,//須設source colorkey NULL))) return 0; return 1; } int CDirectDraw::Fill_Primary_Surface(RECT dest,USHORT color) { //利用某種顏色填滿Primary Surface的某塊區域 DDBLTFX ddbltfx; DD_INIT_STRUCT(ddbltfx); ddbltfx.dwFillColor=color; if(FAILED(lpddsprimary->Blt(&dest, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &ddbltfx))) return 0; return 1; } int CDirectDraw::Fill_Back_Surface(RECT dest,USHORT color) { //利用某種顏色填滿Back Surface的某塊區域 DDBLTFX ddbltfx; DD_INIT_STRUCT(ddbltfx); ddbltfx.dwFillColor=color;//指定填入顏色為color if(FAILED(lpddsback->Blt(&dest, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &ddbltfx))) return 0; return 1; } int CDirectDraw::Fill_Primary_Surface() { //用黑色填滿Primary Surface DDBLTFX ddbltfx; //宣告DDBLTFX結構 DD_INIT_STRUCT(ddbltfx);//初始化DDBLTFX結構 ddbltfx.dwFillColor=0;//指定填入顏色為0 if(FAILED(lpddsprimary->Blt(NULL, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &ddbltfx))) return 0; return 1; } int CDirectDraw::Fill_Back_Surface() { //用黑色填滿Back Surface DDBLTFX ddbltfx; DD_INIT_STRUCT(ddbltfx); ddbltfx.dwFillColor=0; if(FAILED(lpddsback->Blt(NULL, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &ddbltfx))) return 0; return 1; } LPDIRECTDRAWCLIPPER CDirectDraw::DDraw_Attach_Clipper(LPDIRECTDRAWSURFACE7 lpdds, int num_rect, LPRECT clip_list) { //將Clip物件附加到傳入的Suffer中 int index; LPDIRECTDRAWCLIPPER lpddclip;//Clip物件 LPRGNDATA region_data; //宣告LPRGNDATA結構,儲存Clip_List if(FAILED(lpdd7->CreateClipper(0,&lpddclip,NULL)))//建立Clipper return NULL; region_data=(LPRGNDATA)malloc(sizeof(RGNDATAHEADER)+num_rect*sizeof(RECT));//配置記憶體,因為此結構所需記憶體為動態,大小依傳入的RECT數決定 memcpy(region_data->Buffer,clip_list,num_rect*sizeof(RECT));//將資料copy到結構內 //設定RGNDATAHEADER結構 region_data->rdh.dwSize = sizeof(RGNDATAHEADER); region_data->rdh.iType = RDH_RECTANGLES; region_data->rdh.nCount = num_rect; region_data->rdh.nRgnSize = num_rect*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_rect; 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; } //設定Clip List if (FAILED(lpddclip->SetClipList(region_data, 0))) { //須釋放已配置的region_data free(region_data); return(NULL); } //將clipper附加到surface if (FAILED(lpdds->SetClipper(lpddclip))) { //須釋放已配置的region_data free(region_data); return(NULL); } //設定完成,傳回clpiier指標 free(region_data);//配置的資料須釋放 return(lpddclip); } int CDirectDraw::Scan_Image(const CBmp_File &bmp, LPDIRECTDRAWSURFACE7 lpdds, int cx,int cy)//將圖形資料填入Surface { UCHAR *source_ptr, //宣告儲存資訊的指標 *dest_ptr; //設定ddsd結構 DD_INIT_STRUCT(ddsd); //DDSURFACEDESC2 ddsd; //ddsd.dwSize=sizeof(ddsd); //Lock 繪圖頁 lpdds->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, NULL); //計算起始點 //cx = cx*(bmp.bitmap->bmpinfoheader.biWidth+1)+1; //cy = cy*(bmp.bitmap->bmpinfoheader.biHeight+1)+1; //source_ptr=bmp.bitmap->buffer+cy+cx; //將source_ptr指到傳入的bmp的座標 //從圖片的座標開始掃描 source_ptr=bmp.bitmap->buffer+(cy*bmp.bitmap->bmpinfoheader.biWidth*(bmp.bitmap->bmpinfoheader.biBitCount/8))+cx*(bmp.bitmap->bmpinfoheader.biBitCount/8); //將指標指派到記憶體繪圖頁 dest_ptr = (UCHAR *)ddsd.lpSurface; //重複掃描每一行資料 //此處修改為圖片高度 //是因為surface高度會造成小於surface高度的圖片無法顯示 //原為ddsd.dwWidth for (int index_y=0; index_y<bmp.bitmap->bmpinfoheader.biHeight; index_y++) { //拷貝圖檔一行長度的資料到Surface memcpy(dest_ptr, source_ptr, bmp.bitmap->bmpinfoheader.biWidth*(bmp.bitmap->bmpinfoheader.biBitCount)/8); //移動指標 dest_ptr += (ddsd.lPitch); //這個修改過了 source_ptr += bmp.bitmap->bmpinfoheader.biWidth*(bmp.bitmap->bmpinfoheader.biBitCount)/8; } //結束迴圈 //unlock 繪圖頁 lpdds->Unlock(NULL); return 1; } BYTE CDirectDraw::Create_Surface(LPDIRECTDRAWSURFACE7 &plpdds, int width,int height, int mem_flags, USHORT color) { DD_INIT_STRUCT(ddsd); //初始化ddsd結構 //指令下列旗標為有效 ddsd.dwFlags=DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT; //指定寬高 ddsd.dwWidth=width; ddsd.dwHeight=height; //設定為offscreen surface ddsd.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN|mem_flags; if(FAILED(lpdd7->CreateSurface(&ddsd,&plpdds,NULL))) { MessageBox(main_hwnd,"錯誤","錯誤",0); return NULL; } //設定color key,指定為bitmap資料的第一個pixel DDCOLORKEY color_key; color_key.dwColorSpaceLowValue=color; color_key.dwColorSpaceHighValue=color; plpdds->SetColorKey(DDCKEY_SRCBLT,&color_key); return 1; } int CDirectDraw::Scan_Bmp(LPDIRECTDRAWSURFACE7 &lpdds, //掃圖檔進Surface BITMAP_FILE_PTR bitmap,int x,int y) { //僅能讀取橫的圖片 UCHAR *source_ptr, //宣告儲存資訊的指標 *dest_ptr; //設定ddsd結構 DD_INIT_STRUCT(ddsd); //DDSURFACEDESC2 ddsd; //ddsd.dwSize=sizeof(ddsd); //Lock 繪圖頁 lpdds->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, NULL); //計算起始點 //從圖片的座標開始掃描 source_ptr=bitmap->buffer+(y*bitmap->bmpinfoheader.biWidth*(bitmap->bmpinfoheader.biBitCount/8))+x*(bitmap->bmpinfoheader.biBitCount/8); //將指標指派到記憶體繪圖頁 dest_ptr = (UCHAR *)ddsd.lpSurface; //Surface必定小於等於圖片大小 //原為ddsd.dwHeight for (int index_y=0; index_y<ddsd.dwHeight; index_y++) { //拷貝圖檔一行長度的資料到Surface memcpy(dest_ptr, source_ptr, bitmap->bmpinfoheader.biWidth*(bitmap->bmpinfoheader.biBitCount/8)); //移動指標 dest_ptr += (ddsd.lPitch); //移動為Surface寬度 source_ptr += bitmap->bmpinfoheader.biWidth*(bitmap->bmpinfoheader.biBitCount)/8; } //結束迴圈 //unlock 繪圖頁 lpdds->Unlock(NULL); return 1; } int CDirectDraw::Draw_Text_GDI(const char *text,//在back surface輸出文字 int x,int y, COLORREF color) { HDC xdc; if(FAILED(lpddsback->GetDC(&xdc)))//取得裝置代號 return 0; SetTextColor(xdc,color);//設定文字顏色 SetBkMode(xdc,TRANSPARENT);//設定文字背景為透明 TextOut(xdc,x,y,text,strlen(text));//輸出文字 lpddsback->ReleaseDC(xdc);//釋放DC return 1; } CDirectDraw::~CDirectDraw()//解構子 { RELEASE(lpddclipper); //釋放Clipper RELEASE(lpddclipperwin); RELEASE(lpddsback); //釋放back surface RELEASE(lpddsprimary); //釋放primary surface RELEASE(lpdd7); //釋放DirectDraw物件 } //////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////// /* 讀取圖檔的CBmp_File類別 */ CBmp_File::CBmp_File()//建構子 { bitmap=NULL; } int CBmp_File::Load_Bmp_File(const char *filename)//讀取圖檔 { //不管那麼多了,反正沒設調色盤,就只能讀取16bit和24bit的吧! int index; FILE *fp=NULL; //讀取檔案 fp=fopen(filename,"rb"); if(fp==NULL)//開檔失敗 return 0; //配置記憶體給bitmap bitmap=(BITMAP_FILE_PTR)malloc(sizeof(BITMAP_FILE)); bitmap->buffer=NULL; //讀取檔案檔頭 fread(&bitmap->bmpfileheader,sizeof(BITMAPFILEHEADER),1,fp); if(bitmap->bmpfileheader.bfType!=BITMAP_ID) { fclose(fp);//不是bmp就結束 return 0; }//讀取資料檔頭 fread(&bitmap->bmpinfoheader, sizeof(BITMAPINFOHEADER), 1, fp); //以下為將指標移到資料開頭 //因為bmp檔頭長度為54byte fseek(fp,54,SEEK_SET); if(bitmap->bmpinfoheader.biBitCount==8) { //256色圖檔,若未來需要加入256色功能再行修改 fclose(fp);//若是開到256色就結束 fp=NULL; return 0; } else if(bitmap->bmpinfoheader.biBitCount==16) { //16bit的圖檔 bitmap->buffer=(UCHAR *) malloc(bitmap->bmpinfoheader.biWidth*bitmap->bmpinfoheader.biHeight*(bitmap->bmpinfoheader.biBitCount/8)); if(bitmap->bmpinfoheader.biSizeImage==0) { fread(bitmap->buffer, bitmap->bmpinfoheader.biWidth*bitmap->bmpinfoheader.biHeight*(bitmap->bmpinfoheader.biBitCount/8), 1,fp); } else { UCHAR *buff_ptr=(UCHAR *)bitmap->buffer; UCHAR *temp=(UCHAR *)malloc(bitmap->bmpinfoheader.biSizeImage/bitmap->bmpinfoheader.biHeight); for(index=0;index<bitmap->bmpinfoheader.biHeight;index++) { fread(temp, bitmap->bmpinfoheader.biSizeImage/bitmap->bmpinfoheader.biHeight, 1,fp); //biSizeImage/biHeight=biWidth*(biBitCount/8) //因為16-bit的RGB為2byte,所以須*2 memcpy(buff_ptr,temp,2*bitmap->bmpinfoheader.biWidth); buff_ptr+=2*bitmap->bmpinfoheader.biWidth; } free(temp); temp=NULL; } } else if(bitmap->bmpinfoheader.biBitCount==24) { // 24-bit圖檔轉換為16-bit // UCHAR *temp=NULL;//宣告暫存區存放24-bit圖檔資料 //temp=(UCHAR *)malloc(bitmap->bmpfileheader.bfSize-54); temp=(UCHAR *)malloc(bitmap->bmpinfoheader.biWidth*bitmap->bmpinfoheader.biHeight*(bitmap->bmpinfoheader.biBitCount/8)); //配置成16bit大小的記憶體,因為為16-bit所以須*2 bitmap->buffer=(UCHAR *) malloc(2*bitmap->bmpinfoheader.biWidth*bitmap->bmpinfoheader.biHeight); //將影像資料讀到temp if(bitmap->bmpinfoheader.biSizeImage==0) {//若是biSizeImage為0則讀取寬*高*像素 fread(temp, bitmap->bmpinfoheader.biWidth*bitmap->bmpinfoheader.biHeight*(bitmap->bmpinfoheader.biBitCount/8), 1,fp); } else {//否則一行一行讀取 UCHAR *buff_ptr=(UCHAR *)temp; UCHAR *tmp2=(UCHAR *)malloc(bitmap->bmpinfoheader.biSizeImage/bitmap->bmpinfoheader.biHeight); for(index=0;index<bitmap->bmpinfoheader.biHeight;index++) { fread(tmp2, bitmap->bmpinfoheader.biSizeImage/bitmap->bmpinfoheader.biHeight, 1,fp); //biSizeImage/biHeight=biWidth*(biBitCount/8) //因為24-bit的RGB為3byte,所以須*3 memcpy(buff_ptr,tmp2,3*bitmap->bmpinfoheader.biWidth); buff_ptr+=3*bitmap->bmpinfoheader.biWidth; } free(tmp2); tmp2=NULL; } int i; USHORT color; //轉換24-bit為16bit for(i=0;i<bitmap->bmpinfoheader.biWidth*bitmap->bmpinfoheader.biHeight;i++) { //讀取RGB值 UCHAR blue = (temp[i*3 + 0] >> 3), green = (temp[i*3 + 1] >> 3), red = (temp[i*3 + 2] >> 3); //轉換為16bit的RGB color=_RGB16BIT565(red,green,blue); //將資料丟進bitmap中 ((USHORT *)bitmap->buffer)[i] = color; } bitmap->bmpinfoheader.biBitCount=16; free(temp); temp=NULL; } else { fclose(fp); fp=NULL; return 0; } fclose(fp); fp=NULL; Flip_Bmp(bitmap->buffer, //翻轉圖片 bitmap->bmpinfoheader.biWidth*(bitmap->bmpinfoheader.biBitCount/8), bitmap->bmpinfoheader.biHeight); return 1; } int CBmp_File::Unload_Bmp_File() { if(bitmap->buffer)//釋放圖片資料 { free(bitmap->buffer); bitmap->buffer=NULL; } if(bitmap)//釋放資料 { free(bitmap); bitmap=NULL; } return 1; } int CBmp_File::Flip_Bmp(UCHAR *image, int bytes_per_line, int height)//翻轉圖片 { //因為圖片起點是在左下角 UCHAR *buffer=NULL; 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(ℑ[((height-1) - index)*bytes_per_line], &buffer[index*bytes_per_line], bytes_per_line); //釋放記憶體 free(buffer); buffer=NULL; return(1); } CBmp_File::~CBmp_File() { Unload_Bmp_File();//呼叫釋放圖片的函數 } //////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////// /* CSprite類別 */ CSprite::CSprite() //建構子 { //初始化data member x=0,y=0,width=0,height=0; num_frame=0, frames=1; } void CSprite::Action() //控制動畫循環播放 { if(num_frame>=frames-1) num_frame=0; else num_frame++; //讓動畫不斷在所有Surface中循環播放 } void CSprite::Move(int _x,int _y)//原來座標加上傳入的座標 { x+=_x; y+=_y; } void CSprite::MoveTo(int _x,int _y)//移動到傳入的座標 { x=_x; y=_y; } void CSprite::SetInfo(int _width,int _height,int _frames) {//設定Sprite的寬高和框架數 width=_width,height=_height ,frames=_frames; } int CSprite::Get_X()//傳回X座標 { return x; } int CSprite::Get_Y()//傳回Y座標 { return y; } int CSprite::Get_Width()//傳回圖片寬度 { return width; } int CSprite::Get_Height()//傳回圖片寬度 { return height; } int CSprite::Get_Num_Frame()//傳回現在動畫 { return num_frame; } int CSprite::Get_Frames()//傳回動畫張數 { return frames; } CSprite::~CSprite() { int index;//將配置的Surface release for(index=frames-1;index<0;index--) RELEASE(image[index]); } //////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////// /* CTimer物件 */ DWORD CTimer::Get_Clock() { return (GetTickCount()); //利用GetTickCount()取得時間 //傳回值為毫秒(1/1000秒) } DWORD CTimer::Start_Clock() { return (start_clock_count=Get_Clock()); //開始計時 } DWORD CTimer::Wait_Clock(DWORD count) { while( (Get_Clock()-start_clock_count) < count );//計時count毫秒 return (GetTickCount()); } ////////////////////////////////////////////////////////////////////
不知道为甚么还看不到资源下载
等看到了在放上下载连结