🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

initializing an instance field of a vector

Started by
1 comment, last by Alberth 4 years ago

well I am using a vector to resolve collision detection with multiple objects, I am having some problems initializing the instance fields in my code. I have googled “initializing instance fields using c++” but have got little input, I know this is a simple question but I would some clarification on it. my code compiles just fine. I am trying to implement collision detection on vertical side scroller which has multiple sprites to shoot at. this is just some stubbed out code in c++.

#include <iostream>
#include <vector>

using namespace std;

class Brick
{
public:
	float x;
	float y;
	float brick_x;
	float brick_y;
	float brickWidth;
	float brickHeight;
	bool TestCollision(float x, float y)
	{
		if (x > brick_x && x<brick_x + brickWidth && y>brick_y && y < brick_y + brickHeight)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
};

class BrickLayer
{
public:
	vector <Brick> bricks;
	BrickLayer(vector<Brick> bricks)
	{
		/*intialize instance fields*/
	}
	bool TestCollision(float x, float y)
	{
		for (auto& brick : bricks)
		{
			if (brick.TestCollision(x, y))
			{
				return true;
			}
			else
			{
				return false;
			}
		}
	}
};

int main()
{



	system("pause");
	return 0;
} 
Advertisement

Instance fields are nothing special, they are just variables within the object that you can assign, for example in the constructor. For example:

Brick(float x, float y, float width, float height) {
// Not sure why you have x and y data members as well, they don't seem used.
   brick_x = x;
   brick_y = y;
   brickWidth = width;
   brickHeight = height;
}

The usual tactic to initialize data members though is during construction of the members themselves:

Brick(float x, float y, float width, float height)
    : brick_x(x), brick_y(y), brickWidth(width), brickHeight(height)
{ }

The first thing that happens when you call a constructor is that the data members get initialized, and then the constructor code is executed. In the first solution, that means first all data members are assigned 0.0f, and then you initialize them from the parameter values. In the second solution, I initialize the members by copy constructor from the supplied parameters directly, and then there is not anything left to do in the actual code, so it's empty.

This works for anything with a copy-constructor, including your vector:

BrickLayer(const vector<Brick> &p_bricks) : bricks(p_bricks)
{ }

I made a change here in your parameter declaration. I pass the parameter in by const reference (notice the ‘const’ and the additional ‘&’). This saves creating an intermediate copy of the vector just before the call to the constructor.

Then like above, I initialize the ‘bricks’ variable by copying the parameter to the data member. For clarity I added a ‘p_’ prefix to the parameter, so it's easier to distinguish between the instance data member and the parameter, although this is not strictly needed.

Then inside main, you must make a BrickLayer object, passing in a vector of bricks. The simplest is an empty vector:

int main()
{
    vector<Brick> bricks;

    int hit_x = 11;
    int hit_y = 5;
    BrickLayer layer(bricks);
    
    cout << "hitting (" << hit_x << ", " << hit_y << ") -> "
         << layer.TestCollision(hit_x, hit_y) << endl;

    return 0;
}

Note that your collision test is flawed, it doesn't return a boolean value if there are no bricks. My compiler complained with

$ g++ -Wall x.cpp
x.cpp: In member function ‘bool BrickLayer::TestCollision(float, float)’:
x.cpp:52:2: warning: control reaches end of non-void function [-Wreturn-type]
   52 |  }
      |  ^

where line 52 is the closing curly brace of the function.

For a more interesting number of bricks in the vector, you can use all the vector tricks that exist in main to fill the vector, eg

    vector<Brick> bricks = { // Initialize the vector with some bricks.
        Brick(0, 0, 10, 10),
        Brick(10, 0, 20, 10),
    };
    
    bricks.emplace_back(50, 80, 20, 30); // Append another brick.

My example doesn't give the answer you expect. I'll leave it to you to find out why (it's a good exercise). Another nice problem to examine is if you assign ‘hit_x = 10’, which may also not do what you think.

This topic is closed to new replies.

Advertisement