【DirectX 2D游戏开发基础】DirectX的应用实例

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/shangdi712/article/details/48014777

       这次,主要就是利用前面几篇博客里面的例子,来做几个应用练习,主要就是,让图片闪烁,一次读取多张图片,和使用随机数随机读取图片(当然,这里的随机数用的是C语言,而不是C++的随机数引擎,但是原理是一样的),这次,我把我的代码工程上传上来,希望大家下载学习,毕竟 里面会涉及到一些资源问题,把代码复制去了,改起来挺麻烦也。地址:http://download.csdn.net/detail/shangdi712/7704977

     

//Utility.h

#ifndef WINDOWS_USEFUL_TOOLS_
#define WINDOWS_USEFUL_TOOLS_
#include <Windows.h>
#include <MMSystem.h>
#pragma comment(lib,"Winmm.lib")
#include <wchar.h>
#include <time.h>
#endif

#ifndef D3D_USEFUL_TOOLS_
#define D3D_USEFUL_TOOLS_
#include <d3d9.h>
#pragma comment(lib,"d3d9.lib")
#include <d3dx9.h>
#pragma comment(lib,"d3dx9.lib")
#endif

#ifndef SAFE_CLEANUP_
#define SAFE_CLEANUP_

//内联函数模板,参数为 T* 类型的引用
template<typename T>inline void Safe_Delete( T* & p )
{
	if(p){ delete p ; p = NULL;}
}

template<typename T>inline void Safe_Release( T* & p )
{
	if(p){ p->Release() ; p = NULL;}
}

#endif


#ifndef STL_TOOLS_
#define STL_TOOLS_
#include <vector>
#include <string>
using namespace std;
#endif

#ifdef UNICODE
#define string wstring
#define sprintf_s swprintf_s
#else
#define string string
#define sprintf_s sprintf_s
#endif


//WinMain.cpp

#include "Utility.h"

HWND g_hWnd = 0;
int g_iWidth = 800;
int g_iHeight = 600;
HINSTANCE g_hInstance = 0;

LRESULT CALLBACK WndProc(HWND hWnd ,UINT uMsg,
						 WPARAM wParam,LPARAM lParam);

LPDIRECT3D9 g_pD3D = nullptr;
LPDIRECT3DDEVICE9 g_pDevice = nullptr;

LPD3DXSPRITE g_pSprite = nullptr;	//精灵指针
D3DXMATRIX g_matIdentity;	//用于恢复渲染状态的单位矩阵


LPDIRECT3DTEXTURE9 g_pRole = nullptr;	//纹理指针
D3DXIMAGE_INFO g_info;	//图片信息
D3DXMATRIX g_matWorld;	//世界矩阵
D3DXVECTOR2 g_vRolePos;	//角色位置

UINT g_iDruation = 1000;	//持续时间(毫秒单位)
D3DCOLOR g_dwMainColor = D3DCOLOR_XRGB(255,255,255);	//颜色

//我们自定义的图片结构体,包含指针于图片信息
struct stTexture
{
	LPDIRECT3DTEXTURE9 pTexture;	//纹理指针
	D3DXIMAGE_INFO imageInfo;		//纹理详细信息
	D3DXVECTOR2 vPos;				//在屏幕的坐标
	D3DXMATRIX matWorld;			//矩阵变换
};
vector<stTexture*> g_vTextures;		//图片容器

/************************************************************************/
/* 
	有用的知识点:
	1、800*600的窗口,但客户区不足800*600
	   GetClientRect,用于获取客户区像素数

	2、加载一组图片:图片名字有共同特点:前缀+数字+后缀

	3、随机数:随机数种子(整个程序有1个就够了)
			 srand(seed)、rand()
*/
/************************************************************************/

VOID CALLBACK TimerProc(HWND hwnd, UINT uMsg, 
	UINT idEvent,DWORD dwTime)
{
	if (g_dwMainColor == D3DCOLOR_XRGB(255, 255, 255))
		g_dwMainColor = D3DCOLOR_XRGB(255, 0, 0);
	else if (g_dwMainColor == D3DCOLOR_XRGB(255, 0, 0))
		g_dwMainColor = D3DCOLOR_XRGB(255, 255, 255);


	for (int i = 0; i < 10; ++i)
	{
		g_vTextures.at(i)->vPos.x = rand() % 801;
		g_vTextures.at(i)->vPos.y = rand() % 601;
	}
}

