Hi, I'm on the fourth tutorial at Andy Pike's site and it's finally broken that god awful mess up into classes and .h files. Only problem is that now I can't compile. I had a problem with libci.lib before but now I believe it is a different problem. My only error is as follows:
fatal error LINK: cannot open file 'libci.lib'
I know it's a lot to look at but if anyone is bored and decides to take a quick 10 minutes to check this out I'd really appreciate it. Thanks :)
[main.cpp]
#include "CGame.h"
CGame* g_pGame = NULL;
void CleanUp()
{
SafeDelete(g_pGame);
}
//The windows message handler
LRESULT WINAPI WinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
break;
case WM_KEYUP:
switch (wParam)
{
case VK_ESCAPE:
//User has pressed the escape key, so quit
DestroyWindow(hWnd);
return 0;
break;
}
break;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
//Application entry point
INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, INT)
{
//Register the window class
WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_CLASSDC, WinProc, 0L, 0L,
GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
"DX Project 4", NULL};
//Set the mouse pointer to an arrow
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
RegisterClassEx(&wc);
//Create the application's window
HWND hWnd = CreateWindow("DX Project 4", "www.andypike.com: Tutorial 4",
WS_OVERLAPPEDWINDOW, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
NULL, NULL, wc.hInstance, NULL);
g_pGame = new CGame();
g_pGame->EnableLogging();
//Initialize Direct3D
if(g_pGame->Initialize(hWnd, 800, 600))
{
//Show our window
ShowWindow(hWnd, SW_SHOWDEFAULT);
UpdateWindow(hWnd);
//Start game running: Enter the game loop
g_pGame->GameLoop();
}
CleanUp();
UnregisterClass("DX Project 4", wc.hInstance);
return 0;
}
[CGame.h]
#ifndef _CGAME_H
#define _CGAME_H
#include <d3dx8.h>
#include <stdio.h>
#include "Helper.h"
#include "cCuboid.h"
class CGame
{
public:
CGame();
LPDIRECT3DDEVICE8 GetDevice();
void EnableLogging();
void GameLoop();
bool Initialize(HWND hwnd, UINT nwidth, UINT nheight);
virtual ~CGame();
private:
LPDIRECT3D8 m_pD3D;
LPDIRECT3DDEVICE8 m_pD3DDevice;
D3DFORMAT CheckDisplayMode(UINT nwidth, UINT nheight, UINT ndepth);
HRESULT InitializeD3D(HWND hwnd, UINT nwidth, UINT nheight);
bool m_fEnableLogging;
bool InitializeGame();
void SetupCamera();
void SetupPerspective();
void SetupRotation();
void Render();
void WriteToLog(char *lpszText, ...);
DWORD m_dwFrames;
DWORD m_dwStartTime;
DWORD m_dwEndTime;
CCuboid* m_pCube1;
CCuboid* m_pCube2;
CCuboid* m_pCube3;
CCuboid* m_pCube4;
CCuboid* m_pCube5;
CCuboid* m_pCube6;
};
#endif
[CGame.cpp]
// Game.cpp: implementation of the CGame class.
//
//////////////////////////////////////////////////////////////////////
#include "CGame.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CGame::CGame()
{
m_fEnableLogging = false;
m_pD3D = NULL;
m_pD3DDevice = NULL;
m_dwFrames = 0;
m_dwStartTime = 0;
m_dwEndTime = 0;
m_pCube1 = NULL;
m_pCube2 = NULL;
m_pCube3 = NULL;
m_pCube4 = NULL;
m_pCube5 = NULL;
m_pCube6 = NULL;
}
CGame::~CGame()
{
//Game finished, so record time
m_dwEndTime = timeGetTime();
DWORD dwDuration = (m_dwEndTime - m_dwStartTime) / 1000;
//Log stats
WriteToLog("Statistics:");
WriteToLog("\tStart Time (ms): %d", m_dwStartTime);
WriteToLog("\tEnd Time (ms): %d", m_dwEndTime);
WriteToLog("\tDuration (s): %d", dwDuration);
WriteToLog("\tTotal Frame Count: %d", m_dwFrames);
WriteToLog("\tAverage FPS: %d", (m_dwFrames / dwDuration));
//Clean up objects/interfaces
SafeDelete(m_pCube1);
SafeDelete(m_pCube2);
SafeDelete(m_pCube3);
SafeDelete(m_pCube4);
SafeDelete(m_pCube5);
SafeDelete(m_pCube6);
SafeRelease(m_pD3DDevice);
SafeRelease(m_pD3D);
}
bool CGame::Initialize(HWND hWnd, UINT nWidth, UINT nHeight)
{
if(SUCCEEDED(InitializeD3D(hWnd, nWidth, nHeight)))
{
return InitializeGame();
}
else
{
return false;
}
return true;
}
bool CGame::InitializeGame()
{
//Setup games objects here
m_pCube1 = new CCuboid(m_pD3DDevice);
m_pCube1->SetPosition(0.0, 0.0, 0.0);
m_pCube2 = new CCuboid(m_pD3DDevice);
m_pCube2->SetPosition(15.0, 0.0, 0.0);
m_pCube3 = new CCuboid(m_pD3DDevice);
m_pCube3->SetPosition(-15.0, 0.0, 0.0);
m_pCube4 = new CCuboid(m_pD3DDevice);
m_pCube4->SetSize(40.0, 10.0, 10.0);
m_pCube4->SetPosition(0.0, 0.0, 15.0);
m_pCube5 = new CCuboid(m_pD3DDevice);
m_pCube5->SetSize(17.5, 10.0, 10.0);
m_pCube5->SetPosition(-12.5, 0.0, -15.0);
m_pCube6 = new CCuboid(m_pD3DDevice);
m_pCube6->SetSize(17.5, 10.0, 10.0);
m_pCube6->SetPosition(12.5, 0.0, -15.0);
return true;
}
D3DFORMAT CGame::CheckDisplayMode(UINT nWidth, UINT nHeight, UINT nDepth)
{
UINT x;
D3DDISPLAYMODE d3ddm;
for(x = 0; x < m_pD3D->GetAdapterModeCount(0); x++)
{
m_pD3D->EnumAdapterModes(0, x, &d3ddm);
if(d3ddm.Width == nWidth)
{
if(d3ddm.Height == nHeight)
{
if((d3ddm.Format == D3DFMT_R5G6B5) || (d3ddm.Format == D3DFMT_X1R5G5B5) || (d3ddm.Format == D3DFMT_X4R4G4B4))
{
if(nDepth == 16)
{
return d3ddm.Format;
}
}
else if((d3ddm.Format == D3DFMT_R8G8B8) || (d3ddm.Format == D3DFMT_X8R8G8B8))
{
if(nDepth == 32)
{
return d3ddm.Format;
}
}
}
}
}
return D3DFMT_UNKNOWN;
}
HRESULT CGame::InitializeD3D(HWND hWnd, UINT nWidth, UINT nHeight)
{
WriteToLog("InitializeD3D Started...");
//First of all, create the main D3D object. If it is created successfully we
//should get a pointer to an IDirect3D8 interface.
m_pD3D = Direct3DCreate8(D3D_SDK_VERSION);
if(m_pD3D == NULL)
{
WriteToLog("\tUnable to create DirectX8 interface.");
return E_FAIL;
}
//Get the current display mode
D3DDISPLAYMODE d3ddm;
d3ddm.Format = CheckDisplayMode(nWidth, nHeight, 32);
if(d3ddm.Format != D3DFMT_UNKNOWN)
{
//Width x Height x 32bit has been selected
d3ddm.Width = nWidth;
d3ddm.Height = nHeight;
WriteToLog("\t%d x %d x 32bit back buffer format selected. Format = %d.", nWidth, nHeight, d3ddm.Format);
}
else
{
d3ddm.Format = CheckDisplayMode(nWidth, nHeight, 16);
if(d3ddm.Format != D3DFMT_UNKNOWN)
{
//Width x Height x 16bit has been selected
d3ddm.Width = nWidth;
d3ddm.Height = nHeight;
WriteToLog("\t%d x %d x 16bit back buffer format selected. Format = %d.", nWidth, nHeight, d3ddm.Format);
}
else
{
WriteToLog("\tUnable to select back buffer format for %d x %d.", nWidth, nHeight);
return E_FAIL;
}
}
//Create a structure to hold the settings for our device
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = FALSE;
d3dpp.BackBufferCount = 1;
d3dpp.BackBufferFormat = d3ddm.Format;
d3dpp.BackBufferWidth = d3ddm.Width;
d3dpp.BackBufferHeight = d3ddm.Height;
d3dpp.hDeviceWindow = hWnd;
d3dpp.SwapEffect = D3DSWAPEFFECT_COPY_VSYNC;
d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE;
//Select the best depth buffer, select 32, 24 or 16 bit
if(m_pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3ddm.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D32) == D3D_OK)
{
d3dpp.AutoDepthStencilFormat = D3DFMT_D32;
d3dpp.EnableAutoDepthStencil = TRUE;
WriteToLog("\t32bit depth buffer selected");
}
else if(m_pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3ddm.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24X8) == D3D_OK)
{
d3dpp.AutoDepthStencilFormat = D3DFMT_D24X8;
d3dpp.EnableAutoDepthStencil = TRUE;
WriteToLog("\t24bit depth buffer selected");
}
else if(m_pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3ddm.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D16) == D3D_OK)
{
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
d3dpp.EnableAutoDepthStencil = TRUE;
WriteToLog("\t16bit depth buffer selected");
}
else
{
d3dpp.EnableAutoDepthStencil = FALSE;
WriteToLog("\tUnable to select depth buffer.");
}
//Create a Direct3D device.
if(FAILED(m_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &m_pD3DDevice)))
{
WriteToLog("\tUnable to create device.");
return E_FAIL;
}
//Turn on back face culling. This is becuase we want to hide the back of our polygons
m_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
//Turn off lighting becuase we are specifying that our vertices have colour
m_pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
//Turn on Depth Buffering
m_pD3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
WriteToLog("InitialiseD3D Finished OK");
return S_OK;
}
LPDIRECT3DDEVICE8 CGame::GetDevice()
{
return m_pD3DDevice;
}
void CGame::GameLoop()
{
//Enter the game loop
MSG msg;
BOOL fMessage;
PeekMessage(&msg, NULL, 0U, 0U, PM_NOREMOVE);
//Game started, so record time
m_dwStartTime = timeGetTime();
while(msg.message != WM_QUIT)
{
fMessage = PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE);
if(fMessage)
{
//Process message
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
//No message to process, so render the current scene
Render();
}
}
}
void CGame::Render()
{
if(m_pD3DDevice == NULL)
{
return;
}
//Clear the back buffer and depth buffer
m_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
//Begin the scene
m_pD3DDevice->BeginScene();
//Setup the rotation, camera, and perspective matrices
SetupRotation();
SetupCamera();
SetupPerspective();
//Rendering our objects
m_pCube1->Render();
m_pCube2->Render();
m_pCube3->Render();
m_pCube4->Render();
m_pCube5->Render();
m_pCube6->Render();
//End the scene
m_pD3DDevice->EndScene();
//Filp the back and front buffers so that whatever has been rendered on the back buffer
//will now be visible on screen (front buffer).
m_pD3DDevice->Present(NULL, NULL, NULL, NULL);
//Count Frames
m_dwFrames++;
}
void CGame::SetupRotation()
{
//Here we will rotate our world.
D3DXMATRIX matWorld, matWorldX, matWorldY, matWorldZ;
//Create the transformation matrices
D3DXMatrixRotationX(&matWorldX, timeGetTime()/400.0f);
D3DXMatrixRotationY(&matWorldY, timeGetTime()/400.0f);
D3DXMatrixRotationZ(&matWorldZ, timeGetTime()/400.0f);
//Combine the transformations by multiplying them together
D3DXMatrixMultiply(&matWorld, &matWorldX, &matWorldY);
D3DXMatrixMultiply(&matWorld, &matWorld, &matWorldZ);
//Apply the tansformation
m_pD3DDevice->SetTransform(D3DTS_WORLD, &matWorld);
}
void CGame::SetupCamera()
{
//Here we will setup the camera.
//The camera has three settings: "Camera Position", "Look at Position" and "Up Direction"
//We have set the following:
//Camera Position: (0, 0, -100)
//Look at Position: (0, 0, 0)
//Up direction: Y-Axis.
D3DXMATRIX matView;
D3DXMatrixLookAtLH(&matView, &D3DXVECTOR3(0.0f, 0.0f,-100.0f), //Camera Position
&D3DXVECTOR3(0.0f, 0.0f, 0.0f), //Look At Position
&D3DXVECTOR3(0.0f, 1.0f, 0.0f)); //Up Direction
m_pD3DDevice->SetTransform(D3DTS_VIEW, &matView);
}
void CGame::SetupPerspective()
{
//Here we specify the field of view, aspect ration and near and far clipping planes.
D3DXMATRIX matProj;
D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI/4, 1.0f, 1.0f, 500.0f);
m_pD3DDevice->SetTransform(D3DTS_PROJECTION, &matProj);
}
void CGame::WriteToLog(char *lpszText, ...)
{
if(m_fEnableLogging)
{
va_list argList;
FILE *pFile;
//Initialize variable argument list
va_start(argList, lpszText);
//Open the log file for appending
pFile = fopen("log.txt", "a+");
//Write the text and a newline
vfprintf(pFile, lpszText, argList);
putc('\n', pFile);
//Close the file
fclose(pFile);
va_end(argList);
}
}
void CGame::EnableLogging()
{
m_fEnableLogging = true;
FILE* pFile;
//Clear the file contents
pFile = fopen("log.txt", "wb");
//Close it up and return success
fclose(pFile);
}
[CCuboid.h]
#ifndef _CCUBOID_H
#define _CCUBOID_H
#include <d3dx8.h>
#include "helper.h"
//Define a FVF for our cubiods
#define CUBOID_D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)
class CCuboid
{
public:
CCuboid(LPDIRECT3DDEVICE8 pD3DDevice);
bool SetPosition(float x,float y,float z);
bool SetSize(float rwidth,float rheight,float rdepth);
bool Render();
virtual ~CCuboid();
private:
HRESULT CreateVertexBuffer();
LPDIRECT3DVERTEXBUFFER8 m_pVertexBuffer;
LPDIRECT3DDEVICE8 m_pD3DDevice;
bool UpdateVertices();
float m_rWidth;
float m_rHeight;
float m_rDepth;
float m_rX;
float m_rY;
float m_rZ;
//Define a custom vertex for our cuboids
struct CUBOID_CUSTOMVERTEX
{
FLOAT x, y, z;
DWORD color;
};
};
#endif
[CCuboid.cpp]
// Cuboid.cpp: implementation of the CCuboid class.
//
//////////////////////////////////////////////////////////////////////
#include "CCuboid.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CCuboid::CCuboid(LPDIRECT3DDEVICE8 pD3DDevice)
{
m_pD3DDevice = pD3DDevice;
m_pVertexBuffer = NULL;
//Set a default size and position
m_rWidth = 10.0;
m_rHeight = 10.0;
m_rDepth = 10.0;
m_rX = 0.0;
m_rY = 0.0;
m_rZ = 0.0;
//Initialize Vertex Buffer
if(SUCCEEDED(CreateVertexBuffer()))
{
UpdateVertices();
}
}
CCuboid::~CCuboid()
{
SafeRelease(m_pVertexBuffer);
}
bool CCuboid::Render()
{
m_pD3DDevice->SetStreamSource(0, m_pVertexBuffer, sizeof(CUBOID_CUSTOMVERTEX));
m_pD3DDevice->SetVertexShader(CUBOID_D3DFVF_CUSTOMVERTEX);
m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); //Top
m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 4, 8); //Sides
m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 14, 2); //Bottom
return true;
}
HRESULT CCuboid::CreateVertexBuffer()
{
//Create the vertex buffer from our device.
if(FAILED(m_pD3DDevice->CreateVertexBuffer(18 * sizeof(CUBOID_CUSTOMVERTEX),
0, CUBOID_D3DFVF_CUSTOMVERTEX,
D3DPOOL_DEFAULT, &m_pVertexBuffer)))
{
return E_FAIL;
}
return S_OK;
}
bool CCuboid::UpdateVertices()
{
VOID* pVertices;
//Store each point of the cube together with it's colour
//Make sure that the points of a polygon are specified in a clockwise direction,
//this is because anti-clockwise faces will be culled
//We will use a three triangle strips to render these polygons (Top, Sides, Bottom).
CUBOID_CUSTOMVERTEX cvVertices[] =
{
//Top Face
{m_rX - (m_rWidth / 2), m_rY + (m_rHeight / 2), m_rZ - (m_rDepth / 2), D3DCOLOR_XRGB(0, 0, 255),}, //Vertex 0 - Blue
{m_rX - (m_rWidth / 2), m_rY + (m_rHeight / 2), m_rZ + (m_rDepth / 2), D3DCOLOR_XRGB(255, 0, 0),}, //Vertex 1 - Red
{m_rX + (m_rWidth / 2), m_rY + (m_rHeight / 2), m_rZ - (m_rDepth / 2), D3DCOLOR_XRGB(255, 0, 0),}, //Vertex 2 - Red
{m_rX + (m_rWidth / 2), m_rY + (m_rHeight / 2), m_rZ + (m_rDepth / 2), D3DCOLOR_XRGB(0, 255, 0),}, //Vertex 3 - Green
//Face 1
{m_rX - (m_rWidth / 2), m_rY - (m_rHeight / 2), m_rZ - (m_rDepth / 2), D3DCOLOR_XRGB(255, 0, 0),}, //Vertex 4 - Red
{m_rX - (m_rWidth / 2), m_rY + (m_rHeight / 2), m_rZ - (m_rDepth / 2), D3DCOLOR_XRGB(0, 0, 255),}, //Vertex 5 - Blue
{m_rX + (m_rWidth / 2), m_rY - (m_rHeight / 2), m_rZ - (m_rDepth / 2), D3DCOLOR_XRGB(0, 255, 0),}, //Vertex 6 - Green
{m_rX + (m_rWidth / 2), m_rY + (m_rHeight / 2), m_rZ - (m_rDepth / 2), D3DCOLOR_XRGB(255, 0, 0),}, //Vertex 7 - Red
//Face 2
{m_rX + (m_rWidth / 2), m_rY - (m_rHeight / 2), m_rZ + (m_rDepth / 2), D3DCOLOR_XRGB(0, 0, 255),}, //Vertex 8 - Blue
{m_rX + (m_rWidth / 2), m_rY + (m_rHeight / 2), m_rZ + (m_rDepth / 2), D3DCOLOR_XRGB(0, 255, 0),}, //Vertex 9 - Green
//Face 3
{m_rX - (m_rWidth / 2), m_rY - (m_rHeight / 2), m_rZ + (m_rDepth / 2), D3DCOLOR_XRGB(0, 255, 0),}, //Vertex 10 - Green
{m_rX - (m_rWidth / 2), m_rY + (m_rHeight / 2), m_rZ + (m_rDepth / 2), D3DCOLOR_XRGB(255, 0, 0),}, //Vertex 11 - Red
//Face 4
{m_rX - (m_rWidth / 2), m_rY - (m_rHeight / 2), m_rZ - (m_rDepth / 2), D3DCOLOR_XRGB(255, 0, 0),}, //Vertex 12 - Red
{m_rX - (m_rWidth / 2), m_rY + (m_rHeight / 2), m_rZ - (m_rDepth / 2), D3DCOLOR_XRGB(0, 0, 255),}, //Vertex 13 - Blue
//Bottom Face
{m_rX + (m_rWidth / 2), m_rY - (m_rHeight / 2), m_rZ - (m_rDepth / 2), D3DCOLOR_XRGB(0, 255, 0),}, //Vertex 14 - Green
{m_rX + (m_rWidth / 2), m_rY - (m_rHeight / 2), m_rZ + (m_rDepth / 2), D3DCOLOR_XRGB(0, 0, 255),}, //Vertex 15 - Blue
{m_rX - (m_rWidth / 2), m_rY - (m_rHeight / 2), m_rZ - (m_rDepth / 2), D3DCOLOR_XRGB(255, 0, 0),}, //Vertex 16 - Red
{m_rX - (m_rWidth / 2), m_rY - (m_rHeight / 2), m_rZ + (m_rDepth / 2), D3DCOLOR_XRGB(0, 255, 0),}, //Vertex 17 - Green
};
//Get a pointer to the vertex buffer vertices and lock the vertex buffer
if(FAILED(m_pVertexBuffer->Lock(0, sizeof(cvVertices), (BYTE**)&pVertices, 0)))
{
return false;
}
//Copy our stored vertices values into the vertex buffer
memcpy(pVertices, cvVertices, sizeof(cvVertices));
//Unlock the vertex buffer
m_pVertexBuffer->Unlock();
return true;
}
bool CCuboid::SetSize(float rWidth, float rHeight, float rDepth)
{
m_rWidth = rWidth;
m_rHeight = rHeight;
m_rDepth = rDepth;
UpdateVertices();
return true;
}
bool CCuboid::SetPosition(float x, float y, float z)
{
m_rX = x;
m_rY = y;
m_rZ = z;
UpdateVertices();
return true;
}
[helper.h]
#ifndef _HELPER_H
#define _HELPER_H
#define SafeRelease(pInterface) if(pInterface != NULL) {pInterface->Release(); pInterface = NULL;};
#define SafeDelete(pObject) if(pObject != NULL) {delete pObject; pObject = NULL;};
#endif
If you take the time to review this THANK YOU SO MUCH.
//-----------------------------------------One short sleepe past, wee wake eternally, And Death shall be no more, Death thou shalt die.