Объект Sprite больше не рендерится, когда помещается в Vector

Создание небольшой 2D-игры с использованием Direct3D 9 и C ++. Я столкнулся с проблемой, которую не видел раньше. Игра основана на магазине, поэтому у меня есть класс покупателей. Я создал объект в игре, и он рендерится и ведет себя так, как я хочу на минуту. Я решил вместо этого поместить объект в Vector, потому что в какой-то момент мне понадобится их коллекция в любой момент. Однако моя проблема в том, что когда я помещаю объект в вектор, он больше не виден на экране!

Я не получаю ошибок. Я вывел все коды возврата из функций DirectX в тестовый файл, и ничего не вышло. Он работал нормально, его просто не видно на экране! Ничего не изменилось, кроме как поместить его в Вектор.

Я изменил Вектор на Вектор указателей, потому что мне сказали, что Вектор просто создает объект, копирует его и удаляет оригинал. Однако теперь может показаться, что мои указатели Direct3D становятся недействительными при использовании этого метода, довольно быстро. Я думаю, что знаю, что происходит не так, но не уверен в том, как лучше поступить.

Вот класс клиентов:

#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;
}

};

Вот код для основного

#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
}

Я заранее прошу прощения, если я что-то не объяснил должным образом или что-то упустил. Я заведомо плох за попытки объяснить вещи! :/ Может кто-нибудь мне помочь? Начинаю думать, что я должен был придерживаться XNA для этого проекта и узнать немного позже об указателях и векторах … но уже слишком поздно 🙁

Спасибо

0

Решение

Вектор хранит элементы, копируя их. Итак, когда вы делаете vector.push_back(Customer()) вы на самом деле делаете следующее:

  1. Создать новый объект Customer.
  2. копия это в вектор. Поскольку вы не переопределяете оператор присваивания, все члены копируются по значениям, включая указатели D3D.
  3. Уничтожить оригинальный объект Customer. Деструктор освобождает все ресурсы.

Шаг № 3 — проблема, потому что теперь у вектора есть копия недопустимого объекта: все его ресурсы были освобождены. Могу поспорить, что это проблема, но ваш код не определяет деструктор Customer (или вы его не вставляли), поэтому я не уверен. Но в любом случае дизайн очень далек от совершенства.

То, что я могу предложить, это хранение указатели Клиенту. Если моя теория верна, это поможет запустить этот конкретный пример кода.

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

Конечно, вам придется иметь дело с освобождением выделенной памяти.

И, кстати, начните проверять результат вызовов D3D. Без этого любая отладка станет кошмаром (и это уже). Я думаю, что d3dSprite->Draw не удается из-за пропущенной текстуры, вы можете начать проверку оттуда.

Еще одна проблема в loadGraphics метод. Этот код:

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

Возможно, предполагается установить начальные значения для полей объекта, но на самом деле здесь вы создаете новые локальные объекты, которые разрушаются при выходе. поля Customer::position/Customer::center фактически оставлен неинициализированным. Затем в Draw метод вы используете эти неинициализированные поля. Попробуйте исправить это и надеюсь, что это поможет.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]