VOID LoadTextures(string front, int iCount, string back)
{
	TCHAR strTemp[100] = {};

	for (int i = 1; i <= iCount; ++i)
	{
		sprintf_s(
				strTemp,			//字符串存储位置
				TEXT("%s%d%s"),		//格式			
				front.c_str(), i, back.c_str()//替换格式中%...的数据
				);

		stTexture * pTemp = new stTexture;
		ZeroMemory(pTemp, sizeof(stTexture));
 
		D3DXCreateTextureFromFileEx(
			g_pDevice,
			strTemp,
			D3DX_FROM_FILE, D3DX_FROM_FILE, 0, 0, D3DFMT_UNKNOWN,
			D3DPOOL_MANAGED, D3DX_FILTER_LINEAR, D3DX_FILTER_LINEAR,
			D3DCOLOR_XRGB(254, 254, 254), &(pTemp->imageInfo), 
			nullptr, &(pTemp->pTexture));

		pTemp->vPos = D3DXVECTOR2(0, 0);
		D3DXMatrixIdentity(&(pTemp->matWorld));

		g_vTextures.push_back(pTemp);
	}
}

VOID onInitGame()
{
	////获取客户区大小的函数
	//RECT clientRect;
	//SetRectEmpty(&clientRect);
	//GetClientRect(g_hWnd, &clientRect);

	D3DXCreateSprite(g_pDevice, &g_pSprite);

	ZeroMemory(&g_info, sizeof(g_info));
	D3DXCreateTextureFromFileEx(
		g_pDevice,
		TEXT("Resources\\Textures\\Fighter1.png"),
		D3DX_FROM_FILE,D3DX_FROM_FILE,0,0,D3DFMT_UNKNOWN,
		D3DPOOL_MANAGED,D3DX_FILTER_LINEAR,D3DX_FILTER_LINEAR,
		D3DCOLOR_XRGB(254,254,254),&g_info,nullptr,&g_pRole);

	D3DXMatrixIdentity(&g_matWorld);
	D3DXMatrixIdentity(&g_matIdentity);
	g_vRolePos.x = 400;
	g_vRolePos.y = 200;

	//激活一个定时器
	SetTimer(g_hWnd, 1, g_iDruation, TimerProc);

	//测试
	LoadTextures(TEXT("Resources\\Textures\\Fighter"), 10, TEXT(".png"));
}

VOID onInit()
{
	//随机数种子
	srand((unsigned)time(nullptr));

	g_pD3D = Direct3DCreate9(D3D_SDK_VERSION);
	D3DDISPLAYMODE d3ddm;
	ZeroMemory(&d3ddm, sizeof(D3DDISPLAYMODE));
	g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm);

	D3DPRESENT_PARAMETERS d3dpp;
	ZeroMemory(&d3dpp, sizeof(d3dpp));
	d3dpp.BackBufferCount = 1;
	d3dpp.Windowed = true;
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
		g_hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pDevice);

	onInitGame();
}
VOID onLogic(float fElapsedTime)
{

}

VOID onRender(float fElapsedTime)
{
	g_pDevice->Clear(0, nullptr, D3DCLEAR_TARGET,
		D3DCOLOR_XRGB(123, 123, 234), 1.0f, 0);
	g_pDevice->BeginScene();

	g_pSprite->Begin(D3DXSPRITE_ALPHABLEND);

	//--------------------------绘制一张图片--------------------------
	//得到矩阵
	D3DXMatrixTransformation2D(
		&g_matWorld, nullptr, 0.0f,
		&D3DXVECTOR2(1.0f, 1.0f),
		&D3DXVECTOR2(0.0f, 0.0f),
		0.0f,		//弧度制
		&g_vRolePos
		);

	//应用矩阵
	g_pSprite->SetTransform(&g_matWorld);

	//渲染
	g_pSprite->Draw(g_pRole, nullptr, &D3DXVECTOR3(0, 0, 0),
		&D3DXVECTOR3(0, 0, 0), g_dwMainColor);

	//恢复渲染状态
	g_pSprite->SetTransform(&g_matIdentity);
	//---------------------------------------------------------------

 

	//----绘制一组图片----
	for (int i = 0; i < 10; ++i)
	{
		D3DXMatrixTransformation2D(
			&(g_vTextures.at(i)->matWorld),
			nullptr, 0.0f,
			&D3DXVECTOR2(1, 1), 
			&D3DXVECTOR2(0, 0),
			0.0f,
			&(g_vTextures.at(i)->vPos)
			);

		g_pSprite->SetTransform(&(g_vTextures.at(i)->matWorld));

		g_pSprite->Draw(
			(g_vTextures.at(i))->pTexture,
			nullptr,
			&D3DXVECTOR3(0, 0, 0), &D3DXVECTOR3(0,0,0),
			D3DCOLOR_XRGB(255,255,255));

		g_pSprite->SetTransform(&g_matIdentity);
	}
	//------------------
	g_pSprite->End();

	g_pDevice->EndScene();
	g_pDevice->Present(nullptr, nullptr, 0, nullptr);
}

