Question About std::vector

Started by
11 comments, last by Dasil 14 years, 10 months ago
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.
Advertisement
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?
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).
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.
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.
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.
.
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.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

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?
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);	// ...}

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

So, do the camera's x and y values stay the same throughout the game or do they change?

This topic is closed to new replies.

Advertisement