client.cpp

来自「对游戏编程感兴趣的 朋友可以 下载下来看看 对DX讲解的很很详细」· C++ 代码 · 共 389 行

CPP
389
字号
#include <windows.h>
#include <mmsystem.h>
#include "resource.h"
#include "ddutil.h"

#define SCREEN_WIDTH 800	//创建DirectX的宽度,高度,颜色深度
#define SCREEN_HEIGHT 600
#define SCREEN_BPP 16	//XXXXX(红)XXXXXX(绿)XXXXX(蓝)
#define RGB16_GREEN	0x07E0 //0000,0111,1110,0000
#define RGB16_WHITE 0xFFFF //1111,1111,1111,1111
#define RGB16_BLACK 0x0000 //0000,0000,0000,0000

#define YUNDONG_UP    1		//定义运动的方向
#define YUNDONG_DOWN  2
#define YUNDONG_LEFT  3
#define YUNDONG_RIGHT 4

#define NUM_SPRITES 1	//定义出现的精灵图像个数

struct SPRITE			//定义精灵的运动结构
{
	FLOAT fPosX;		//出现的位置
	FLOAT fPosY;
	FLOAT fVelX;		//水平或垂直运动的速度
	FLOAT fVelY;
	DWORD dwWidth;		//定义的大小;		
	DWORD dwHeight;
	INT iFangXiang;		//精灵运动的方向
};

CDisplay* g_pDisplay;		//创建DirectX类的实例
CSurface* g_pLogoSurface;	//创建一个位图表面
CSurface* g_pTextSurface;	//创建一个文字表面
SPRITE g_Sprite[NUM_SPRITES];	//创建图像精灵		
DWORD g_dwLastTick ;		//记录时间
BOOL g_bActive;				//判断DirectX是否能活动
BOOL g_bLianJie;			//跳过窗口的判断变量

LRESULT CALLBACK MainWndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );//窗口的消息处理函数
HRESULT ProcessNextFrame();			//显示下一帧
void UpdateSprite( SPRITE* pSprite, FLOAT fTimeDelta );		//更新精灵的范围的边界情况
HRESULT DisplayFrame();		//显示帧的内容
HRESULT RestoreSurfaces();	//当平面信息丢失时更新平面的内容
VOID FreeDirectDraw();		//释放表面及DirectX实例