VOID onDestroy()
{
	Safe_Release(g_pSprite);
	Safe_Release(g_pDevice);
	Safe_Release(g_pD3D);
}

INT WINAPI WinMain( __in HINSTANCE hInstance, 
				   __in_opt HINSTANCE hPrevInstance,
				   __in_opt LPSTR lpCmdLine, 
				   __in int nShowCmd )
{
	WNDCLASS wc;
	ZeroMemory(&wc,sizeof(wc));
	wc.cbClsExtra = NULL;
	wc.cbWndExtra = NULL;
	wc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
	wc.hCursor = LoadCursor(0,IDC_ARROW);
	wc.hIcon = LoadIcon(0,IDI_APPLICATION);
	wc.hInstance = hInstance;
	wc.lpfnWndProc = WndProc;
	wc.lpszClassName = TEXT("Alibaba");
	wc.lpszMenuName = NULL;
	wc.style = CS_HREDRAW | CS_VREDRAW;

	RegisterClass(&wc);

	g_hWnd = CreateWindow(wc.lpszClassName,
		TEXT("D3D_FirstApp"),WS_OVERLAPPEDWINDOW,
		50, 20, g_iWidth + 16, g_iHeight + 39, NULL, 
		NULL, hInstance, NULL);

	if(g_hWnd)
	{
		g_hInstance = hInstance;
		onInit();
		ShowWindow(g_hWnd,SW_SHOWNORMAL);
		UpdateWindow(g_hWnd);
	}

	MSG msg;
	ZeroMemory(&msg,sizeof(msg));
	while ( msg.message!=WM_QUIT)
	{
		if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		else
		{
			static DWORD dwTime = timeGetTime();
			DWORD dwCurrentTime = timeGetTime();
			DWORD dwElapsedTime = dwCurrentTime - dwTime;
			float fElapsedTime = dwElapsedTime * 0.001f;
			onLogic(fElapsedTime);
			onRender(fElapsedTime);
			if (dwElapsedTime < 1000 / 60)
				Sleep(1000 / 60 - dwElapsedTime);
			dwTime = dwCurrentTime;
		}
	}
	onDestroy();
	UnregisterClass(wc.lpszClassName, hInstance);
	return 0;
}

LRESULT CALLBACK WndProc(HWND hWnd ,UINT uMsg,
						 WPARAM wParam,LPARAM lParam)
{
	switch(uMsg)
	{
	case WM_KEYDOWN:
		if(wParam == VK_ESCAPE)
			DestroyWindow(hWnd);
		break;
	case WM_CLOSE:
		DestroyWindow(hWnd);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	}
	return DefWindowProc(hWnd,uMsg,wParam,lParam);
}


          这里,关于第一个知识点,我要说明一下,我们都知道,生成窗口的时候,窗口都是带边框的,而我们在CreateWindow函数中定义的窗口的小是带边框的大小,所以我们要使用GetClientRect这个函数GetClientRect这个函数,我们可以把它写到onRander函数里,然后打断点,看返回值,假如你写的是800*600,但是函数返回来的是750*550,那我们,写代码的时候,就将定义窗口大小那,换成800+50和600+50即可,这样的话,我们得到的客户区大小就是800*600 ,而不是加上那个边框后的大小,之后删掉这个函数就行了,这就是它的用法

         这个代码中,我们将图片所用到的信息放到一个结构体中,到时候,创建结构体对象的时候,所有信息都包括了,使代码更简洁

猜你喜欢

转载自blog.csdn.net/shangdi712/article/details/48014777