Quote:Original post by Evil Steve
To me it looks like D3DManagement.h shouldn't include GameManagement.h - why does the lower level D3D related class need to know about the higher level game related class?
The D3DManagement need GameManager because my design is crap. I don't know how to separate properly the lower layer of the higher layer. Look at theses files:
D3DManagement.h
#pragma once#include <d3dx9.h>#include <iostream>#include <sstream>class GameManager;#include "GameManager.h"#include "Logger.h"using namespace std;#define D3DSAFE_RELEASE(p) if (p != NULL) { p->Release(); }class D3DManagement{private: LPDIRECT3D9 m_D3DObject; LPDIRECT3DDEVICE9 m_D3DDevice; HWND m_MainWindowHandle; int m_Width; int m_Height; bool m_Keys[256];// ------------------------------------------------------------------------------------------------ D3DManagement() {} ~D3DManagement() {}// ------------------------------------------------------------------------------------------------public:// ------------------------------------------------------------------------------------------------ static D3DManagement *GetInstance() { static D3DManagement instance; return &instance; }// ------------------------------------------------------------------------------------------------ HRESULT BuildWindow(string name, int width, int height); HRESULT InitD3D(); void MessageLoop(); void Draw(); void Cleanup(); void SetMatrices(); LPDIRECT3DDEVICE9 GetDevice(); HWND GetHandle(); bool GetKey(int key); void SetKey(int key, bool value);};LRESULT CALLBACK MsgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
D3DManagement.cpp
#include "D3DManagement.h"const int FPS = 100;const int FRAMERATE = FPS/1000;LRESULT CALLBACK MsgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){ switch (msg) { case WM_DESTROY: PostQuitMessage(0); return 0; case WM_SETCURSOR: SetCursor(NULL); //D3DManagement::GetInstance()->GetDevice()->ShowCursor(FALSE); return 0; case WM_KEYDOWN: if(wParam == VK_ESCAPE) { GameManager::GetInstance()->SetGameOver(true); PostQuitMessage(0); return 0; } D3DManagement::GetInstance()->SetKey((int)wParam, true); return 0; case WM_KEYUP: D3DManagement::GetInstance()->SetKey((int)wParam, false); return 0; } return DefWindowProc(hwnd, msg, wParam, lParam);}bool D3DManagement::GetKey(int key){ return m_Keys[key];}void D3DManagement::SetKey(int key, bool value){ m_Keys[key] = value;}HRESULT D3DManagement::BuildWindow(string name, int width, int height){ m_Width = width; m_Height = height; WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW, MsgProc, 0L, 0L, GetModuleHandle(NULL), NULL, LoadCursor(NULL, IDC_ARROW), NULL, NULL, "D3DM", NULL}; if(!RegisterClassEx(&wc)) { MSG_ERROR("Window registration failed"); return E_FAIL; } MSG_SUCCESS("Windows registration succeeded"); m_MainWindowHandle = CreateWindow("D3DM", "Direct3D Test", WS_POPUP | WS_SYSMENU | WS_VISIBLE, 100, 100, m_Width, m_Height, GetDesktopWindow(), NULL, wc.hInstance, NULL); if (m_MainWindowHandle == NULL) { MSG_ERROR("Window creation failed"); return E_FAIL; } MSG_SUCCESS("Windows creation succeeded"); ShowWindow(m_MainWindowHandle, SW_SHOW); UpdateWindow(m_MainWindowHandle); for (int i = 0; i < 256; i++) { m_Keys = false; } return S_OK;}void D3DManagement::MessageLoop(){ float last_time = timeGetTime(); MSG msg; PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE); while (msg.message != WM_QUIT) { float current_time = timeGetTime(); float delta_time = (current_time - last_time) * 0.001f; if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); GameManager::GetInstance()->ManageInput(); } if ((current_time - last_time) >= FRAMERATE) { GameManager::GetInstance()->ManageGame(); Draw(); last_time = current_time; } }}HRESULT D3DManagement::InitD3D(){ if (((m_D3DObject = Direct3DCreate9(D3D_SDK_VERSION)) == NULL)) { MSG_ERROR("Can't create Direct3D object"); return E_FAIL; } MSG_SUCCESS("Direct3D object creation succeeded"); D3DPRESENT_PARAMETERS d3dpp; ZeroMemory(&d3dpp, sizeof(d3dpp)); d3dpp.Windowed = TRUE; d3dpp.EnableAutoDepthStencil = TRUE; d3dpp.AutoDepthStencilFormat = D3DFMT_D16; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferWidth = m_Width; d3dpp.BackBufferHeight = m_Height; d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8; d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; if (FAILED(m_D3DObject->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_MainWindowHandle, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &m_D3DDevice))) { MSG_ERROR("Can't create Direct3D device"); return E_FAIL; } MSG_SUCCESS("Direct3D device creation succeeded"); m_D3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); m_D3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE); // Desactivation du Z buffer m_D3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, false); SetMatrices(); return S_OK;}void D3DManagement::Draw(){ m_D3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); m_D3DDevice->BeginScene(); GameManager::GetInstance()->Draw(); m_D3DDevice->EndScene(); m_D3DDevice->Present(NULL, NULL, NULL, NULL);}void D3DManagement::Cleanup(){ D3DSAFE_RELEASE(m_D3DObject); D3DSAFE_RELEASE(m_D3DDevice);}void D3DManagement::SetMatrices(){ D3DXMATRIX matWorld; D3DXMatrixTranslation(&matWorld, 2, 2, 0); m_D3DDevice->SetTransform(D3DTS_WORLD, &matWorld); // ------------------------------------------------------------------------------------------------ D3DXVECTOR3 vecEyePt (0.0f, 3.0f, 0.0f); D3DXVECTOR3 vecLookatPt (0.0f, 0.0f, 0.0f); D3DXVECTOR3 vecUpVec (0.0f, 1.0f, 0.0f); D3DXMATRIXA16 matView; D3DXMatrixLookAtLH(&matView, &vecEyePt, &vecLookatPt, &vecUpVec); m_D3DDevice->SetTransform(D3DTS_VIEW, &matView); // ------------------------------------------------------------------------------------------------ D3DXMATRIX matOrtho; D3DXMatrixOrthoLH(&matOrtho, D3DX_PI/4, 1.0f, 1.0f, 100.0f); m_D3DDevice->SetTransform(D3DTS_PROJECTION, &matOrtho);}LPDIRECT3DDEVICE9 D3DManagement::GetDevice(){ return m_D3DDevice;}HWND D3DManagement::GetHandle(){ return m_MainWindowHandle;}
GameManager.h
#pragma onceclass D3DManagement;class Sprite;class Tank;#include "D3DManagement.h"#include "Sprite.h"#include "Tank.h"#include "TextManager.h"class GameManager{private: Tank *m_Player; bool m_GameOver;// ------------------------------------------------------------------------------------------------ GameManager() {} ~GameManager() {}// ------------------------------------------------------------------------------------------------public:// ------------------------------------------------------------------------------------------------ static GameManager *GetInstance() { static GameManager instance; return &instance; }// ------------------------------------------------------------------------------------------------ void Init(); void Destroy(); void Draw(); void GameLoop(); void ManageGame(); void ManageInput(); void SetGameOver(bool value); bool IsGameOver();};
GameManager.cpp
#include "GameManager.h"void GameManager::Init(){ D3DManagement::GetInstance()->BuildWindow("D3DApp", 1024, 768); D3DManagement::GetInstance()->InitD3D(); //D3DManagement::GetInstance()->Init(); TextManager::GetInstance()->Init(); m_Player = new Tank("tank.bmp", 300, 200); m_GameOver = false;}void GameManager::Destroy(){ TextManager::GetInstance()->Destroy(); D3DManagement::GetInstance()->Cleanup(); delete m_Player;}void GameManager::GameLoop(){ while (m_GameOver != true) { D3DManagement::GetInstance()->MessageLoop(); }}void GameManager::Draw(){ m_Player->Draw(); TextManager::GetInstance()->DrawMessage("Tank Battle 0.1a", 10, 10, D3DCOLOR_XRGB(255,255,255));}void GameManager::ManageGame(){ m_Player->Update();}void GameManager::ManageInput(){ if (D3DManagement::GetInstance()->GetKey(VK_UP)) { m_Player->DecreasePosition(false, true, 32); } if (D3DManagement::GetInstance()->GetKey(VK_DOWN)) { m_Player->IncreasePosition(false, true, 32); } if (D3DManagement::GetInstance()->GetKey(VK_LEFT)) { m_Player->DecreasePosition(true, false, 32); } if (D3DManagement::GetInstance()->GetKey(VK_RIGHT)) { m_Player->IncreasePosition(true, false, 32); }}void GameManager::SetGameOver(bool value){ m_GameOver = value;}bool GameManager::IsGameOver(){ return m_GameOver;}