//////////////////////////////////////
//			应用程序入口			//
//////////////////////////////////////
int APIENTRY WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, int nCmdShow )
{
	WNDCLASS wc;
	HWND hWnd;
	HACCEL hAccel;
	MSG msg;
    
	ZeroMemory( &g_Sprite, sizeof(SPRITE) * NUM_SPRITES );
    srand( GetTickCount() );
	

	//////////////////////////////////////
	//			创建游戏窗体			//
	//////////////////////////////////////
	wc.lpszClassName = TEXT("Client");	//窗口类名称
	wc.lpfnWndProc = MainWndProc;		//消息处理函数
	wc.style = CS_VREDRAW | CS_HREDRAW;	//窗口的类型
	wc.hInstance = hInst;				//窗口实例(继承)
	wc.hIcon = LoadIcon( hInst, MAKEINTRESOURCE(IDI_MAIN) ); //窗口图标
	wc.hCursor = LoadCursor( NULL, IDC_ARROW );				//窗口鼠标
	wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);	//窗口的背景
	wc.lpszMenuName = NULL;	//窗口菜单
	wc.cbClsExtra = 0;	//保留
	wc.cbWndExtra = 0;	//保留

	if( RegisterClass( &wc ) == 0 )	//判断窗口类是否注册成功
		return E_FAIL;


	hWnd = CreateWindow( TEXT("Client"), TEXT("Client1"),	//创建窗口
						 WS_SYSMENU | WS_MAXIMIZEBOX, 180,110,
						 430, 230, NULL, NULL, hInst, NULL );

    if( hWnd == NULL )	//判断窗口是否创建成功
    	return E_FAIL;

	ShowWindow( hWnd, nCmdShow );	//显示窗口
	UpdateWindow( hWnd );		//更新窗口
	//以下四行内容显示一个窗口,可删除
	g_bLianJie = false;		//设置窗口退出条件
	while(GetMessage( &msg, NULL, 0, 0 ) && !g_bLianJie)	//显示窗口并处理消息
	{
		TranslateMessage( &msg );
		DispatchMessage( &msg );
	}

	hAccel = LoadAccelerators( hInst, MAKEINTRESOURCE(IDR_MAIN_ACCEL) );	//创建按键关联表

	//////////////////////////////////
	//			创建DirectDraw		//
	//////////////////////////////////
	HRESULT hr;
	
	g_pDisplay = new CDisplay();	//定义DirectX实例
	//创建一个全屏的窗体
	if( FAILED( hr = g_pDisplay->Create( hWnd, SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP ) ) )
		return hr;

	//创建一个平面,并且在画上一个位图资源,用于显示位图
	if( FAILED( hr = g_pDisplay->CreateSurfaceFromBitmap(&g_pLogoSurface, MAKEINTRESOURCE( IDB_DIRECTX ), 0, 0) ) )
		return hr;
	//设置位图显示时的透明颜色
	if( FAILED( hr = g_pLogoSurface->SetColorKey( RGB16_BLACK ) ) )
		return hr;
	//创建一个平面,并且在输出文字资源,用于显示文字
	if( FAILED( hr = g_pDisplay->CreateSurfaceFromText( &g_pTextSurface, NULL, "123456789",
														RGB(0,255,0), RGB(255, 255, 0) ) ) )
		return hr;
	//设置文字显示时的透明颜色(应该与文字背景色一致)
	if( FAILED( hr = g_pTextSurface->SetColorKey( RGB16_GREEN ) ) )
		return hr;

	for( int i = 0; i < NUM_SPRITES; i++ )	//定义精灵初始值
	{
		g_Sprite[i].fPosX = 0.0f;
		g_Sprite[i].fPosY = 0.0f;
        g_Sprite[i].fVelX = 0.0f;
        g_Sprite[i].fVelY = 0.0f;
		g_Sprite[i].dwWidth = g_pLogoSurface->GetWidth();	//得到位图平面的宽度和高度
		g_Sprite[i].dwHeight = g_pLogoSurface->GetHeight();
		g_Sprite[i].iFangXiang = YUNDONG_UP;
	}

	g_dwLastTick = timeGetTime();	//记录当前时间

	while(true)//进入消息循环,以下内容不明白,请有心人帮忙解释一下
	{
		if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )	//判断是否收到消息
		{
			//WM_QUIT退出消息
			if( 0 == GetMessage(&msg, NULL, 0, 0 ) )	
			{
				return (int)msg.wParam;
			}
	
			//翻译并且分派消息
			if( 0 == TranslateAccelerator( hWnd, hAccel, &msg ) )	//是否是按键表对应的消息
			{
				TranslateMessage( &msg );
				DispatchMessage( &msg );
			}
		}
		else
		{
			if( g_bActive )		//当可以重画屏幕时
			{
				if( FAILED( ProcessNextFrame() ) )	//显示下一帧
					return 0;
			}
			else
			{
				WaitMessage();		//等待消息
				g_dwLastTick = timeGetTime();	
			}
		}
	}
	return 0;
}

