当我尝试在 VS 2010 中编译时,出现以下两个链接错误。我确保我的包含和库设置在项目属性 > VC ++ 目录中是正确的,并且还检查以确保项目 > 链接器 > 输入具有 d3d9 .lib & d3dx9.lib 在其中。我还尝试在 D3DGraphics.h 中为上述两个库添加#pragma 注释,但无济于事:(
编译错误....
1>D3DGraphics.obj:错误 LNK2019:未解析的外部符号 _Direct3DCreate9@4 在函数“public:long thiscall D3DGraphics::SetupD3D(struct HWND *)”中引用 (?SetupD3D@D3DGraphics@@QAEJPAUHWND__@@@Z)
1>main.obj : 错误 LNK2019: 在函数“void __cdecl SetupFirework1(void) " (?SetupFirework1@@YAXXZ)
... : 致命错误 LNK1120: 2 unresolved externals
完整的程序结构如下...
D3DGraphics.h
#include <d3d9.h> // necessary Direct3D libraries
// Global pointer to the Direct 3D device
extern IDirect3DDevice9* g_pd3dDevice;
// Used to create the Direct3D object
extern IDirect3D9* g_pD3D;
class D3DGraphics
{
public:
// Global pointer to the Direct3D object
IDirect3D9* g_pD3D;
// Global pointer to the Direct 3D device
IDirect3DDevice9* g_pd3dDevice;
//The class constructor - executes whenever an instance is created.
//D3DGraphics() { /* does nothing */ }
// Method to setup D3D parameters
HRESULT SetupD3D ( HWND hWnd );
// Destructor.
// A method that executes when an instance is destroyed.
~D3DGraphics();
void Render();
void Cleanup(); // close Direct3D and release resources
};
D3DGraphics.cpp
#include "D3DGraphics.h"
// Global pointer to the Direct 3D device
IDirect3DDevice9* g_pd3dDevice;
// Used to create the Direct3D object
IDirect3D9* g_pD3D;
//// Constructor code
//D3DGraphics :: D3DGraphics()
//{
//
//}
// TYPE Classname :: MethodName
HRESULT D3DGraphics :: SetupD3D ( HWND hWnd)
{
// Create a D3D object called g_pD3D, return a fail message if this can't be done.
if (NULL == (g_pD3D = Direct3DCreate9(D3D_SDK_VERSION))) return E_FAIL;
/* *** Setup a data structure of paramteres to create the Direct3D device *** */
// data structure is called d3dpp
D3DPRESENT_PARAMETERS d3dpp;
// used to clear all data from the structure to ensure no spurious values will be used
ZeroMemory( &d3dpp,sizeof( d3dpp ) );
// application will be windowed
d3dpp.Windowed = TRUE;
// back to front buffer behavior - DISCARD = random data used for error checking
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
// back buffer format - UNKNOWN = use current display resolution to retain consistency
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
// D3D device to create and manage depth and stencil buffer automatically
d3dpp.EnableAutoDepthStencil = TRUE;
// format of the surfaces which hold the depth & stencil buffers - D16 = 16Bit colours
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
////////////* ***END data structure creation*** *////////////
/* *** Create the Direct3D Device using the defined parameters from the data strucutre d3dpp *** */
// Create the Direct3D Device and return a pointer to it, or return E_FAIL if it can't be created
if (FAILED(g_pD3D -> CreateDevice( D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&g_pd3dDevice)))
{
return E_FAIL;
}
// Enable the Z buffer
g_pd3dDevice -> SetRenderState(D3DRS_ZENABLE, TRUE);
return S_OK;
}
// Destructor code
D3DGraphics :: ~D3DGraphics()
{
//???
}
void D3DGraphics :: Cleanup()
{
//release the D3DDevice creation resources
if (g_pD3D != NULL) g_pD3D -> Release();
//release the rendering device creation resources
if (g_pd3dDevice !=NULL) g_pd3dDevice -> Release();
// Render the frame to the back buffer.
}
/* *** The Render cycle for drawing graphics on the screen *** */
void D3DGraphics :: Render()
{
// black background colour
DWORD BackgroundColour = 0x0000000;
// Clear the contents of the backbuffer & Zbuffer and set its colour.
g_pd3dDevice -> Clear(0, // 0 rectangles to be cleared
NULL, // no array of rectangle coordinates
D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, // which buffers should be cleared
BackgroundColour, // the background colour to use, defined as black 0x0000000
1.0f, // Z buffer value
0); // stencil buffer value
// Begin rendering the scene.
if (SUCCEEDED(g_pd3dDevice -> BeginScene()))
{
/// ...GRAPHICS ARE DRAWN HERE...///
// end the rendering
g_pd3dDevice -> EndScene();
}
// Present the backbuffer to the display.
g_pd3dDevice -> Present(NULL, NULL, NULL, NULL);
}
////////////* *** END The Render cycle *** *////////////
烟花.h
#include "D3DGraphics.h"
#include <d3dx9math.h> // required in this file for D3DXVECTOR3
// class for a single firework spark
class SPARKCLASS
{
public:
SPARKCLASS();
D3DXVECTOR3 Position;
float XVelocity, YVelocity, ZVelocity;
float Time;
int LifeTime;
};
// max number of sparks that can exist in the system
const int MaxNumberOfSparks = 500;
// class for the firework particle system
class FIREWORKCLASS
{
public:
FIREWORKCLASS (LPDIRECT3DDEVICE9);
void Update();
void Render();
float LaunchAngle;
float LaunchVelocity;
float ParticleSize;
int Lifetime;
int StartInterval, StartCounter, NumberToStart;
float TimeIncrement;
D3DCOLOR SparkColour;
D3DXVECTOR3 Origin;
private:
//array of sparks
SPARKCLASS Sparks[MaxNumberOfSparks];
//starts a new particle
void StartParticle(int);
//counter for the number of sparks that are alive
int SparksAlive;
//vertex buffer for the points
LPDIRECT3DVERTEXBUFFER9 pPointBuffer;
//the Direct3D Deice onto which sparks will be rendered
LPDIRECT3DDEVICE9 pRenderTarget;
};
struct POINTVERTEX
{
D3DXVECTOR3 Position;
D3DCOLOR Colour;
};
// the structure of a vertex in our vertex buffer
#define D3DFVF_POINTVERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE)
烟花.cpp
#include "Fireworks.h"
void FIREWORKCLASS :: StartParticle(int P)
{
// set this spark's lifetime to the maximum
Sparks[P].LifeTime = Lifetime;
Sparks[P].Time = 0.0f;
Sparks[P].Position.x = 0;
Sparks[P].Position.y = 0;
Sparks[P].Position.z = 0;
// select a random angle around a circle
float DirectionAngle = (float)rand()/(180/D3DX_PI);
//calculate the vertical component of velocity
Sparks[P].YVelocity = LaunchVelocity
* (float)sin(LaunchAngle);
//calculate the horizontal components of velocity - X & Z
Sparks[P].XVelocity = LaunchVelocity
* (float)sin(LaunchAngle)
* (float)cos(DirectionAngle);
Sparks[P].ZVelocity = LaunchVelocity
* (float)sin(LaunchAngle)
* (float)cos(DirectionAngle);
//since another spark now exists, increment the spark counter
SparksAlive++;
}
void FIREWORKCLASS :: Render()
{
//enable point sprites and set the size of the point
pRenderTarget -> SetRenderState(D3DRS_POINTSPRITEENABLE, true);
pRenderTarget -> SetRenderState(D3DRS_POINTSCALEENABLE, true);
pRenderTarget -> SetRenderTarget(D3DRS_LIGHTING, false);
//scale the points according to distance
pRenderTarget -> SetRenderState(D3DRS_POINTSIZE,
FtoDW(ParticleSize));
pRenderTarget -> SetRenderState(D3DRS_POINTSIZE_MIN, FtoDW(0.0f));
pRenderTarget -> SetRenderState(D3DRS_POINTSCALE_A, FtoDW(0.0f));
pRenderTarget -> SetRenderState(D3DRS_POINTSCALE_B, FtoDW(0.0f));
pRenderTarget -> SetRenderState(D3DRS_POINTSCALE_C, FtoDW(0.0f));
//render the contents of the vertex buffer
pRenderTarget -> SetStreamSource(0, pPointBuffer, 0,
sizeof(POINTVERTEX));
pRenderTarget -> SetFVF(D3DFVF_POINTVERTEX);
pRenderTarget -> DrawPrimitive(D3DPT_POINTLIST, 0, 0); // 0, ??
//reset the render states
pRenderTarget -> SetRenderState(D3DRS_POINTSPRITEENABLE, false);
pRenderTarget -> SetRenderState(D3DRS_POINTSCALEENABLE, false);
pRenderTarget -> SetRenderState(D3DRS_LIGHTING, true);
}
* Main.cpp *
#define D3D_DEBUG_INFO // Enable debugging information
#include "Windows.h"
#include "Fireworks.h"
//global pointer to Firework1 object
FIREWORKCLASS *g_Firework1 = NULL;
void SetupFirework1()
{
g_Firework1 = new FIREWORKCLASS(g_pd3dDevice);
g_Firework1 -> Origin.x = 0.0f;
g_Firework1 -> Origin.x = 0.0f;
g_Firework1 -> Origin.x = 0.0f;
g_Firework1 -> StartInterval = 10;
g_Firework1 -> StartCounter = 10;
g_Firework1 -> LaunchAngle = D3DXToRadian(80);
g_Firework1 -> LaunchVelocity = 40.0f;
g_Firework1 -> TimeIncrement = 0.04f;
g_Firework1 -> Lifetime = 200;
g_Firework1 -> NumberToStart = 8;
g_Firework1 -> ParticleSize = 2.0f;
g_Firework1 -> SparkColour = 0x00FFE000; // yellow
}
// The window's message handling function.
LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
{
// The user has clicked on the 'close' button on the window's title bar.
// Send a 'WM_QUIT' message to the application to close it down.
PostQuitMessage(0);
return 0;
}
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
// WinMain() - The application's entry point.
// This sort of procedure is mostly standard, and could be used in most
// DirectX applications.
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int)
{
/* ***Create the application window*** */
// Register the window class
WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
"Blank", NULL};
RegisterClassEx(&wc);
// Create the application's window
HWND hWnd = CreateWindow( "Blank", "---Fireworks---",
WS_OVERLAPPEDWINDOW, 100, 100, 800, 800, // ?, ?, size(x), size(y)
GetDesktopWindow(), NULL, wc.hInstance, NULL);
/* ***END application window creation*** */
// Create an instance of the D3DGraphics class called D3D
D3DGraphics D3D;
// Initialize Direct3D
if (SUCCEEDED(D3D.SetupD3D(hWnd)))
{
// Show the window
ShowWindow(hWnd, SW_SHOWDEFAULT);
UpdateWindow(hWnd);
// Enter the message loop
MSG msg;
ZeroMemory(&msg, sizeof(msg));
// Respond to messages until a 'WM_QUIT' message is received.
while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
// g_Firework1 -> Update(); // update Firework1 particles
D3D.Render(); // render the scene
}
// Execute the class destructor to clear any resources that
// D3DGraphics class has created/used.
D3D.Cleanup();
}
UnregisterClass("Blank", wc.hInstance);
return 0;
}