版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/shangdi712/article/details/47963509
首先,工程文件链接http://download.csdn.net/detail/shangdi712/9051999 使用工程文件时候,切记配置directx环境
其实,这个博客只介绍一个函数,就是D3DXMatrixTransformation2D,矩阵变换函数,在使用这个函数之前,我们需要先定义一个矩阵变量
D3DXMATRIX g_matWorld;
这是D3D里面定义的矩阵,用于实现图片的平移,旋转,缩放变换,而图像的锚点是什么呢,我们暂且把它认为成逻辑上的中心点,默认是在图片左上角,旋转的时候以它为中心,显示的时候,将这个点认为是图片坐标系的原点,也就是说,如果我们不设置位置的话,这个图片永远都把锚点放到最左上角,超出 的部分显示,好了,现在让我们看一下这个函数
D3DXMatrixTransformation2D(
&g_matWorld, //返回的矩阵
nullptr, //缩放的中心
0.0f, //影响缩放的因素
&D3DXVECTOR2(1.0f, 1.0f), //在X、Y方向的缩放量
&D3DXVECTOR2(0.0f, 0.0f), //旋转中心
fAngle, //旋转弧度
&g_playerPos//平移量
);
要使这个函数生效,我们需要调用这个函数
g_pSprite->SetTransform(&g_matWorld);
最后,我们一定要记得恢复渲染状态
D3DXMatrixIdentity(&g_matWorld);
但是,图片的变换,跟矩阵有什么关系呢,好的
假设我们有这样一个单位矩阵,再假设我们的图片坐标为写X 和Y,我们将x 和 y竖着写,最底下给0,然后和矩阵相乘会发生什么
对,没错,这个关系恒成立,假设最底下一行变成2,2,1 会怎么样,那相乘之后就会变成 2+x 2+y 1,大家可以亲自动笔算一下,所以,接下来告诉大家结论
我们在此处画两条线,右下角负责图片平移,左下角负责图片的等比例缩放,左上角负责x轴方向和y轴方向缩放,左上角负责旋转
好了,现在我们照例,贴出完整代码
//Utility.h
#ifndef WINDOWS_USEFUL_TOOLS_
#define WINDOWS_USEFUL_TOOLS_
#include <Windows.h>
#include <MMSystem.h>
#pragma comment(lib,"Winmm.lib")
#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>
using namespace std;
#endif
WinMain.cpp
#include "Utility.h"
HWND g_hWnd = 0;
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;
LPDIRECT3DTEXTURE9 g_pTexture = nullptr;
D3DXIMAGE_INFO g_ImageInfo;
//矩阵:用来控制图片的平移、旋转、缩放变换
D3DXMATRIX g_matWorld; //世界坐标系下的矩阵(4x4)
LPDIRECT3DTEXTURE9 g_pCarrot = nullptr;
VOID onInitGame()
{
D3DXCreateSprite(g_pDevice, &g_pSprite);
ZeroMemory(&g_ImageInfo, sizeof(g_ImageInfo));
D3DXCreateTextureFromFileEx(
g_pDevice, TEXT("Resources\\Textures\\carrot.png"),
D3DX_FROM_FILE,D3DX_FROM_FILE,
0,0,D3DFMT_UNKNOWN,D3DPOOL_MANAGED,
D3DX_FILTER_LINEAR,D3DX_FILTER_LINEAR,
D3DCOLOR_XRGB(254,253,255),&g_ImageInfo,nullptr,&g_pTexture);
D3DXCreateTextureFromFile(g_pDevice,
TEXT("Resources\\Textures\\carrot.png"), &g_pCarrot);
INT iTileWidth = g_ImageInfo.Width / 3; //单元格的宽(Tile:单元格)
INT iTileHeight = g_ImageInfo.Height / 3; //单元格的高(Tile:单元格)
//将矩阵置为单位矩阵
D3DXMatrixIdentity(&g_matWorld);
}
VOID onInit()
{
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, 234, 123), 1.0f, 0);
g_pDevice->BeginScene();
g_pSprite->Begin(D3DXSPRITE_ALPHABLEND);
//获得一个具有变换信息的矩阵
static float fAngle = 0.0f;
fAngle += fElapsedTime*10;
D3DXMatrixTransformation2D(
&g_matWorld, //返回的矩阵
nullptr, //缩放的中心
0.0f, //影响缩放的因素
&D3DXVECTOR2(1.0f, 1.0f), //在X、Y方向的缩放量
&D3DXVECTOR2(0.0f, 0.0f), //旋转中心
fAngle, //旋转弧度
&g_playerPos//平移量
);
g_pSprite->SetTransform(&g_matWorld);
g_pSprite->Draw(
g_pTexture,
nullptr,
&D3DXVECTOR3(g_ImageInfo.Width / 2.0f, g_ImageInfo.Height / 2.0f, 0.0f), //锚点
&D3DXVECTOR3(0.0f,0.0f,0.0f),
0xFFFFFFFF
);
//----恢复渲染状态---- ****************************
D3DXMatrixIdentity(&g_matWorld);
g_pSprite->setTransform(&g_matWorld);
g_pSprite->End();
g_pDevice->EndScene();
g_pDevice->Present(nullptr, nullptr, 0, nullptr);
}
VOID onDestroy()
{
Safe_Release(g_pTexture);
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,800,600,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_MOUSEMOVE:
g_playerPos.x = LOWORD(lParam);
g_playerPos.y = HIWORD(lParam);
break;
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);
}