//////////////////////////////////////////////
//			游戏窗体消息处理函数			//
//////////////////////////////////////////////
LRESULT CALLBACK MainWndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
	HDC hdc;
	PAINTSTRUCT ps;

	switch (msg)
	{
		case WM_KEYDOWN:	//当任意键按下时退出开始的窗口
			g_bLianJie = true;
			return 0L;
		case WM_PAINT:	//重画屏幕消息与DirectX无关
		{
			hdc = BeginPaint(hWnd, &ps);	//得到DC
			HFONT hFont = CreateFont(30,0,0,0,0,0,0,0,0,0,0,0,0,"宋体");	//创建字体
			SelectObject(hdc, hFont);	//设置字体
			DeleteObject(hFont);	//删除字体
			//GetClientRect( hWnd, &rect );
			SetTextColor(hdc, RGB(0, 0, 0));	//设置颜色
			TextOut(hdc, 100, 50, "欢迎使用游戏", 12);	//显示文字
			SetTextColor(hdc, RGB(0, 0, 255));
			TextOut(hdc, 100, 100, "我的DirectXDraw", 15);

			EndPaint( hWnd, &ps);	//删除DC
            return 0L;
		}
		case WM_COMMAND:	
			switch ( LOWORD(wParam) )
			{
				case IDM_EXIT:	//按键表中的退出消息
					PostMessage( hWnd, WM_CLOSE, 0, 0 );
					return 0L;
				case IDM_UP:	//按键表中的向上消息
					g_Sprite[0].fVelX = 0.0f;	//水平不运动
					g_Sprite[0].fVelY = -100.0f;	//竖直向上
					g_Sprite[0].iFangXiang = YUNDONG_UP;	//运动方向
					break;
				case IDM_DOWN:	//按键表中的向下消息
					g_Sprite[0].fVelX = 0.0f;
					g_Sprite[0].fVelY = 100.0f;
					g_Sprite[0].iFangXiang = YUNDONG_DOWN;
					break;
				case IDM_LEFT:	//按键表中的向左消息
					g_Sprite[0].fVelX = -100.0f;
					g_Sprite[0].fVelY = 0.0f;
					g_Sprite[0].iFangXiang = YUNDONG_LEFT;
					break;
				case IDM_RIGHT:	//按键表中的向右消息
					g_Sprite[0].fVelX = 100.0f;
					g_Sprite[0].fVelY = 0.0f;
					g_Sprite[0].iFangXiang = YUNDONG_RIGHT;
					break;
			}
			break;
		case WM_SIZE:	//尺寸改变时
			if( SIZE_MAXHIDE == wParam || SIZE_MINIMIZED == wParam )
				g_bActive = FALSE;
			else
				g_bActive = TRUE;
        case WM_SETCURSOR:	//鼠标隐藏
            // Hide the cursor in fullscreen 
            SetCursor( NULL );
			return TRUE;
		case WM_SYSCOMMAND:	//系统消息,不可少
			switch( wParam )
			{
				case SC_MONITORPOWER:
					return TRUE;
			}
			break;
		case WM_DESTROY:	//窗口释放消息
            PostQuitMessage( 0 );	//抛出窗口退出消息
			FreeDirectDraw();	//释放平面
            return 0L;
	}
	return DefWindowProc(hWnd, msg, wParam, lParam);	//系统默认详细处理
}

//////////////////////////////////
//			显示下一帧			//
//////////////////////////////////
HRESULT ProcessNextFrame()	
{
	HRESULT hr;

	DWORD dwCurrTick = timeGetTime();	//得到当前时间	
	DWORD dwTickDiff = dwCurrTick - g_dwLastTick;	//显示暂停时间

	if( dwTickDiff == 0 )	//没有暂停退出
		return S_OK;

	g_dwLastTick = dwCurrTick;	//重新得到当前时间
	for( int i = 0; i < NUM_SPRITES; i++ )	
		UpdateSprite( &g_Sprite[i], dwTickDiff / 1000.0f );	//循环更新精灵的运动位置

	if( FAILED( hr = DisplayFrame() ) )	//显示屏幕的内容
	{
		if( hr != DDERR_SURFACELOST )	//判断屏幕信息是否丢失
			return hr;

		RestoreSurfaces();	//重新刷新表面内容
	}
	
	return S_OK;
}

