Sign in to follow this  
Dasil

Question About std::vector

Recommended Posts

Hi again, In my program, I have a GameObject class, and a Footman class that inheirits from it (class Footman : public GameObject). The footman gets created and displayed correctly, and if I use the new footman without adding it to a vector, I can update his position using something like: footman.move(1.0f, 1.0f); which add 1.0 to his x and y positions (it's a 2D game). This works correctly, but if I try to add the footman to a std::vector<GameObject> and update his position: std::vector<GameObject> gameObjects; gameObjects.push_back(footman); gameObjects[0].move(1.0f, 1.0f); // footman is the only thing in gameObjects right now, so he is at position 0 nothing happens. He is created and displayed properly again, but he doesn't move. Is there a way that I can move the footman after he has been added to the vector? Any help would be appreciated.

Share this post


Link to post
Share on other sites
Does gameObject have a move function? I think for a footman stored in a gameObject container and have move called, GameObject has to have a virtual move function for it to work right. Can someone verify this?

Share this post


Link to post
Share on other sites
Store the proper type of object in the vector. You want either a vector of Footman, or a vector of GameObject*. Your current code, a vector of GameObject, will not work.

Remember, a vector copies its elements. If the element type is GameObject, as in your current code, the GameObject copy operations will be used. These copy operations do not know how to copy the part of the actual object that is a Footman, resulting in the objects contained in the vector not longer having the data members that are Footman specific. This is known as slicing.

Since it looks like you want to store anything derived from GameObject in this list and operate on it, you probably want GameObject*.

This may not be the cause of your actual problem, however, since it appears move() and the associated data members are probably GameObject members. You should provide more code. The code that renders the objects would be interesting, as well as the class definitions. It's possible that move() is doing the right thing but the renderer is now reading the wrong object (remember the thing in the vector is a copy).

Share this post


Link to post
Share on other sites
Quote:

Does gameObject have a move function? I think for a footman stored in a gameObject container and have move called, GameObject has to have a virtual move function for it to work right. Can someone verify this?

Dynamic dispatch can only occur through a pointer or reference in C++. The type in his vector is GameObject (not a pointer, not a reference), so in order to compile, GameObject must have a move() method. Whether or not it's virtual will probably not matter unless in the base class move() does nothing and it is in fact the Footman override of move() that does the work.

Share this post


Link to post
Share on other sites
Thanks for the replies.

In my original post, I wrote the inheiritance incorrectly. Footman inheirits from Unit which inheirits from GneObject.

GameObject.h:

class GameObject
{
public:
GameObject();
virtual ~GameObject();

void set(const Vec2 &pos, float w, float h, const Vec2 &vel);
float getWidth();
float getHeight();

void setWidth(float w);
void setHeight(float h);

float getX();
float getY();

Vec2 getPosition();
Vec2 getVelocity();
void move(float x, float y);
virtual void initializeTexture(LPCTSTR filename, float width, float height, int index);
virtual void draw(int frame);
virtual void setFrames();

bool selected();
void select();
void deselect();
LPD3DXSPRITE getSprite();

protected:
Vec2 mPosition;
Vec2 mVelocity;
float mWidth;
float mHeight;
bool mSelected;
LPD3DXSPRITE mSprite;
};

class Unit : public GameObject
{
public:
Unit();
virtual ~Unit();

void create(std::string name);

std::string getName();

protected:
std::string mName;
};

class Footman : public Unit
{
public:
Footman();
~Footman();

void initializeTexture(LPCTSTR filename, float width, float height, int index);
void draw(int frame);
void setFrames();

private:
LPDIRECT3DTEXTURE9 mTextures[1];
AnimationFrame mFrames[34];
};



The move function:

void GameObject::move(float x, float y)
{
mPosition.x += x;
mPosition.y += y;
}



The draw function:

void Footman::draw(int frame)
{
static int frameToDraw = 0;
static int frameNumber = 0;
RECT rect;
SetRect(&rect, mFrames[frameToDraw].mX, mFrames[frameToDraw].mY, mFrames[frameToDraw].mX2, mFrames[frameToDraw].mY2);

D3DXVECTOR3 center(0.0f, 0.0f, 0.0f), position(getPosition().x, getPosition().y, 0.0f);

mSprite->Begin(D3DXSPRITE_ALPHABLEND);
mSprite->Draw(mTextures[frame], &rect, &center, &position, D3DCOLOR_ARGB(255, 255, 255, 255));
mSprite->End();

frameNumber++;
if (frameNumber == 5)
{
frameToDraw++;
frameNumber = 0;
}

if (frameToDraw == 15)
{
frameToDraw = 1;
}
}




mFrames is an array of custom rectangles representing the area of the sprite sheet to draw.

I tried it with a vector<Footman>, but it still didn't work.

I need a vector because it is a 2D RTS, and right now I making the "camera move" by moving all of the objects a certain amount when the mouse is at the edge of the screen. I want to be able to just loop through the vector containing all objects and move them. Is there a different container that would be better in this situation.

I hope this makes sense, and I'll post more code if you need it.

Share this post


Link to post
Share on other sites
You should use std::vector<GameObject*> and store pointers to objects of type GameObject or anything derived from GameObject so that you get polymorphism working. By using std::vector<GameObject> you get object slicing.

Share this post


Link to post
Share on other sites
Quote:
Original post by Dasil
I need a vector because it is a 2D RTS, and right now I making the "camera move" by moving all of the objects a certain amount when the mouse is at the edge of the screen.
Really, really, do not do this. Instead, store a camera position somewhere, and subtract the camera position from each object position as you render.

This way your units remain in a fixed 'world coordinate' system, which makes pretty much everything simpler.

Share this post


Link to post
Share on other sites
Quote:
Really, really, do not do this. Instead, store a camera position somewhere, and subtract the camera position from each object position as you render.


Can you give an example (preferably with code) of this?

Share this post


Link to post
Share on other sites
Quote:
Original post by Dasil
Quote:
Really, really, do not do this. Instead, store a camera position somewhere, and subtract the camera position from each object position as you render.
Can you give an example (preferably with code) of this?
Here, directly from your render method:

struct Camera
{
float x, float y;
}

void Footman::draw(int frame, Camera &camera)
{
// ...
D3DXVECTOR3 position(getPosition().x - camera.x, getPosition().y - camera.y, 0.0f);
// ...
}

Share this post


Link to post
Share on other sites
I think I also need a vector so that when a new unit is trained, they are added to the vector so I can loop through and check to see which units are dead and other things. Is this right, or is there a better way to do this?

Also, is there a way to move the object in the vector?

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