0

Creating a small 2D game, using Direct3D 9 and C++. I have come across a problem I have not seen before. The game is a shop based one so I have a customer class. I have created the object in the game and it renders and behaves how I want for the minute. I decided to put the object in to a Vector instead because I will, at some point, need a collection of them at any one time. My problem is, however, when I put the object in to a Vector, it no longer is visible on the screen!

I get no errors. I have outputted all the return codes from the DirectX functions in to a test file and nothing failed. It ran fine, it just isn't visible on the screen! Nothing has changed other than putting it in to a Vector.

I changed the Vector to a Vector of pointers because I was told that the Vector was simply creating the object, copying it and deleting the original. However, it would now seem that my Direct3D pointers become invalid using this method, pretty quickly. I think I know what is going wrong but not sure the best course of action.

Here is the customer class:

#include "Headers.h"
#include "Playercard.h"

class Customer{

private:

LPDIRECT3DTEXTURE9 texture, playerInfoCard;
D3DXVECTOR3 position, direction, playerCardPosition;
D3DXVECTOR3 center;
LPD3DXFONT font;
POINT curPos;

HRESULT rc;

//Playercard playerCard;
int depthBuffer;
int walkingAlternator;

// Some information about the customer

char name[10];
int age;
double cash;

int itemWanted;
char productWanted[20];

bool happy;
bool male;
bool female;
bool displayPlayerCard;

RECT textBox;

Playercard playercard;

void assignNameAndGender()
{
    srand((unsigned int)time(0));
    int name_decider = rand() % 16 + 1;

    switch(name_decider)
    {
    case 1:
        strcpy_s(name, "John");
        male = true; female = false;
        break;
    case 2:
        strcpy_s(name, "Chris");
        male = true; female = false;
        break;
    case 3:
        strcpy_s(name, "Ben");
        male = true; female = false;
        break;
    case 4:
        strcpy_s(name, "Jack");
        male = true; female = false;
        break;
    case 5:
        strcpy_s(name, "Jamie");
        male = true; female = false;
        break;
    case 6:
        strcpy_s(name, "Bill");
        male = true; female = false;
        break;
    case 7:
        strcpy_s(name, "Liam");
        male = true; female = false;
        break;
    case 8:
        strcpy_s(name, "Alex");
        male = true; female = false;
        break;
    case 9:
        strcpy_s(name, "Nikki");
        male = false; female = true;
        break;
    case 10:
        strcpy_s(name, "Alice");
        male = false; female = true;
        break;
    case 11:
        strcpy_s(name, "Lucy");
        male = false; female = true;
        break;
    case 12:
        strcpy_s(name, "Emily");
        male = false; female = true;
        break;
    case 13:
        strcpy_s(name, "Laura");
        male = false; female = true;
        break;
    case 14:
        strcpy_s(name, "Mary");
        male = false; female = true;
        break;
    case 15:
        strcpy_s(name, "Katie");
        male = false; female = true;
        break;
    case 16:
        strcpy_s(name, "Emma");
        male = false; female = true;
        break;
    }
}

void assignAge()
{
    srand((unsigned int)time(0));
    age = rand() % 53 + 12;          // An age between 12 and 65
}

void assignCash()
{
    if(age < 16)
        cash = 5.00;
    if(age >= 16 && age <= 18)
        cash = 15.00;
    if(age >= 19 && age <= 21)
        cash = 20.00;
    if(age >= 22 && age <= 25)
        cash = 25.00;
    if(age >= 26 && age <= 30)
        cash = 30.00;
    if(age > 31)
    {
        int randNum = rand() % 9 + 1;

        switch(randNum)
        {
        case 1:
            cash = 20.00;
            break;
        case 2:
            cash = 25.00;
            break;
        case 3:
            cash = 30.00;
            break;
        case 4:
            cash = 35.00;
            break;
        case 5:
            cash = 40.00;
            break;
        case 6:
            cash = 45.00;
            break;
        case 7:
            cash = 50.00;
            break;
        case 8:
            cash = 55.00;
            break;
        case 9:
            cash = 60.00;
            break;
        }
    }
}

public:

Customer()
{
    direction.x = (float)cos(0.558)*4;    // 30 degree movement
    direction.y = (float)sin(0.558)*4;    // 30 degree movement
    position.x = 500;
    position.y = 500;
    displayPlayerCard = false;  // Only true when mouse clicked
    happy = true;               // A new customer is always happy at first!
    walkingAlternator = 1;      // Help control sprite movement

    strcpy_s(productWanted, "Xbox");
    assignNameAndGender();      // Assign customer a name
    assignAge();                // Assign customer an age
    assignCash();               // Assign customer an amount of cash
    playercard.load(name, male, age, cash, productWanted);
}

~Customer()
{
}


void move()
{
    if(KEY_DOWN(0x57) || KEY_DOWN(VK_UP))
    {
        position.y -= direction.y;
        position.x += direction.x;
        walkingUp();
    }
    else if(KEY_DOWN(0x41) || KEY_DOWN(VK_LEFT))
    {
        position.y -= direction.y;
        position.x -= direction.x;
        walkingLeft();
    }
    else if(KEY_DOWN(0x53) || KEY_DOWN(VK_DOWN))
    {
        position.y += direction.y;
        position.x -= direction.x;
        walkingDown();
    }
    else if(KEY_DOWN(0x44) || KEY_DOWN(VK_RIGHT))
    {
        position.y += direction.y;
        position.x += direction.x;
        walkingRight();
    }
    else
    {
        // Reset the sprite here so that the feet are together in resting position AND so that sprite is facing the way it was going when it stopped
    }
}

void loadGraphics()
{
    D3DXCreateTextureFromFileEx(d3dDevice, "player_information_card.png", D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2, 0, 0, 
        D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DCOLOR_XRGB(255, 255, 255), NULL, NULL, &playerInfoCard);

    D3DXCreateTextureFromFileEx(d3dDevice, "Characters/female_shopper1.png", D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2, 0, 0,
        D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DCOLOR_XRGB(255, 255, 255), NULL, NULL, &texture);

    D3DXVECTOR3 position(100.0f, 100.0f, 0.0f);
    D3DXVECTOR3 center(0.0f, 0.0f, 0.0f);

    D3DXCreateFont(d3dDevice,                   // the D3D Device
               20,                              // font height of 30
               0,                               // default font width
               FW_NORMAL,                       // font weight
               1,                               // not using MipLevels
               false,                           // italic font
               DEFAULT_CHARSET,                 // default character set
               OUT_DEFAULT_PRECIS,              // default OutputPrecision,
               DEFAULT_QUALITY,                 // default Quality
               DEFAULT_PITCH | FF_DONTCARE,     // default pitch and family
               "Georgia",                       // use Facename Arial
               &font);                          // the font object    
}

void draw()
{
    d3dSprite->Draw(texture, NULL, &center, &position, D3DCOLOR_ARGB(255, 255, 255, 255));

    if(displayPlayerCard) 
    {
        playerCardPosition = position;
        playerCardPosition.y -= 128;
        playerCardPosition.x += 32;

        SetRect(&textBox, (int)playerCardPosition.x+5, (int)playerCardPosition.y+5, (int)playerCardPosition.x+256-5, (int)playerCardPosition.y+128-5);

        d3dSprite->Draw(playerInfoCard, NULL, &center, &playerCardPosition, D3DCOLOR_ARGB(255, 255, 255, 255));
        font->DrawTextA(d3dSprite, playercard.plCard().c_str(), -1, &textBox, DT_LEFT, D3DCOLOR_ARGB(255, 255, 255, 255));
    }
}

void walkingDown()
{
    if(walkingAlternator == 1 || walkingAlternator == 2 || walkingAlternator == 3 || walkingAlternator == 4 || walkingAlternator == 5 
        || walkingAlternator == 6 || walkingAlternator == 7 || walkingAlternator == 8 || walkingAlternator == 9 || walkingAlternator == 10)
    {
        D3DXCreateTextureFromFileEx(d3dDevice, "Characters/female_shopper2.png", D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2, 0, 0, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT,
        D3DX_DEFAULT, D3DX_DEFAULT, D3DCOLOR_XRGB(255, 255, 255), NULL, NULL, &texture);
        walkingAlternator++;
    }
    else if(walkingAlternator == 11 || walkingAlternator == 12 || walkingAlternator == 13 || walkingAlternator == 14 || walkingAlternator == 15
        || walkingAlternator == 16 || walkingAlternator == 17 || walkingAlternator == 18 || walkingAlternator == 19 || walkingAlternator == 20)
    {
        D3DXCreateTextureFromFileEx(d3dDevice, "Characters/female_shopper3.png", D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2, 0, 0, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT,
        D3DX_DEFAULT, D3DX_DEFAULT, D3DCOLOR_XRGB(255, 255, 255), NULL, NULL, &texture);
        walkingAlternator++;
    }

    if(walkingAlternator >= 20)
    {
        walkingAlternator = 1;
    }
}

void walkingUp()
{
    if(walkingAlternator == 1 || walkingAlternator == 2 || walkingAlternator == 3 || walkingAlternator == 4 || walkingAlternator == 5 
        || walkingAlternator == 6 || walkingAlternator == 7 || walkingAlternator == 8 || walkingAlternator == 9 || walkingAlternator == 10)
    {
        D3DXCreateTextureFromFileEx(d3dDevice, "Characters/female_shopper1_back2.png", D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2, 0, 0, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT,
        D3DX_DEFAULT, D3DX_DEFAULT, D3DCOLOR_XRGB(255, 255, 255), NULL, NULL, &texture);
        walkingAlternator++;
    }
    else if(walkingAlternator == 11 || walkingAlternator == 12 || walkingAlternator == 13 || walkingAlternator == 14 || walkingAlternator == 15
        || walkingAlternator == 16 || walkingAlternator == 17 || walkingAlternator == 18 || walkingAlternator == 19 || walkingAlternator == 20)
    {
        D3DXCreateTextureFromFileEx(d3dDevice, "Characters/female_shopper1_back1.png", D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2, 0, 0, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT,
        D3DX_DEFAULT, D3DX_DEFAULT, D3DCOLOR_XRGB(255, 255, 255), NULL, NULL, &texture);
        walkingAlternator++;
    }

    if(walkingAlternator >= 20)
    {
        walkingAlternator = 1;
    }
}

void walkingLeft()
{
    if(walkingAlternator == 1 || walkingAlternator == 2 || walkingAlternator == 3 || walkingAlternator == 4 || walkingAlternator == 5 
        || walkingAlternator == 6 || walkingAlternator == 7 || walkingAlternator == 8 || walkingAlternator == 9 || walkingAlternator == 10)
    {
        D3DXCreateTextureFromFileEx(d3dDevice, "Characters/female_shopper1_back3.png", D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2, 0, 0, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT,
        D3DX_DEFAULT, D3DX_DEFAULT, D3DCOLOR_XRGB(255, 255, 255), NULL, NULL, &texture);
        walkingAlternator++;
    }
    else if(walkingAlternator == 11 || walkingAlternator == 12 || walkingAlternator == 13 || walkingAlternator == 14 || walkingAlternator == 15
        || walkingAlternator == 16 || walkingAlternator == 17 || walkingAlternator == 18 || walkingAlternator == 19 || walkingAlternator == 20)
    {
        D3DXCreateTextureFromFileEx(d3dDevice, "Characters/female_shopper1_back4.png", D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2, 0, 0, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT,
        D3DX_DEFAULT, D3DX_DEFAULT, D3DCOLOR_XRGB(255, 255, 255), NULL, NULL, &texture);
        walkingAlternator++;
    }

    if(walkingAlternator >= 20)
    {
        walkingAlternator = 1;
    }
}

void walkingRight()
{
    if(walkingAlternator == 1 || walkingAlternator == 2 || walkingAlternator == 3 || walkingAlternator == 4 || walkingAlternator == 5 
        || walkingAlternator == 6 || walkingAlternator == 7 || walkingAlternator == 8 || walkingAlternator == 9 || walkingAlternator == 10)
    {
        D3DXCreateTextureFromFileEx(d3dDevice, "Characters/female_shopper4.png", D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2, 0, 0, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT,
        D3DX_DEFAULT, D3DX_DEFAULT, D3DCOLOR_XRGB(255, 255, 255), NULL, NULL, &texture);
        walkingAlternator++;
    }
    else if(walkingAlternator == 11 || walkingAlternator == 12 || walkingAlternator == 13 || walkingAlternator == 14 || walkingAlternator == 15
        || walkingAlternator == 16 || walkingAlternator == 17 || walkingAlternator == 18 || walkingAlternator == 19 || walkingAlternator == 20)
    {
        D3DXCreateTextureFromFileEx(d3dDevice, "Characters/female_shopper5.png", D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2, 0, 0, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT,
        D3DX_DEFAULT, D3DX_DEFAULT, D3DCOLOR_XRGB(255, 255, 255), NULL, NULL, &texture);
        walkingAlternator++;
    }

    if(walkingAlternator >= 20)
    {
        walkingAlternator = 1;
    }
}

void checkInteractivity()
{
    GetCursorPos(&curPos);
    if (GetKeyState(VK_LBUTTON) & 0x80 &&                        
        curPos.x >= position.x && curPos.x <= position.x+64 &&   
        curPos.y >= position.y && curPos.y <= position.y+128)    
    {
        displayPlayerCard = true;
    }
    else
    {
        displayPlayerCard = false;
    }
}

D3DXVECTOR3 returnPosition()
{
    return position;
}

D3DXVECTOR3 returnPosition(bool returnCentreOfSprite)
{
    return position;
}

};