//////////////////////////////////////////
//			更新精灵的运动位置			//
//										//
//	参数:精灵结构指针,屏幕未更新时间  //
//////////////////////////////////////////
void UpdateSprite( SPRITE* pSprite, FLOAT fTimeDelta )
{
	pSprite->fPosX += pSprite->fVelX * fTimeDelta;//计算新的位置
	pSprite->fPosY += pSprite->fVelY * fTimeDelta;
	
	//以下判断是否超出屏幕的范围
	if( pSprite->fPosX < 0.0f )	
	{
		pSprite->fPosX = FLOAT( SCREEN_WIDTH -1 - pSprite->dwWidth/2 );
	}

    if( pSprite->fPosX >= SCREEN_WIDTH - pSprite->dwWidth/2 )
    {
        pSprite->fPosX = 0;
    }

    if( pSprite->fPosY < 0 )
    {
        pSprite->fPosY = FLOAT( SCREEN_HEIGHT - 1 - pSprite->dwHeight/2 );
    }

    if( pSprite->fPosY > SCREEN_HEIGHT - pSprite->dwHeight/2 )
    {
        pSprite->fPosY = 0;
    }   
}

//////////////////////////////////////
//			显示帧的内容			//
//////////////////////////////////////
HRESULT DisplayFrame()
{
	HRESULT hr;
	RECT prc;

	g_pDisplay->Clear( 0x3F1F );	//使用指定的颜色覆盖屏幕

	for( int i =0; i < NUM_SPRITES; i++ )//循环显示每一个精灵
	{
		if ( g_Sprite[i].iFangXiang == YUNDONG_UP )	//显示箭头的方向
		{	
			prc.left=1;			//在平面位图中的位置	
			prc.top=1;
			prc.bottom = g_Sprite[i].dwHeight / 2;
			prc.right = g_Sprite[i].dwWidth / 2;
		}
		else if( g_Sprite[i].iFangXiang == YUNDONG_DOWN )
		{
			prc.top = g_Sprite[i].dwHeight / 2 + 1;
			prc.left = 1;
			prc.bottom = g_Sprite[i].dwHeight;
			prc.right = g_Sprite[i].dwWidth / 2;
		}
		else if( g_Sprite[i].iFangXiang == YUNDONG_RIGHT )
		{
			prc.top = 1;
			prc.left = g_Sprite[i].dwWidth / 2 + 1;
			prc.bottom = g_Sprite[i].dwHeight / 2;
			prc.right = g_Sprite[i].dwWidth;
		}
		else if( g_Sprite[i].iFangXiang == YUNDONG_LEFT )
		{
			prc.top = g_Sprite[i].dwHeight / 2 + 1;
			prc.left = g_Sprite[i].dwWidth / 2 + 1;
			prc.bottom = g_Sprite[i].dwHeight;
			prc.right = g_Sprite[i].dwWidth;
		}
		g_pDisplay->Blt( (DWORD)g_Sprite[i].fPosX, (DWORD)g_Sprite[i].fPosY,	//显示精灵
 					 g_pLogoSurface, &prc );
	}
	prc.top = 1;
	prc.bottom = g_pTextSurface->GetHeight();
	prc.left = 1;
	prc.right = g_pTextSurface->GetWidth();
	g_pDisplay->Blt( 10, 10, g_pTextSurface, NULL );	//在指定位置显示文字


	if( FAILED(hr = g_pDisplay->Present() ) )	//呈现这一帧图像
		return hr;
	return S_OK;
}

//////////////////////////////////
//			更新表面			//
//////////////////////////////////
HRESULT RestoreSurfaces()
{
	HRESULT hr;
	
	if( FAILED( hr = g_pDisplay->GetDirectDraw()->RestoreAllSurfaces() ) )	//实例恢复所有表面
		return hr;
	if( FAILED( hr = g_pTextSurface->DrawText( NULL, "2935629", RGB( 0, 0, 0 ), RGB( 255, 255, 255 ) ) ) )
		return hr;
	if( FAILED( hr = g_pLogoSurface->DrawBitmap( MAKEINTRESOURCE( IDB_DIRECTX ) ) ) )
		return hr;
	return S_OK;
}

//////////////////////////////////////
//			释放表面及实例			//
//////////////////////////////////////
VOID FreeDirectDraw()
{
	for( int i =0; i < NUM_SPRITES; i++ )
		SAFE_DELETE( g_pLogoSurface );
	SAFE_DELETE( g_pTextSurface );
	SAFE_DELETE( g_pDisplay );
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?