Reputation: 333
I think this is best explained with some pseudo-code:
std::vector<Yes> objs;
//The Yes Class constructor: Yes(x,y)
//Let's imagine I instantiated this vector with one object somewhere appropriately
void inSomeFunction()
{
for(int i = 0; i < 20; ++i)
{
int randX = rand() % mapWidth;
int randY = rand() % mapHeight;
for(int j = 0; j < objs.size(); ++j)
{
if(randX > x + threshold, for all objects in my vector && randY > y + threshold, for all objects in my vector)
{
objs.push_back(Yes(randX,randY));
}
}
}
}
So I have a window, whose dimensions are mapWidth and mapHeight and I am basically just trying to make 20 objects that do not overlap one another in the xy-plane.
I also want to make sure the randX and randY is not overlapping but also some threshold distance away from all the other existing objects. So let's say my threshold = 20, then I want to make sure that randX and randY is not contained with the circle of radius 20 surrounding any/all existing object(s) in the vector.
Example for clarity: first Yes object is at (x,y) = (10,20) and my threshold = 20, I want to create a second object, taking randX and randY as parameters, and push it into my vector; however, I want to make sure that the point (randX,randY) doesn't lie in the circle of radius 20 and centered at (10,20) which is the coordinates of my first object. The program can either generate another random (x,y) or just generate randX and randY in a way to fit the conditions I want, but I need it to keep checking this for all the objects in my vector as I create more objects.
I want to know how to accomplish this? Also for more clarity, it's for a game. I'm trying to generate multiple buildings in a 2D map, but I obviously don't want them to overlap or be close to each other. How would I go about accomplishing this?
Upvotes: 1
Views: 183
Reputation: 66371
I would break this down into smaller functions.
Something like this:
bool overlaps(const Yes& thing, int x, int y)
{
// See if (x, y) overlaps 'thing' in whichever way is appropriate.
}
bool overlaps_any(const std::vector<Yes>& things, int x, int y)
{
for (const Yes& thing : things)
{
if (overlaps(thing, x, y))
{
return true;
}
}
return false;
}
void inSomeFunction(std::vector<Yes>& objs)
{
for(int i = 0; i < 20; ++i)
{
int x = 0;
int y = 0;
do {
x = rand() % mapWidth;
y = rand() % mapHeight;
} while (overlaps_any(objs, x, y));
objs.push_back(Yes(x,y));
}
}
There are possibly more efficient ways, but since you only generate a map once, I wouldn't worry about efficiency at the moment.
Upvotes: 1
Reputation: 4873
I'm going to go out on a limb here based off what I'm reading. May not be the best way, but it is simple. Without fully knowing your project, it's hard to say. But if you gave us your full project, we'd tell you to shorten down like you have already done. So, I would assume you're going to get speculative answers at best on this one.
Nonetheless, an idea:
Create a 2D Boolean array of the max-x and max-y you can have. For each object, it will take x, y space in that array by setting the values to true. You can then check if something is too close, or if it's already in use by scanning so far from the given random value.
Upvotes: 0
Reputation: 3995
This is how to iterate through a vector. You can yourself compare the elements to values you wish.
std::vector<Object> objs;
void inSomeFunction()
{
for (int i = 0; i < 20; ++i)
{
int randX = rand() % mapWidth;
int randY = rand() % mapHeight;
for (std::vector<Object>::iterator itrObj = objs.begin(); itrObj != objs.end(); ++itrObj)
{
//Here you can access with operator -> the members of the class
//itrObj->x
//Or
//(*itrObj).x
//This is how you iterate through a std::vector<T>
//
//Do stuff with the values here
//
//If you do not wish to change the members
//of the class Object stored in this vector and only compare them
//use a const_iterator instead of iterator
}
}
This is a way to check if it is within range:
struct Window
{
Window (int x, int y, int width, int height)
: x(x)
, y(y)
, width(width)
, height(height)
{}
int x;
int y;
int width;
int height;
};
struct Position
{
Position (int x, int y)
: x(x)
, y(y)
{}
int x;
int y;
};
bool IsWithinRange (const Window &Range, const Position &Check)
{
int r_x = Range.x,
r_y = Range.y,
r_width = Range.width,
r_height = Range.height,
r_max_x = r_width + r_x,
r_max_y = r_height + r_y;
if (Check.x >= r_x && Check.x <= r_max_x)
if (Check.y >= r_y && Check.y <= r_max_y)
return true;
return false;
}
I'm not sure how your Object class is structured, but I'm sure you can do minor adjustments.
Upvotes: 0