Here is the code for the main

#include "Headers.h."
#include "Customer.h"
#include "Background.h"
#include "Counter.h"
#include "GameStations.h"
#include "ConsoleCab.h"
#include "ClothesStand.h"
#include "GamePanel.h"

    std::vector<Customer*> customers;

Background background;
Counter counter;
GameStations gameStations;
ConsoleCab consoleCab;
ClothesStand clothesStand;
GamePanel gamePanel;

void initDirectX(HWND hWnd);       // Initializes Direct3D Graphics
void render();                     // Render graphics
void cleanUp();                    // Cleans everything up and releases memory

LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    HWND hWnd;                                          // The handle to the window function
    WNDCLASSEX window;                                  // Pointer to window struct
    ZeroMemory(&window, sizeof(WNDCLASSEX));            // Clears window class so we can use it
    window.cbSize = sizeof(WNDCLASSEX);                 // Size of window
    window.style = CS_HREDRAW | CS_VREDRAW;             // Redraws the entire window if a movement or size adjustment changes the height of the client area. 
    window.lpfnWndProc = WindowProc;                    // Pointer to the window procedure
    window.hInstance = hInstance;                       // Handle to current instance
    window.hCursor = LoadCursor(NULL, IDC_ARROW);       // We'll stick with the normal cursor here
    window.lpszClassName = "Window";                    // Gives the class a name
    RegisterClassEx(&window);                           // Registers the window class 

    hWnd = CreateWindowEx(NULL,
        "Window",                     // Name of the class
        "Space Game",                 // Title of the window
        WS_EX_TOPMOST | WS_POPUP,     // Fullscreen
        0, 0,                         // Position of window (0,0 for fullscreen)
        SCREEN_WIDTH, SCREEN_HEIGHT,  // Screen resolution (Uses global declaration)
        NULL,                         // Parent window (None)
        NULL,                         // Menus (None)
        hInstance,                    // Application handle
        NULL);                        // Set to NULL as we aren't using more than 1 window

    ShowWindow(hWnd, nCmdShow);                         // Display window
    initDirectX(hWnd);                                  // Initialises the directX graphics
    MSG msg = {0};                                      // msg holds the Windows events message queue

    customers.push_back(new Customer());

    for (std::vector<Customer*>::iterator customerIT = customers.begin(); customerIT != customers.end(); customerIT++)
    {
         (*customerIT)->loadGraphics();
    } // Object properties become invalid here.

    background.loadGraphics();
    counter.loadGraphics();
    gameStations.loadGraphics();
    consoleCab.loadGraphics();
    clothesStand.loadGraphics();
    gamePanel.loadGraphics();

    /************************************** Main game loop *************************************************/

    while(TRUE)                                         // Main game loop
    {
        if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))     // If messages are waiting
        {
            TranslateMessage(&msg);                      // Translates the keystroke messages into the correct format
            DispatchMessage(&msg);                       // Sends message to the windowsProc function
            if(msg.message == WM_QUIT)                   // If the message was a quit message
                break;                                   // Breaks out of main game loop
        }
        else                  
        {

        for (std::vector<Customer*>::iterator customerIT = customers.begin(); customerIT != customers.end(); customerIT++)
        {
            (*customerIT)->checkInteractivity();
            (*customerIT)->move();
        }

            gamePanel.hoverDetection();
            render();
        }
    }

    /*******************************************************************************************************/

    // We are out of the main game loop (Due to a WM_QUIT signal)
    cleanUp();                                          // Do some housekeeping before quitting
    return msg.wParam;                                  // Return the WM_QUIT message to Windows. End of program
}

LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch(message)                                     // Sorts through messages
    {
    case WM_DESTROY:                                // When window has been closed
        {
            PostQuitMessage(0);                     // Closes the application
            return 0;  
        } 
        break;
    }
    return DefWindowProc (hWnd,                         // Returns any messages the switch statement didn't pick up
        message,
        wParam,
        lParam);
}

void initDirectX(HWND hWnd)
{
    d3d = Direct3DCreate9(D3D_SDK_VERSION);              // Create DirectX9 interface
    D3DPRESENT_PARAMETERS d3dParameters;                 // Pointer to DirectX9 parameters

    ZeroMemory(&d3dParameters, sizeof(d3dParameters));   // Clears the structure so we can use it
    d3dParameters.Windowed = FALSE;                      // Fullscreen
    d3dParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;    // Get rid of old framess
    d3dParameters.hDeviceWindow = hWnd;                  // Sets the window to be used by Direct3D
    d3dParameters.BackBufferFormat = D3DFMT_X8R8G8B8;    // Sets the back buffer format to 32-bit
    d3dParameters.BackBufferWidth = SCREEN_WIDTH;        // Sets the width of the buffer
    d3dParameters.BackBufferHeight = SCREEN_HEIGHT;      // Sets the height of the buffer

    d3d->CreateDevice(D3DADAPTER_DEFAULT,                // Creates a device class
        D3DDEVTYPE_HAL,
        hWnd,
        D3DCREATE_SOFTWARE_VERTEXPROCESSING,
        &d3dParameters,
        &d3dDevice);

    D3DXCreateSprite(d3dDevice, &d3dSprite);
}

void render()
{
    d3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(10, 0, 32), 1.0f, 0);   // Clears the screen to a dark blue
    d3dDevice->BeginScene();                                                         // Begins Direct3D scene
    d3dSprite->Begin(D3DXSPRITE_ALPHABLEND);                                         // Begin sprite drawing

    background.draw();

    counter.draw();
    gameStations.draw();
    consoleCab.draw();
    clothesStand.draw();
    gamePanel.updateInformation(564.55, 800.56, 1034.54, "July");


    for (std::vector<Customer*>::iterator customerIT = customers.begin(); customerIT != customers.end(); customerIT++)
    {
        (*customerIT)->draw();
    }

    gamePanel.draw();

    d3dSprite->End();                                                                // End drawing
    d3dDevice->EndScene();                                                           // Ends the Direct3D scene
    d3dDevice->Present(NULL, NULL, NULL, NULL);                                      // Presents the Direct3D scene (Displays to screen)
}

void cleanUp()
{
    d3dDevice->Release();   // Closes the Direct3D device and releases memory
    d3d->Release();         // Closes Direct3D and releases memory
}

I apologise in advance if I have not explained something properly or missed something out. I am notoriously bad for trying to explain things! :/ Can anyone help me out? Beginning to think I should have stuck with XNA for this project and learnt about pointers and vectors a little more in depth later on... too late now though :(

Thanks

Chris
  • 191
  • 1
  • 13
  • Not really related to the question, but "Sprite", "Customer", "Animation" etc are all different (and mostly unrelated) concepts that don't all belong in the same class. And try to minimize your use of globals - you can't get fully around them if you're using the WinAPI directly, but this seems like a bit too many of them. – Cubic Feb 06 '13 at 22:48
  • Anyone else spotted anything? Tearing my hair out over this one! – Chris Feb 07 '13 at 13:03

1 Answers1

2

Vector stores elements by copying them. So, when you do vector.push_back(Customer()) you actually do the following:

  1. Create new Customer object.
  2. Copy it into the vector. Since you don't override assignment operator all members are copied by values, including D3D pointers.
  3. Destroy original Customer object. Destructor releases all the resources.

Step #3 is the problem because of now vector has a copy of an invalid object: all its resources were released. I'd bet this is the problem but your code doesn't define destructor of Customer (or you didn't paste it) so, I'm not that sure. But anyway, the design is very far from perfect.

What I may suggest is storing pointers to Customer. If my theory is correct this will help to run this particular code sample.

std::vector<Customer*> customers;
customers.push_back(new Customer());

Of course, you'll have to deal with releasing of the allocatied memory.

And by the way, start checking D3D calls result. Without this any debugging will be a nightmare (and it is already). My guess is that d3dSprite->Draw fails because of missed texture, you may start checking from there.

Another problem is in loadGraphics method. This code:

D3DXVECTOR3 position(100.0f, 100.0f, 0.0f);
D3DXVECTOR3 center(0.0f, 0.0f, 0.0f);

Is probably supposed to set initial values to the object fields but in fact here you construct new local objects that get destroyed on exit. Fields Customer::position/Customer::center in fact left uninitialized. Then, in Draw method you use these uninitialized fields. Try fixing this and hope this will help.

real4x
  • 1,433
  • 12
  • 11
  • Hi, thank you for replying. You are absolutely correct. The destructor is being called shortly after the object is created. However, even with the changes you suggested, this still occurs. You're right about the design and lack of error checking too. Once I have this sorted, I need to spend some time putting in decent error checking. – Chris Feb 07 '13 at 20:31
  • Okay, so I am using a vector of pointers now but I still am seeing no change. When I put a breakpoint in the destructor of the Customer class, the program breaks almost instantly which tells me that the destructor is still being called when I put a new instance of Customer in to the vector. Can anyone think why? I am now checking all Direct3D calls and no errors are being thrown up. I am very confused. I have used Vectors before and never come across this. – Chris Feb 10 '13 at 13:45
  • If you show the new code we will figure this out. At least there is a progress: you know that destructor is called when it's not expected. – real4x Feb 11 '13 at 03:21
  • Thanks, I have updated the code in my original post. The change has been in the main where you can see I am creating a vector of pointers instead and then using push_back to put a new instance of Customer in to the vector, as per your suggestion. Also, I am putting the HRESULT returns from the direct3D calls in to a text file and each one is called successfully. No errors at all. – Chris Feb 11 '13 at 10:04
  • Well, to say the trurh I don't see how destructor can be called. Did you try to step out from the breakpoint and see where the destructor is called from? – real4x Feb 11 '13 at 19:25
  • I'm a little confused. When I put some code in the desctructor to write to a line to a text file, this doesn't get written but I put a break point in and it breaks out of the program. I wish I could step out and see where it is coming from but this is a fullscreen application and I do not have two screens. I experimented earlier and created a single pointer instance of Customer and this behaved the same. Is there perhaps another form of container I could use instead of a Vector that may get around this? Sorry to keep going on - I have never been stumped by something like this b4! @real4x – Chris Feb 12 '13 at 23:23
  • I don't think this time problem is in the container. It's somewhere in Customer class or its usage. Try swicthing to windowed mode and debugging all the process step-by-step. IMO just `d3dParameters.Windowed = TRUE` should be enough for this purpose. – real4x Feb 13 '13 at 18:40
  • Sorry for the delay. I have been away for a number of days but I am back now. You were right, it is not running the destructor. For some reason, my breakpoint was breaking elsewhere and not in the destructor (odd). I have stepped through the code. Everything gets run just fine. I have checked out the parameters in the draw() function and all are valid. I was hoping to see something glaringly obvious. Racking my brain but coming up with nothing still. I take it that I would hear about it if it was an error occurring in Direct3D? @real4x – Chris Feb 18 '13 at 21:58
  • I have been stepping through with a debugger and found that some of my pointers are invalid. For example, LPDIRECT3DTEXTURE9 texture, playerInfoCard and some other properties become invalid as soon as the loop which loads the graphics in to each object within the vector is exited. I am guessing that once the loop has finished, the pointer to my object goes out of scope and gets deleted automatically. I have edited the original post so that all the code is there. – Chris Feb 21 '13 at 17:42
  • Thank you @real4x. You were right, I had failed to correctly initialise those variables which was causing the problem. I feel a bit silly for not noticing it to be honest! :/ Thanks for your help. Much appreciated. – Chris Feb 28 '13 at 16:39