www.pudn.com > DDraw_Sprite.zip > DDex1.cpp
// // // #include#include #include "resource.h" #define NAME TEXT("DDExample1") #define TITLE TEXT("Direct Draw Example 1") #define IMAGE_COUNT 2 #define NUM_SPRITES 5 #define SCREEN_WIDTH 240 #define SCREEN_HEIGHT 320 #define SCREEN_BPP 8 #define SPRITE_DIAMETER 32 TCHAR fileNames[IMAGE_COUNT][MAX_PATH] = { L"\\Windows\\1.bmp", L"\\Windows\\2.bmp" }; static const TCHAR szMsg[] = TEXT("Page Flipping Test: Press F12 to exit"); static const TCHAR szFrontMsg[] = TEXT("Front buffer (F12 to quit)"); static const TCHAR szBackMsg[] = TEXT("Back buffer (F12 to quit)"); HINSTANCE g_hInst = NULL; HWND g_hwnd = NULL; int curImage = 0; RECT rect; DWORD g_dwLastTick; BOOL g_bActive = FALSE; LPDIRECTDRAW g_pDD = NULL; // DirectDraw object LPDIRECTDRAWSURFACE g_pDDSPrimary = NULL; // DirectDraw primary surface LPDIRECTDRAWSURFACE g_pDDSBack = NULL; // DirectDraw back surface LPDIRECTDRAWSURFACE g_pBmp = NULL; //LPDIRECTDRAWSURFACE g_pBmp[IMAGE_COUNT] = {0}; LPDIRECTDRAWSURFACE g_pDDSLogo = NULL; struct SPRITE_STRUCT { FLOAT fPosX; FLOAT fPosY; FLOAT fVelX; FLOAT fVelY; }; SPRITE_STRUCT g_Sprite[NUM_SPRITES]; void UpdateSprite(SPRITE_STRUCT* pSprite, FLOAT fTimeDelta); HRESULT ProcessNextFrame(); void ReleaseAllObjects(void); void UpdateFrame(); void MakeRect(int left, int top, int right, int bottom); LPDIRECTDRAWSURFACE BitmapSurface(LPCTSTR fileName); LPDIRECTDRAWSURFACE SpriteSurface(LPCTSTR fileName); BOOL InitDDraw(); BOOL InitWindow(HINSTANCE hInstance, int nShowCmd); LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); static HRESULT PASCAL EnumFunction(LPDIRECTDRAWSURFACE pSurface, LPDDSURFACEDESC lpSurfaceDesc, LPVOID lpContext); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd) { g_hInst = hInstance; ZeroMemory(&g_Sprite, sizeof(SPRITE_STRUCT) * NUM_SPRITES); srand( GetTickCount()); if(!InitWindow(hInstance, nShowCmd)) { return FALSE; } g_dwLastTick = timeGetTime(); MSG msg; //while(GetMessage(&msg, NULL, 0, 0)) //{ // TranslateMessage(&msg); // DispatchMessage(&msg); //} while(TRUE) { if(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { if(0 == GetMessage(&msg, NULL, 0, 0)) { return (int)msg.wParam; } TranslateMessage(&msg); DispatchMessage(&msg); } else { if(g_bActive) { if(FAILED(ProcessNextFrame())) { return FALSE; } } else { // Make sure we go to sleep if we have nothing else to do //WaitMessage(); // Ignore time spent inactive g_dwLastTick = timeGetTime();//获得当前系统时间 } } } return (int)msg.wParam; } BOOL InitWindow(HINSTANCE hInstance, int nShowCmd) { WNDCLASS wc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); wc.hCursor = NULL; wc.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_ICON1)); wc.hInstance = hInstance; wc.lpfnWndProc = WndProc; wc.lpszClassName = NAME; wc.lpszMenuName = NULL; wc.style = CS_HREDRAW | CS_VREDRAW; if(!RegisterClass(&wc)) { return FALSE; } g_hwnd = CreateWindow(/*WS_EX_TOPMOST,*/ NAME, TITLE, WS_POPUP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), NULL, NULL, hInstance, NULL); if(!g_hwnd) { return FALSE; } ShowWindow(g_hwnd, nShowCmd); UpdateWindow(g_hwnd); SetFocus(g_hwnd); InitDDraw(); return TRUE; } LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch(message) { case WM_LBUTTONUP: PostMessage(hwnd, WM_DESTROY, 0, 0); break; case WM_DESTROY: { ReleaseAllObjects(); PostQuitMessage(0); } break; case WM_SIZE: if( SIZE_MAXHIDE==wParam || SIZE_MINIMIZED==wParam ) g_bActive = FALSE; else g_bActive = TRUE; //UpdateFrame(); break; case WM_EXITMENULOOP: g_dwLastTick = timeGetTime(); break; case WM_MOVE: //UpdateFrame(); break; case WM_TIMER: { //KillTimer(hwnd, 1); //curImage++; //if(curImage>1) //{ // curImage = 0; //} UpdateFrame(); } break; } return DefWindowProc(hwnd, message, wParam, lParam); } BOOL InitDDraw() { DDSURFACEDESC ddsd; if(DD_OK != DirectDrawCreate(NULL, &g_pDD, NULL)) { return FALSE; } if(DD_OK != g_pDD->SetCooperativeLevel(g_hwnd, DDSCL_FULLSCREEN)) { return FALSE; } //if(DD_OK != g_pDD->SetDisplayMode(240,320,24,0,0)) //{ // return FALSE; //} DDCAPS ddCaps; DDCAPS ddHelCaps; g_pDD->GetCaps(&ddCaps, &ddHelCaps); if (!(ddCaps.ddsCaps.dwCaps & DDSCAPS_BACKBUFFER)) { return FALSE; //return InitFail(hWnd, E_FAIL, szNoBackBufferMsg); } if (!(ddCaps.ddsCaps.dwCaps & DDSCAPS_FLIP)) { return FALSE; //return InitFail(hWnd, E_FAIL, szNoFlipSurfacesMsg); } memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP; ddsd.dwBackBufferCount = 1; if(DD_OK != g_pDD->CreateSurface(&ddsd, &g_pDDSPrimary, NULL)) { return FALSE; } //ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER; if(DD_OK != g_pDDSPrimary->EnumAttachedSurfaces(&g_pDDSBack, EnumFunction)) { return FALSE; } g_pBmp = BitmapSurface(MAKEINTRESOURCE(IDB_BITMAP1)); if(!g_pBmp) { return FALSE; } g_pDDSLogo = SpriteSurface(MAKEINTRESOURCE(IDB_DIRECTX)); if(!g_pDDSLogo) { return FALSE; } DDCOLORKEY ddck; ddck.dwColorSpaceLowValue = RGB(0,0,0); ddck.dwColorSpaceHighValue = RGB(0,0,0); g_pDDSLogo->SetColorKey(DDCKEY_SRCBLT, &ddck); for(int iSprite = 0; iSprite < NUM_SPRITES; iSprite++) { // Set the sprite's position and velocity // 设置这些 sprite(小怪物)的初始坐标随机产生 g_Sprite[iSprite].fPosX = (float) (rand() % SCREEN_WIDTH); g_Sprite[iSprite].fPosY = (float) (rand() % SCREEN_HEIGHT); // 速度也随机产生 g_Sprite[iSprite].fVelX = 500.0f * rand() / RAND_MAX - 250.0f; g_Sprite[iSprite].fVelY = 500.0f * rand() / RAND_MAX - 250.0f; //g_Sprite[iSprite].fVelX = (FLOAT)(500.0f * rand() / RAND_MAX); //g_Sprite[iSprite].fVelY = (FLOAT)(500.0f * rand() / RAND_MAX); } UpdateFrame(); //SetTimer(g_hwnd, 1, 50, 0); return TRUE; } static HRESULT PASCAL EnumFunction(LPDIRECTDRAWSURFACE pSurface, LPDDSURFACEDESC lpSurfaceDesc, LPVOID lpContext) { static BOOL bCalled = FALSE; if(!bCalled) { //lpSurfaceDesc->ddsCaps.dwCaps = DDSCAPS_BACKBUFFER; *((LPDIRECTDRAWSURFACE *)lpContext) = pSurface; bCalled = TRUE; return DDENUMRET_OK; } else { OutputDebugString(L"DDEX1: Enumerated more than surface?"); pSurface->Release(); return DDENUMRET_CANCEL; } } LPDIRECTDRAWSURFACE SpriteSurface(LPCTSTR fileName) { HDC hdc; HBITMAP hBitmap; LPDIRECTDRAWSURFACE surf; hBitmap = LoadBitmap(g_hInst, fileName); //hBitmap = (HBITMAP)LoadImage(g_hInst, fileName, IMAGE_BITMAP, 0, 0, 0); if(!hBitmap) { return NULL; } BITMAP bmp; GetObject(hBitmap, sizeof(BITMAP), &bmp); int surfWidth = bmp.bmWidth; int surfHeight = bmp.bmHeight; DDSURFACEDESC ddsd; memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY; ddsd.dwWidth = 32; ddsd.dwHeight = 32; if(DD_OK != g_pDD->CreateSurface(&ddsd, &surf, NULL)) { DeleteObject(hBitmap); return NULL; } else { surf->GetDC(&hdc); HDC bitDC = CreateCompatibleDC(hdc); //hBitmap = CreateCompatibleBitmap(hdc, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); //FillRect(); SelectObject(bitDC, hBitmap); //TransparentImage(bitDC, 0, 0, surfWidth, surfHeight, hBitmap, 0, 0, surfWidth, surfHeight, RGB(255,255,255)); //TransparentBlt(hdc, 0, 0, surfWidth, surfHeight, bitDC, 0, 0, surfWidth, surfHeight, RGB(255,255,255)); BitBlt(hdc, 0, 0, surfWidth, surfHeight, bitDC, 0, 0, SRCCOPY); surf->ReleaseDC(hdc); DeleteDC(bitDC); } DeleteObject(hBitmap); return surf; } LPDIRECTDRAWSURFACE BitmapSurface(LPCTSTR fileName) { HDC hdc; HBITMAP hBitmap; LPDIRECTDRAWSURFACE surf; hBitmap = LoadBitmap(g_hInst, fileName); //hBitmap = (HBITMAP)LoadImage(g_hInst, fileName, IMAGE_BITMAP, 0, 0, 0); if(!hBitmap) { return NULL; } BITMAP bmp; GetObject(hBitmap, sizeof(BITMAP), &bmp); int surfWidth = bmp.bmWidth; int surfHeight = bmp.bmHeight; DDSURFACEDESC ddsd; memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY; ddsd.dwWidth = 240; ddsd.dwHeight = 320; if(DD_OK != g_pDD->CreateSurface(&ddsd, &surf, NULL)) { DeleteObject(hBitmap); return NULL; } else { surf->GetDC(&hdc); HDC bitDC = CreateCompatibleDC(hdc); //hBitmap = CreateCompatibleBitmap(hdc, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); //FillRect(); SelectObject(bitDC, hBitmap); BitBlt(hdc, 0, 0, surfWidth, surfHeight, bitDC, 0, 0, SRCCOPY); surf->ReleaseDC(hdc); DeleteDC(bitDC); } DeleteObject(hBitmap); return surf; } void UpdateFrame() { if(!g_pBmp) { g_pBmp = BitmapSurface(MAKEINTRESOURCE(IDB_BITMAP1)); if(!g_pBmp) { return; } } static BYTE phase = 0; //RECT rc; //SIZE size; //int nMsg; //HDC hdc; DDBLTFX ddbltfx; memset(&ddbltfx, 0, sizeof(ddbltfx)); ddbltfx.dwSize = sizeof(ddbltfx); ddbltfx.dwFillColor = 0; MakeRect(0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); //if(DD_OK == g_pDDSBack->GetDC(&hdc)) //{ // SetBkColor(hdc, RGB(0,255,255)); // SetTextColor(hdc, RGB(255,0,0)); // GetClientRect(g_hwnd, &rc); // if(phase) // { // nMsg = lstrlen(szMsg); // GetTextExtentPoint(hdc, szMsg, nMsg, &size); // ExtTextOut(hdc, (rc.right-size.cx)/2, (rc.bottom-size.cy)/2, 0, NULL, szMsg, nMsg, NULL); // nMsg = lstrlen(szFrontMsg); // GetTextExtentPoint(hdc, szFrontMsg, nMsg, &size); // ExtTextOut(hdc, (rc.right-size.cx)/2, 0, 0, NULL, szFrontMsg, nMsg, NULL); // phase = 0; // } // else // { // nMsg = lstrlen(szBackMsg); // GetTextExtentPoint(hdc, szBackMsg, nMsg, &size); // ExtTextOut(hdc, (rc.right-size.cx)/2, 0, 0, NULL, szBackMsg, nMsg, NULL); // phase = 1; // } // g_pDDSBack->ReleaseDC(hdc); //} //if(DD_OK == g_pBmp[curImage]->GetDC(&hdc)) //{ // SetBkColor(hdc, RGB(0,255,255)); // SetTextColor(hdc, RGB(255,0,0)); // GetClientRect(g_hwnd, &rc); // if(phase) // { // nMsg = lstrlen(szMsg); // GetTextExtentPoint(hdc, szMsg, nMsg, &size); // ExtTextOut(hdc, (rc.right-size.cx)/2, (rc.bottom-size.cy)/2, 0, NULL, szMsg, nMsg, NULL); // nMsg = lstrlen(szFrontMsg); // GetTextExtentPoint(hdc, szFrontMsg, nMsg, &size); // ExtTextOut(hdc, (rc.right-size.cx)/2, 0, 0, NULL, szFrontMsg, nMsg, NULL); // phase = 0; // } // else // { // nMsg = lstrlen(szBackMsg); // GetTextExtentPoint(hdc, szBackMsg, nMsg, &size); // ExtTextOut(hdc, (rc.right-size.cx)/2, 0, 0, NULL, szBackMsg, nMsg, NULL); // phase = 1; // } // g_pBmp[curImage]->ReleaseDC(hdc); //} g_pDDSBack->Blt(NULL, NULL, NULL, DDBLT_COLORFILL, &ddbltfx); g_pDDSBack->Blt(NULL, g_pBmp, &rect, DDBLT_WAITNOTBUSY, 0); RECT rcSprite; for(int iSprite = 0; iSprite < NUM_SPRITES; iSprite++) { rcSprite.left = (LONG)g_Sprite[iSprite].fPosX; rcSprite.top = (LONG)g_Sprite[iSprite].fPosY; rcSprite.right = (LONG)g_Sprite[iSprite].fPosX + 32; rcSprite.bottom = (LONG)g_Sprite[iSprite].fPosY + 32; g_pDDSBack->Blt(&rcSprite, g_pDDSLogo, NULL, DDBLT_WAITNOTBUSY|DDBLT_KEYSRC, 0); } g_pDDSPrimary->Blt(NULL, g_pDDSBack, &rect, DDBLT_WAITNOTBUSY, 0); //HRESULT hRet = g_pDDSPrimary->Flip(NULL, 0); //int nextSlide = (curImage >= IMAGE_COUNT-1) ? 0 : curImage+1; //if(!g_pBmp[nextSlide]) //{ // g_pBmp[nextSlide] = BitmapSurface(MAKEINTRESOURCE(IDB_BITMAP1+nextSlide)); //} //int prevSlide = (curImage < 1) ? IMAGE_COUNT-1 : curImage-1; //if(!g_pBmp[prevSlide]) //{ // g_pBmp[prevSlide] = BitmapSurface(MAKEINTRESOURCE(IDB_BITMAP1+prevSlide)); //} } void MakeRect(int left, int top, int right, int bottom) { rect.left = left; rect.top = top; rect.right = right; rect.bottom = bottom; } void ReleaseAllObjects(void) { //for(int i = 0; i < IMAGE_COUNT; i++) //{ // if(g_pBmp[i] != NULL) // { // g_pBmp[i]->Release(); // g_pBmp[i] = NULL; // } //} if(g_pBmp != NULL) { g_pBmp->Release(); g_pBmp = NULL; } if(g_pDDSLogo != NULL) { g_pDDSLogo->Release(); g_pDDSLogo = NULL; } if (g_pDDSBack != NULL) { g_pDDSBack->Release(); g_pDDSBack = NULL; } if (g_pDDSPrimary != NULL) { g_pDDSPrimary->Release(); g_pDDSPrimary = NULL; } if (g_pDD != NULL) { g_pDD->Release(); g_pDD = NULL; } } HRESULT ProcessNextFrame() { //HRESULT hr; DWORD dwCurrTick = timeGetTime(); DWORD dwTickDiff = dwCurrTick - g_dwLastTick; if(dwTickDiff == 0) { return S_OK; } g_dwLastTick = dwCurrTick; for(int iSprite = 0; iSprite < NUM_SPRITES; iSprite++) { UpdateSprite(&g_Sprite[iSprite], dwTickDiff / 1000.0f); } UpdateFrame(); return S_OK; } void UpdateSprite(SPRITE_STRUCT* pSprite, FLOAT fTimeDelta) { pSprite->fPosX += pSprite->fVelX * fTimeDelta; pSprite->fPosY += pSprite->fVelY * fTimeDelta; if(pSprite->fPosX < 0.0f) { pSprite->fPosX = 0; pSprite->fVelX = -pSprite->fVelX; } if(pSprite->fPosX >= SCREEN_WIDTH - SPRITE_DIAMETER) { pSprite->fPosX = SCREEN_WIDTH - SPRITE_DIAMETER - 1; pSprite->fVelX = -pSprite->fVelX; } if(pSprite->fPosY < 0) { pSprite->fPosY = 0; pSprite->fVelY = -pSprite->fVelY; } if(pSprite->fPosY > SCREEN_HEIGHT - SPRITE_DIAMETER) { pSprite->fPosY = SCREEN_HEIGHT - 1 - SPRITE_DIAMETER; pSprite->fVelY = -pSprite->fVelY; } }