您的位置:首页 > 其它

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

2015-08-26 23:25 507 查看
这次,主要就是利用前面几篇博客里面的例子,来做几个应用练习,主要就是,让图片闪烁,一次读取多张图片,和使用随机数随机读取图片(当然,这里的随机数用的是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 ,而不是加上那个边框后的大小,之后删掉这个函数就行了,这就是它的用法

这个代码中,我们将图片所用到的信息放到一个结构体中,到时候,创建结构体对象的时候,所有信息都包括了,使代码更简洁
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: