Sign in to follow this  
Antonym

Optimizing my c++ code

Recommended Posts

Antonym    179
Hello I though it was time to optimize my code/make good c++ code.. Right now I think I am not really doing object oriented programming... my code is messy and noobish. I use globals a lot, I use structures and any efficient measure for code you can think off I probably don't use.. Could anyone give me some tips/point me to an article on two on how to make good code? Something that caught my attention a while ago that several programs from books and tutorials I came a cross had everything handled in complex classes, classes kept in header files that were accesed in source files. I don't know how to go about or where to start changing my code to this style, it looked really organized and 'efficient'. Any info on the subject would be appreciated.

Share this post


Link to post
Share on other sites
rip-off    10979
Writing good code has little to do with "optimizing" or "efficiency" - unless you are talking about programmer efficiency.

The first step is typically to break your code into smaller chunks. This may help.

Share this post


Link to post
Share on other sites
Antonym    179
Oh I already read that article and did the splitting into headers and source files though I am not sure I am doing a good job when it comes to what functions go in what files. I am also trying to get rid of my global variables.

Share this post


Link to post
Share on other sites
bluntman    255
Quote:
Writing good code has little to do with "optimizing" or "efficiency"

More like, writing good code is broad area with a few different measures. In my opinion (i.e. I agree with rip-off) the first area to work on would be code layout, structure and naming . But optimization and efficiency in terms of algorithm choice, and data management are very important in certain areas of games programming at certain levels (generally professional level, or "hardcore" projects).

Share this post


Link to post
Share on other sites
Treb    172
I would recommend Effective C++ over Code Complete. I liked the concrete examples Effective C++ was able to give, and the lay out was very nice. I would also recommend reading Guru of The Week as a free resource.

Share this post


Link to post
Share on other sites
godsenddeath    182
Quote:
Original post by Antonym
Oh I already read that article and did the splitting into headers and source files though I am not sure I am doing a good job when it comes to what functions go in what files. I am also trying to get rid of my global variables.


Generally you create a header/source pair for every class you write(and the majority of your code should be in classes), the rest of the functions would usually be grouped in files by functionality. I don't know what your project is, but say all your set-up/initialization functions would be in one, possibly along with clean up, all of your asset/file loading could go in one, but liek I said, these would generally be in classes.

The only "loose" functions you should have would be utility functions in which there aren't enough related ones to form a utility class.


also, when you're talking about optimization, if you remember anything, remember this... 20/80. 20% of your code will be run 80% of the time, and that is a proven fact. So although you should generally write code with proformance in mind, figure out the code that gets run the most, and that is what you should optimize first

Share this post


Link to post
Share on other sites
VanillaSnake21    175
Quote:
Original post by Treb
I would recommend Effective C++ over Code Complete. I liked the concrete examples Effective C++ was able to give, and the lay out was very nice. I would also recommend reading Guru of The Week as a free resource.


Effective C++ points out common mistakes , it does not go too deep into organization, optimization, modularity, cohesion etc. Code Complete teaches you how to write reliable, clear code. Effectiv C++ complements by going deeper into the syntatical correctness.

Share this post


Link to post
Share on other sites
Clawer    166
Hi,

if you want to use good object oriented solutions I suggest you to read this book. The book is not for beginners so, before buying, consider if you would be able to understand it.

Another good solution would be to study on good source code or to work with experienced programmers.

Share this post


Link to post
Share on other sites
Antonym    179
Yikes lots of info, lots of different viewpoints... I feel I am biting more than I can chew.

Do you guys think it would be a bad idea to go with the info I've gathered, the bits and pieces from here and there and work with that? Try and learn the rest as I go?

Share this post


Link to post
Share on other sites
demonkoryu    980
Learning "proper" OOP is not so easy as it looks. But it can considerably elevate the code abstraction level:

  • The most important gain from using objects is to encapsulate data and algorithms behind an interface (an object). That way you can change underlying implementations (mostly done via private members or other means to hide away messy details) without having to change all code that is using the object.
  • Second, you can re-use classes via subclassing.
  • Third, OOP then enables complex forms of abstraction via use of interfaces (you can exchange classes and thus implementations in your code when these classes have common interfaces, possibly during runtime if you're using virtual methods).

    You'll have to bite the bullet and experiment with OOP, to see how you can use it with your code. A good way to learn fast is to use OOP code, from a premade engine or another software (I learned lots about OOP from Qt GUI framework).

    Share this post


    Link to post
    Share on other sites
    demonkoryu    980
    Quote:
    Original post by DevFred
    Quote:
    Original post by godsenddeath
    The only "loose" functions you should have would be utility functions

    Haven't you read How Non-Member Functions Improve Encapsulation?

    I do not buy into this. Artificially breaking the public interface into member and non-member functions feels unnatural and just serves to show off the "minimality" of the class interface. At some point, as additional requirements surface, some non-members will have to be integrated back into the class, making the free functions redundant, or the public interface will have to be extended to cover that additional functionality, thus showing how unneccessary the separation was in the first place.

    Share this post


    Link to post
    Share on other sites
    Antonym    179
    Hmm.. so I decided to try and get down to it.. and couldn't I really don't know how to get down with it.

    For example this is the code I have for creating a window and initilizing everything else.. I don't know hot to make it more oriented programish or implement encapsulation.. :S

    How would could I do it just for example?


    #include "global.h"

    input inputData;

    int WINAPI WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow)
    {
    HWND hWnd;

    if(!displayWindow(&hWnd, hInstance, nCmdShow))
    return 0;

    if(!initD3D(&hWnd))

    return 0;

    loadGraphics();

    mainLoop();

    closeDX();

    return 0;
    }

    bool displayWindow (HWND *hWnd, HINSTANCE hInstance, int nCmdShow){
    WNDCLASSEX wc;


    ZeroMemory(&wc, sizeof(WNDCLASSEX));

    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = (WNDPROC)WindowProc;
    wc.hInstance = hInstance;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.lpszClassName = "WindowClass1";

    if(RegisterClassEx(&wc)==0)
    return FALSE;

    *hWnd = CreateWindowEx(NULL,
    "WindowClass1",
    "Dungeon",
    WS_OVERLAPPEDWINDOW,
    // WS_EX_TOPMOST | WS_POPUP,
    0, 0,
    SCREEN_WIDTH, SCREEN_HEIGHT,
    NULL,
    NULL,
    hInstance,
    NULL);

    if(*hWnd == NULL)
    return FALSE;

    ShowWindow(*hWnd, nCmdShow);

    return TRUE;
    }

    bool handleMessages(){
    static MSG msg;

    if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
    if(msg.message == WM_QUIT)
    return FALSE;

    TranslateMessage(&msg);
    DispatchMessage(&msg);
    }

    return TRUE;
    }

    LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){
    switch(message)
    {
    case WM_DESTROY:
    {
    PostQuitMessage(0);
    return 0;
    } break;

    case WM_KEYDOWN:
    {
    switch(wParam)
    {
    case VK_RIGHT:
    {
    inputData.turn_right = true;
    } break;

    case VK_LEFT:
    {
    inputData.turn_left = true;
    } break;

    case VK_UP:
    {
    inputData.move_forward = true;
    } break;

    case VK_DOWN:
    {
    inputData.move_backward = true;
    } break;

    case VK_SPACE:
    {
    inputData.shooting = true;
    } break;

    case VK_ESCAPE:
    {
    DestroyWindow(hWnd);
    } break;

    }

    } break;

    case WM_KEYUP:
    {
    switch(wParam)
    {
    case VK_RIGHT:
    {
    inputData.turn_right = false;
    } break;

    case VK_LEFT:
    {
    inputData.turn_left = false;
    } break;

    case VK_UP:
    {
    inputData.move_forward = false;
    } break;

    case VK_DOWN:
    {
    inputData.move_backward = false;
    } break;

    case VK_SPACE:
    {
    inputData.shooting = false;
    } break;
    }

    } break;
    }

    return DefWindowProc (hWnd, message, wParam, lParam);
    }

    Share this post


    Link to post
    Share on other sites
    demonkoryu    980
    GD.net has a good article on this very subject.

    But to try to answer your question:
    The first thing will be to get these free functions into a class, so that you can just do:

    Window window;
    if(!window.displayWindow(hInstance, nCmdShow))
    return 0;

    if(!initD3D(window.getHandle()))
    return 0;



    You can then also create a D3D object that just takes a window as a parameter, so you can do

    Window window;
    if(!window.display(hInstance, nCmdShow))
    return 0;
    D3D d3d(window);
    if(!d3d.init())
    return 0;


    Notice that you're not passing the HWND directly. It's "encapsulated" by the Window object.


    What you're doing when you move code around is called "refactoring", and it's pretty easy to do when you're used to it. There's a page about refactoring and you should get one of the recommended books if you're serious about software engineering.

    Share this post


    Link to post
    Share on other sites
    visitor    643
    Quote:

    I do not buy into this. Artificially breaking the public interface into member and non-member functions feels unnatural and just serves to show off the "minimality" of the class interface. At some point, as additional requirements surface, some non-members will have to be integrated back into the class, making the free functions redundant, or the public interface will have to be extended to cover that additional functionality, thus showing how unneccessary the separation was in the first place.


    Both sides have good arguments. In any case it is important to avoid reduplicating code and to implement things in terms of other things where possible. There is nothing in member functions that says they cannot or shouldn't be implemented in terms of other (public) methods (except you are not forced to).

    Share this post


    Link to post
    Share on other sites
    Antonym    179
    Alright I think I am getting something..

    Here's the header with the new class I created for it and the new source file..
    Although I am getting some stranger errors I don't get..

    1>c:\documents and settings\david\mis documentos\visual studio 2005\projects\dungeon\dungeon\window.h(30) : error C2533: 'application::{ctor}' : constructors not allowed a return type
    1>c:\documents and settings\david\mis documentos\visual studio 2005\projects\dungeon\dungeon\window.cpp(11) : error C2264: 'application::application' : error in function definition or declaration; function not called

    header

    #include <windows.h>
    #include <windowsx.h>

    class application
    {
    private:
    HWND hWnd;

    WNDCLASSEX wc;

    LPCSTR className;
    LPCSTR windowName;

    DWORD windowStyle;

    int screenWidth;
    int screenHeight;

    static MSG msg;

    public:
    application();
    HWND getHandle();
    bool displayWindow(HINSTANCE, int);
    bool handleMessages();

    }

    application::application()
    {
    className = "WindowClass1";
    windowName = "Dungeon";
    windowStyle = WS_OVERLAPPEDWINDOW;
    screenWidth = 640;
    screenHeight = 480;
    }

    HWND application::getHandle()
    {
    return hWnd;
    }

    bool application::displayWindow(HINSTANCE hInstance, int nCmdShow)
    {
    ZeroMemory(&wc, sizeof(WNDCLASSEX));

    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = (WNDPROC)WindowProc;
    wc.hInstance = hInstance;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.lpszClassName = className;

    if(RegisterClassEx(&wc)==0)
    return FALSE;

    hWnd = CreateWindowEx(NULL,
    className,
    windowName,
    windowStyle,
    0, 0,
    screenWidth,
    screenHeight,
    NULL,
    NULL,
    hInstance,
    NULL);

    if(hWnd == NULL)
    return FALSE;

    ShowWindow(hWnd, nCmdShow);

    return TRUE;
    }

    bool application::handleMessages()
    {

    if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
    if(msg.message == WM_QUIT)
    return FALSE;

    TranslateMessage(&msg);
    DispatchMessage(&msg);
    }

    return TRUE;
    }




    source

    #include "global.h"
    #include "window.h"

    input inputData;

    int WINAPI WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow)
    {
    application app;

    if(!app.displayWindow(hInstance, nCmdShow))
    return 0;

    if(!initD3D(app.getHandle()))
    return 0;

    loadGraphics();

    mainLoop();

    closeDX();

    return 0;
    }

    LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    switch(message)
    {
    case WM_DESTROY:
    {
    PostQuitMessage(0);
    return 0;
    } break;

    case WM_KEYDOWN:
    {
    switch(wParam)
    {
    case VK_RIGHT:
    {
    inputData.turn_right = true;
    } break;

    case VK_LEFT:
    {
    inputData.turn_left = true;
    } break;

    case VK_UP:
    {
    inputData.move_forward = true;
    } break;

    case VK_DOWN:
    {
    inputData.move_backward = true;
    } break;

    case VK_SPACE:
    {
    inputData.shooting = true;
    } break;

    case VK_ESCAPE:
    {
    DestroyWindow(hWnd);
    } break;

    }

    } break;

    case WM_KEYUP:
    {
    switch(wParam)
    {
    case VK_RIGHT:
    {
    inputData.turn_right = false;
    } break;

    case VK_LEFT:
    {
    inputData.turn_left = false;
    } break;

    case VK_UP:
    {
    inputData.move_forward = false;
    } break;

    case VK_DOWN:
    {
    inputData.move_backward = false;
    } break;

    case VK_SPACE:
    {
    inputData.shooting = false;
    } break;
    }

    } break;
    }

    return DefWindowProc (hWnd, message, wParam, lParam);
    }





    A couple of unrelated questions..
    What does static mean?
    Is using typedefs okey?
    When/how does WindowProc get called?

    Share this post


    Link to post
    Share on other sites
    visitor    643
    Quote:

    What does static mean?


    In front of a class member it means that this is not an instance member, but something that all instances of this class share.

    Quote:

    Is using typedefs okey?


    Absolutely.

    Unless they are more confusing than the original type, e.g typedeffing pointers is somewhat bad (though WINAPI uses it everywhere).


    typedef int* PData;
    ...
    int main()
    {
    PData dat;
    ...
    }


    When you are not careful and things are far from each other, it is easy to think that dat is a normal default-constructed object (and therefore doesn't need to be initialized). However, it is actually just an uninitialized pointer.


    Quote:

    When/how does WindowProc get called?


    From handleMessages (and in particular as a callback by DispatchMessage). And the procedure was registered first with the window in displayWindow.

    You just need to study WinAPI references (and introductory tutorials).

    Share this post


    Link to post
    Share on other sites
    rip-off    10979
    You should aim to have as few members as possible. For example, your MSG variable can be local to handleMessages() as it is never used elsewhere.

    In addition your WNDCLASSEX and className variables should be local to displayWindow(), they don't appear to be used elsewhere. Your windowstyle variable is effectively a constant, so I would define it as a const local inside displayWindow(), unless you want to provide a way to change or modify this.

    Arguably the same could apply to the windowName, screenWidth and screenHeight, but I think having these values as an arguments to the constructor would be a good idea (then you can easily reuse this class in different projects). You can keep a default constructor for quick prototyping projects.

    Finally, I believe it is very poor style to cast the WNDPROC, because this could cause errors. Your WindowProc must match the declaration exactly, so a cast should be unnecessary. I would take the WindowProc as an argument to displayWindow. Currently you must be forward declaring the WindowProc somewhere. But I don't really know if that is a great idea - I don't program with raw WinAPI calls.

    Share this post


    Link to post
    Share on other sites
    Antonym    179


    'Finally, I believe it is very poor style to cast the WNDPROC, because this could cause errors. Your WindowProc must match the declaration exactly, so a cast should be unnecessary. I would take the WindowProc as an argument to displayWindow. Currently you must be forward declaring the WindowProc somewhere.'
    What does this mean?

    'But I don't really know if that is a great idea - I don't program with raw WinAPI calls.'
    How do you do it then?

    Share this post


    Link to post
    Share on other sites
    rip-off    10979
    Quote:
    Original post by Antonym


    'Finally, I believe it is very poor style to cast the WNDPROC, because this could cause errors. Your WindowProc must match the declaration exactly, so a cast should be unnecessary. I would take the WindowProc as an argument to displayWindow. Currently you must be forward declaring the WindowProc somewhere.'
    What does this mean?

    It means two things.

    The first is that you cast the symbol "WindowProc" to a WNDPROC. This is an extremely bad idea. We cast when C++ won't implicitly change a value from one thing to another. A WindowProc should already be a WNDPROC, so the cast is unnecessary. However, a more subtle problem is: what is WindowProc isn't a WNDPROC? Well, the code should fail to compile. But you put in a cast, which could cause the code to compile anyway. This is extremely dangerous, calling a function through the incorrect pointer type is asking for your code to behave in unpredictable ways. It is a perfect example of undefined behaviour.

    Secondly, your code uses the symbol "WindowProc", yet it isn't declared in the file it is used in. This must mean that it is declared somewhere else, probably in "global.h". This means that your class implicitly depends on the existence of a function with the correct signature called WindowProc being available.

    Your code can make this dependency explicit by receiving the WNDPROC as an argument:

    bool application::displayWindow(HINSTANCE hInstance, int nCmdShow, WNDPROC windProc)
    {
    ZeroMemory(&wc, sizeof(WNDCLASSEX));

    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = windProc;
    }



    Quote:

    'But I don't really know if that is a great idea - I don't program with raw WinAPI calls.'
    How do you do it then?


    A library like SDL handles pretty much everything I need for window creation, input handling (and more) in less code, and in a cross platform fashion. If you just want to set up a basic rendering context to draw to (using a 2D API or OpenGL) SDL is perfect solution. There are others too I'm sure.

    Share this post


    Link to post
    Share on other sites
    Antonym    179
    I made the changes as suggested. By the way with 'WindowProc symbol' you meant the WindowProc function's declaration right?

    I moved on to the direct3d object.. When I finished the class the source file was empty :S.. Here I didnt change much either..

    I am still trying to determine which variables should be contained within the class and which within each function.. I am confused when it comes to having members from this class work with members of other classes. For example when direct3d is initialized it requires several members from the window class such as screen width, height, the handle to the window(HWND) and particularly when it comes to the part of drawing the sprites I think it'll require a lot of info from members of classes I plan to make soon.. The game's objects such as the ship and missiles.

    Edit: On a side note, I read the do not cast article, understood it somewhat. Something that I wanted to mention was that I ended up on this other article.
    http://blogs.msdn.com/oldnewthing/archive/2004/01/08/48616.aspx
    Abd how do people learn all of this? Where is this knowledge available? It all is gibberish to me yet they/he seems to know every little detail and that detail's very inner workings.. An understanding like that would be great instead of my pseudo-understanding of the inner workings of code.


    #include "window.h"

    class Direct3D
    {
    private:

    IDirect3D9* d3dObject;
    IDirect3DDevice9* d3dDevice;
    LPD3DXSPRITE d3dSprite;
    bool windowed;

    public:
    Direct3D();
    void loadSprite(sprite*, LPCTSTR, int, int, D3DXVECTOR2, D3DXVECTOR2)
    void startRender();
    void endRender();
    void Direct3D::drawSprite(sprite*, object*);
    void closeDX();
    }

    Direct3D::Direct3D(application app)
    {
    IDirect3D9* d3dObject = NULL;
    IDirect3DDevice9* d3dDevice = NULL;
    LPD3DXSPRITE d3dSprite = NULL;
    windowd = TRUE;

    //Direct3D Interface
    d3dObject = Direct3DCreate9(D3D_SDK_VERSION);
    if(d3dObject == NULL)
    return FALSE;

    //Present Parameters
    D3DPRESENT_PARAMETERS d3dpp;

    ZeroMemory(&d3dpp, sizeof(d3dpp));

    d3dpp.Windowed = windowed;
    d3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD;
    d3dpp.hDeviceWindow = app.hWnd;
    d3dpp.BackBufferFormat=D3DFMT_X8R8G8B8;
    d3dpp.BackBufferWidth = app.screenWidth;
    d3dpp.BackBufferHeight = app.screenHeight;
    d3dpp.BackBufferCount=1;
    d3dpp.PresentationInterval=D3DPRESENT_INTERVAL_ONE;

    //Direct3D Device
    HRESULT hr = d3dObject->CreateDevice(D3DADAPTER_DEFAULT,
    D3DDEVTYPE_HAL,
    app.hWnd,
    D3DCREATE_HARDWARE_VERTEXPROCESSING,
    &d3dpp,
    &d3dDevice);
    if(FAILED(hr))
    {
    //Try Software instead of Hardware
    hr = d3dObject->CreateDevice(D3DADAPTER_DEFAULT,
    D3DDEVTYPE_HAL,
    app.hWnd,
    D3DCREATE_SOFTWARE_VERTEXPROCESSING,
    &d3dpp,
    &d3dDevice);
    if(FAILED(hr))
    return FALSE;
    }

    //Sprite interface
    hr = D3DXCreateSprite(d3dDevice, &d3dSprite);
    if(FAILED(hr)){
    closeDX();
    return FALSE;
    }
    return TRUE;
    }

    void Direct3D::loadSprite(sprite* pSprite,
    LPCTSTR file,
    int width,
    int height,
    D3DXVECTOR2 scaling,
    D3DXVECTOR2 center)
    {
    D3DXCreateTextureFromFileEx(d3dDevice,
    file,
    D3DX_DEFAULT,
    D3DX_DEFAULT,
    D3DX_DEFAULT,
    NULL,
    D3DFMT_A8R8G8B8,
    D3DPOOL_MANAGED,
    D3DX_DEFAULT,
    D3DX_DEFAULT,
    D3DCOLOR_XRGB(255, 0, 255),
    NULL,
    NULL,
    &pSprite->tex);

    pSprite->width = width;
    pSprite->height = height;
    pSprite->scaling = scaling;
    pSprite->center = center;
    }

    void Direct3D::startRender(){
    d3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
    d3dDevice->BeginScene();
    d3dSprite->Begin(D3DXSPRITE_ALPHABLEND);
    }

    void Direct3D::endRender(){
    d3dSprite->End();
    d3dDevice->EndScene();
    d3dDevice->Present(NULL, NULL, NULL, NULL);
    }

    void Direct3D::drawSprite(sprite* pSprite, object* pObject)
    {
    //Sprite portion to draw
    RECT frameBox;

    frameBox.left = pSprite->col * pSprite->width;
    frameBox.right = frameBox.left + pSprite->width;
    frameBox.top = pSprite->row * pSprite->height;
    frameBox.bottom = frameBox.top + pSprite->height;

    //Sprite transformation
    D3DXVECTOR2 scaling = pSprite->scaling;
    D3DXVECTOR2 center = pSprite->center;
    D3DXVECTOR2 pos = pObject->pos;
    float rotation = (float)pObject->angle2 * DegtoRad;

    D3DXMATRIX mat;
    D3DXMatrixTransformation2D(&mat, NULL, NULL, &scaling, &center, rotation, &pos);

    d3dSprite->SetTransform(&mat);
    d3dSprite->Draw(pSprite->tex, &frameBox, NULL, NULL, 0xFFFFFFFF);


    bool edge = false;

    //Check to redraw at other side of screen if the edge has been reached
    D3DXVECTOR2 part = pObject->pos;
    if((pObject->pos.x - pObject->width) < 0){
    part.x = pObject->pos.x + screenWidth;
    }
    if((pObject->pos.x + pObject->width) > screenWidth){
    part.x = pObject->pos.x - screenWidth;
    }
    if((pObject->pos.y - pObject->height) < 0){
    part.y = pObject->pos.y + screenHeight;
    }
    if((pObject->pos.y + pObject->height) > screenHeight){
    part.y = pObject->pos.y - screenHeight;
    }

    //Redraw
    D3DXMatrixTransformation2D(&mat, NULL, NULL, &scaling, &center, rotation, &#8706;);
    d3dSprite->SetTransform(&mat);
    d3dSprite->Draw(pSprite->tex, &frameBox, NULL, NULL, 0xFFFFFFFF);

    }

    void Direct3d::closeDX()
    {
    if(d3dSprite)
    d3dSprite->Release();

    if(d3dDevice)
    d3dDevice->Release();

    if(d3dObject)
    d3dObject->Release();
    }




    [Edited by - Antonym on December 19, 2008 4:14:34 PM]

    Share this post


    Link to post
    Share on other sites
    visitor    643
    Quote:

    I moved on to the direct3d object.. When I finished the class the source file was empty :S


    If you put the implementation of the class methods into a source file then it wouldn't be empty. Accidentally, for this reason, if I'm not mistaken, it might not be possible to include this header from more than one other source file without getting "multiple definitions" linker errors.

    Quote:

    I am still trying to determine which variables should be contained within the class and which within each function..


    Does a variable have to retain the value between calls to the member function(s) where it is used? In other cases it is more appropriate to use local variables/pass arguments to methods.

    Quote:

    For example when direct3d is initialized it requires several members from the window class such as screen width, height, the handle to the window(HWND)


    You may not need to pass the entire application class (actually it might not be a good idea to pass that by value - what are the consequences of copying the application?). Instead you might pass the size data (width/height could be wrapped into a nice struct) and HWND as separate arguments. The application class might have an accessor function to obtain these. (As I see it this might be desirable since it "decouples" the directx class from the application class. They don't need to know about each other. The less classes know about each other, the more flexible the architecture.)

    Share this post


    Link to post
    Share on other sites
    Antonym    179
    But you need an instance of a class to access its members don't you? So you would need to either have a global instance of a class or pass it to other classes/functions of other classes as an argument wouldn't you?

    I want to learn more about decoupling specially when it comes to classes interacting with one another..

    Also wouldn't doing this...

    struct window
    {
    windowName;

    screenWidth;
    screenHeight;

    window();
    }gw; //game window

    window::window()
    {
    windowName = "Dungeon";

    screenWidth = 640;
    screenHeight = 480;
    }



    make the window and direct3d code messy?

    Share this post


    Link to post
    Share on other sites

    Create an account or sign in to comment

    You need to be a member in order to leave a comment

    Create an account

    Sign up for a new account in our community. It's easy!

    Register a new account

    Sign in

    Already have an account? Sign in here.

    Sign In Now

    Sign in to follow this