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; 
	}  
}