Thread: Starting on my game engine

  1. #1
    Sanity is for the weak! beene's Avatar
    Join Date
    Jul 2006
    Posts
    321

    Starting on my game engine

    Hi.
    I've made a start on my game engine. I only have 1 class so far.... CRenderDevice. I don't know if that's the only class I need for rendering the window right now, but we'll come to that later.....

    Anyways.....

    I had it all working and I was actually really happy with myself because I had made countless attempts to get this working and I did it. I decided to tidy up the code a bit and I have 3 stupid errors that I can't get rid of unless i'm msiing something really stupid.

    Here's the errors:
    Code:
    1>.\CMain.cpp(9) : error C2512: 'CRenderDevice' : no appropriate default constructor available
    1>.\CMain.cpp(16) : error C2065: 'm_Device' : undeclared identifier
    1>.\CMain.cpp(22) : error C2065: 'CDisplay' : undeclared identifier
    ... and here is the code, some is commented and some is not, I was just happy to see it working so i'll work on the comments later.

    I have highlighted the lines where the errors are in red.

    CMain.cpp
    Code:
    #include "CRenderDevice.h"
    
    int WINAPI WinMain(
             HINSTANCE ChInstance, /*Handle to the current application instance*/
    	 HINSTANCE ChPrevInstance, /*Not used in 32-bit Win32 programming and is 0*/   
    	 LPSTR cmdLine, /*Command line argument string used to run the program*/
             int cmdShow) /*Specifies how the application window should be displayed*/
    {
        CRenderDevice CDevice;
        if(!CDevice.CInitD3D( /*If CInitD3D fails*/
    	ChInstance, /*Application instance*/
    	450, /*Application width*/
    	375, /*Application height*/
    	true, /*Windowed?*/
    	D3DDEVTYPE_HAL, /*DeviceType*/
    	&m_Device)) /*Device*/
    	{
    	    MessageBox(0, "CInitD3D() - FAILED!", "Error", 0);
    	    return 0;
    	}
    
        CDevice.EnterMsgLoop(CDisplay); /*Pump the message loop*/
    
        return 0; /*Return false*/
    }
    CRenderDevice.h
    Code:
    /*CRenderDevice.h*/
    
    #include <d3dx9.h>
    
    class CRenderDevice
    {
    public:
        CRenderDevice(IDirect3DDevice9*);
        ~CRenderDevice();
    
        bool CInitD3D(
    	HINSTANCE ChInstance,
    	int CWidth, int CHeight,
    	bool CWindowed,
    	D3DDEVTYPE CDeviceType,
    	IDirect3DDevice9** Device);
    
        static LRESULT CALLBACK WndProc(
    	HWND CHwnd,
    	UINT CMsg,
    	WPARAM wParam,
    	LPARAM lParam);
    
        int EnterMsgLoop(
    	bool (*ptr_display)(float timeDelta));
    
        bool CDisplay(float CTimeDelta);
    
    protected:
        IDirect3DDevice9* m_Device;
    };
    CRenderDevice.cpp
    Code:
    #include "CRenderDevice.h"
    
    CRenderDevice::CRenderDevice(IDirect3DDevice9* Device)
    {
        m_Device = Device;
    }
    
    CRenderDevice::~CRenderDevice()
    {
        m_Device->Release(); /*Done with the device*/
    }
    
    bool CRenderDevice::CInitD3D(
    	HINSTANCE ChInstance, 
    	int CWidth, int CHeight, 
    	bool CWindowed, D3DDEVTYPE CDeviceType, 
    	IDirect3DDevice9** Device)
    {
        HWND CHwnd = 0;
        WNDCLASS wc;
    
        wc.style = CS_HREDRAW | CS_VREDRAW;
        wc.lpfnWndProc = WndProc;
        wc.cbClsExtra = 0;
        wc.cbWndExtra = 0;
        wc.hInstance = ChInstance;
        wc.hIcon = LoadIcon(0, IDI_APPLICATION);
        wc.hCursor = LoadCursor(0, IDC_ARROW);
        wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        wc.lpszMenuName = 0;
        wc.lpszClassName = "D3D Framework";
    
        if(!RegisterClass(&wc))
        {
            MessageBox(0, "RegisterClass() - FAILED!", "Error", 0);
            return 0;
        }
    
        CHwnd = CreateWindowEx(
    	0,
    	"D3D Framework",
    	"Engine",
    	WS_OVERLAPPEDWINDOW,
    	CW_USEDEFAULT,
    	CW_USEDEFAULT,
    	CWidth,
    	CHeight,
    	CHwnd,
    	0,
    	ChInstance,
    	0);
    
        if(!CHwnd)
        {
            MessageBox(0, "CreateWindowEx() - FAILED!", "Error", 0);
            return 0;
        }
    
        ShowWindow(CHwnd, SW_SHOW);
        UpdateWindow(CHwnd);
    
        HRESULT hr = 0;
    
        IDirect3D9* d3d9 = 0;
        d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
    
        if(!d3d9)
        {
            MessageBox(0, "Direct3DCreate9() - FAILED!", "Error", 0);
            return 0; /*Return false*/
        }
    
        /*Step 2, Check for Hardware vp(VertexProcessing)*/
        D3DCAPS9 caps;
        d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, CDeviceType, &caps);
    
        int vp = 0; /*Vertex processing variable*/
        if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) /*If hardware vp is supported*/
        {
            vp = D3DCREATE_HARDWARE_VERTEXPROCESSING; /*Create hardware VertexProcessing*/
        }
        else 
        {
            vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING; /*Create Software Vertwx Processing*/
        }
    
        /*Step 3, Fill out the D3DPRESENT_PARAMETERS structure*/
        D3DPRESENT_PARAMETERS d3dpp;
        /*The backbuffer width in pixels*/
        d3dpp.BackBufferWidth            = CWidth;
        /*The backbuffer height in pixels*/
        d3dpp.BackBufferHeight           = CHeight;
        /*The pixel format of the backbuffer
        eg(Alpha - 8, Red - 8, Green - 8, Blue - 8 = 32-bit pixel format)*/
        d3dpp.BackBufferFormat           = D3DFMT_A8R8G8B8;
        /*How many backbuffers we want*/
        d3dpp.BackBufferCount            = 1;
        /*The type of multisampling we want to use with the backbuffer*/
        d3dpp.MultiSampleType            = D3DMULTISAMPLE_NONE;
        /*The quality level of the multisampling*/
        d3dpp.MultiSampleQuality         = 0;
        /*Specify how the buffers in the flipping chain will be swapped*/
        d3dpp.SwapEffect                 = D3DSWAPEFFECT_DISCARD;
        /*The window handle associated with the device*/
        d3dpp.hDeviceWindow              = CHwnd;
        /*Specify true to run in windowed mode,
        false to run in fullscreen mode*/
        d3dpp.Windowed                   = CWindowed;
        /*Set to true to have Direct3D create and
        maintain the depth/stencil buffer automatically*/
        d3dpp.EnableAutoDepthStencil     = true;
        /*The format of the depth/stencil format
        eg(24-bit depth with 8 bits reserved for the stencil buffer*/
        d3dpp.AutoDepthStencilFormat     = D3DFMT_D24S8;
        /*Some additional characteristics*/
        d3dpp.Flags                      = 0;
        /*Refresh rate*/
        d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
        /*Describes the refresh rate between
        the adapter refresh rate and the rate which 
        IDirect3DDevice9::Present operations are completed*/
        d3dpp.PresentationInterval       = D3DPRESENT_INTERVAL_IMMEDIATE;
    
        /*Step 4, Create the Device*/
        hr = d3d9->CreateDevice(
    	D3DADAPTER_DEFAULT, /*Primary Adapter*/
    	CDeviceType, /*Device type*/
    	CHwnd, /*Window associated with the device*/
    	vp, /*VertexProcessing*/
    	&d3dpp, /*Present parameters*/
    	Device); /*Return the created device*/
    
        if(FAILED(hr)) /*If creating the device failed*/
        {
            /*Try again using a 16-bit depth buffer*/
            d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
    
            hr = d3d9->CreateDevice(
    	    D3DADAPTER_DEFAULT, /*Primary Adapter*/
    	    CDeviceType, /*Device type*/
    	    CHwnd, /*Window associated with the device*/
    	    vp, /*VertexProcessing*/
    	    &d3dpp, /*Present parameters*/
    	    Device); /*Return the created device*/
        }
    
        if(FAILED(hr)) /*If it failed again*/
        {
            d3d9->Release(); /*Done with the d3d9 object*/
            MessageBox(0, "CreateDevice() - FAILED!", "Error", 0);
            return 0; /*Return false*/
        }
    
        d3d9->Release(); /*Done with the d3d9 object*/
    	
        return 1; /*Return true*/
    }
    
    int CRenderDevice::EnterMsgLoop(bool (*ptr_display)(float timeDelta))
    {
        MSG CMsg; /*Message handler*/
        ZeroMemory(&CMsg, sizeof(MSG)); /*Set everything in the message loop to zero*/
    
        static float lastTime = (float)timeGetTime(); 
    
        /*While msg doesn't = WM_QUIT(quit the program), execute the message loop*/
        while(CMsg.message != WM_QUIT) /*Start of message loop*/
        {
            /*Check to see for any messages in the message queue and see if any of them need processing*/ 
            if(PeekMessage(&CMsg, 0, 0, 0, PM_REMOVE))
            {
                /*Translate virtual-key messages into character messages*/
                TranslateMessage(&CMsg);
                /*Dispatch a message to the windows procedure*/
                DispatchMessage(&CMsg);
            }
            else
            {
                float currTime = (float)timeGetTime();
                float timeDelta = (currTime - lastTime)* 0.001f;
    
                ptr_display(timeDelta);
    
                lastTime = currTime;
            }
        }
        return CMsg.wParam;
    }
    
    bool CRenderDevice::CDisplay(float CTimeDelta)
    {
        if(m_Device)
        {
            m_Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
    		    0x00000000, 1.0f, 0);
            m_Device->Present(0, 0, 0, 0);
        }
        return 1;
    }
    
    LRESULT CALLBACK CRenderDevice::WndProc(HWND CHwnd, UINT CMsg, WPARAM wParam, LPARAM lParam)
    {
        switch(CMsg)
        {
            case WM_DESTROY:
    	PostQuitMessage(0);
            break;
            case WM_KEYDOWN:
    	if( wParam == VK_ESCAPE)
    	    DestroyWindow(CHwnd);
            break;
        }
        return DefWindowProc(CHwnd, CMsg, wParam, lParam);
    }
    ......Oh yeah... on a final note. If you have any ways to improve my code or any critisicm please share.... Thanks.

    And sorry about my post being long.
    Last edited by beene; 11-19-2007 at 11:16 AM.

  2. #2
    The larch
    Join Date
    May 2006
    Posts
    3,573
    The error is correct. This class does not have a constructor that can be called with zero arguments. The compiler will not create a default constructor automatically if there are others present.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  3. #3
    Sanity is for the weak! beene's Avatar
    Join Date
    Jul 2006
    Posts
    321
    Thanks, that was a stupid error on my part, I can't believe I didn't see that before, but what about the other errors?

  4. #4
    The larch
    Join Date
    May 2006
    Posts
    3,573
    You mean concerning m_device? It seems somewhat weird to pass the address of a member to initialize the same object. But anyway, if you are taking the address of a member, I guess you should specify the instance of the object that you are talking about.

    Similarly, taking the address of a member function is a bit more complicated than that.
    Last edited by anon; 11-19-2007 at 11:47 AM.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  5. #5
    Sanity is for the weak! beene's Avatar
    Join Date
    Jul 2006
    Posts
    321
    I've gone over what you have posted and I think I know where you're coming from, but I don't know how to fix it without declaring the variable global.

  6. #6
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Just what does the "C" prefix mean in your names?

    Anyway, m_device is CRenderDevice's own member. It shouldn't be passed to the public member function at all. In fact, main() has no business even knowing that m_device exists.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  7. #7
    Sanity is for the weak! beene's Avatar
    Join Date
    Jul 2006
    Posts
    321
    Nothing important.

    So should I make Device global?

  8. #8
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    No. It's a private member and that's fine. It shouldn't appear in any function arguments, is my point.

    For that matter, I see no need for two-phase construction in the CRenderDevice class. (First you default-construct it, then you call CInitD3D. Why not pass all necessary arguments to the constructor?)
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  9. #9
    Sanity is for the weak! beene's Avatar
    Join Date
    Jul 2006
    Posts
    321
    Right, I changed it around abit and now have the error:

    Code:
    error C3867: 'CRenderDevice::CDisplay': function call missing argument list; use '&CRenderDevice::CDisplay' to create a pointer to member
    Should I post the code?

  10. #10
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Yes, post the a few lines of code around where you are getting this error - unless adding a () to the end of the line [before the semicolon] fixes the problem.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  11. #11
    Sanity is for the weak! beene's Avatar
    Join Date
    Jul 2006
    Posts
    321
    Code:
    CRenderDevice::CRenderDevice(HINSTANCE ChInstance)
    {
        CInitD3D( /*If CInitD3D fails*/
    	ChInstance, /*Application instance*/
    	450, /*Application width*/
    	375, /*Application height*/
    	true, /*Windowed?*/
    	D3DDEVTYPE_HAL); /*DeviceType*/
    
    	EnterMsgLoop(CDisplay); /*Pump the message loop*/
    }
    ...and no that didn't work.

  12. #12
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    What's the argument list of EnterMsgLoop? I think you're trying to pass a member function as a normal function pointer. You can't do that.

    Besides, you shouldn't enter the message loop from the constructor. In fact, you shouldn't enter the message loop from the render device at all - what have they got to do with each other?
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  13. #13
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    You should stick your message loop in the application object. The message loop in turn then calls the application render function or view render function after the delta time has been calculated and after Update() has been called on all objects.

    This code is most likely from a book by Frank Luna where he passes in a render function pointer. The OP does not realize that you cannot pass a C++ function that way because it is called with a this call instead of a std call.

    There are 3 solutions and the one I chose was to make the message loop call a reachable C++ function (IE: one it had access to and therefore did not need a pointer). This solution makes sense too since Application::Render() is a function of the app. Remember you are only calling this from the message loop. There is nothing then preventing you from using a View class object to actually perform the rendering in the loop.

    2nd solution is to create a render function that is not a member of any class. I do not recommend this since it obviously causes a host of other problems. This is the method the book chooses and I do not agree with it.

    3rd solution is to make the render function static. Now you cannot touch non-static class objects in a static function but you can get around this by calling a non-static render function from the static render function. I don't recommend this either since this effectively means you have 2 render calls and one just simply calls another render function. This IMO is not a good design.
    Last edited by VirtualAce; 11-20-2007 at 06:57 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Possibility to create a good game engine
    By sarah22 in forum Tech Board
    Replies: 8
    Last Post: 06-13-2009, 01:04 AM
  2. Game Engine, please guide me!
    By Akkernight in forum Game Programming
    Replies: 12
    Last Post: 03-04-2009, 02:31 PM
  3. game engine advice?
    By stien in forum Game Programming
    Replies: 0
    Last Post: 01-23-2007, 03:46 PM
  4. Game Engine Link Prob
    By swgh in forum Game Programming
    Replies: 2
    Last Post: 01-26-2006, 12:14 AM
  5. What specifically is a game Engine?
    By WebSnozz in forum Game Programming
    Replies: 3
    Last Post: 12-24-2001, 12:26 AM