pbivens67 said:
class GameObject { public: float x; float y; float Position; float Size;
What is a GameObject?
Something supposed to be anything?
Why does it have x and y, but also a one dimensional position? And a one dimensional size?
Why not just x, y, width and height, as you were using all the time before?
That's 2D position and 2D size then, which is what you need.
But as said before, the ideal data for a (axis aligned) rectangle is to define two corners:
topLeftX, topLeftY, and bottomRightX, bottomRightY.
It's better because then you don't need additions for an overlap test.
And instead those clumsy names we should just call it:
minX, minY, maxX, maxY.
That's shorter to type and is clear about math and meaning. It does not need a convention about left = decreasing coordinate and right = increasing coordinate, or vice versa, adding the same confusion about top and bottom.
So if you are willing to change your habits about rectangles, use min/max corners.
But not that nonsense from the quote.
pbivens67 said:
bool CheckCollision(GameObject &one, GameObject &two) // AABB - AABB collision
This would make sense for a global function, as said some posts before.
But currently you have it as a member function, so you can use the current instance for the ‘first’ box, and you need to give only the ‘second’ box as parameter.
Your function works technically, but since you don't use the current instance of the GameObject, it's just bad code.
To fix it, we have several options:
class GameObject
{
public:
vec2 Position;
vec2 Size;
bool CheckCollision(GameObject &two) // AABB - AABB collision
{
bool collisionX = Position.x + Size.x >= two.Position.x &&
two.Position.x + two.Size.x >= Position.x;
bool collisionY = Position.y + Size.y >= two.Position.y &&
two.Position.y + two.Size.y >= Position.y;
return collisionX && collisionY;
}
};
I have removed x and y, and made pos and size 2D vectors.
But you don't have a 2D vector class. So i wonder why you seek for related code examples, pasting them in, although we gave examples avoiding a need for a 2D vector class.
Using such vec2 class would be a good idea, as said before, but i assume you do not yet and just want to make some Breakout Bricks or Space Invaders enemies first, which is fine.
But that's another topic. Let's focus on the ‘current instance’ and ‘global function vs. member function’ confusion for now.
Maybe it helps if we use the ‘this pointer', which is a C++ language feature:
class GameObject
{
public:
vec2 Position;
vec2 Size;
bool CheckCollision(GameObject &two) // AABB - AABB collision
{
bool collisionX = this->Position.x + this->Size.x >= two.Position.x &&
two.Position.x + two.Size.x >= this->Position.x;
bool collisionY = this->Position.y + this->Size.y >= two.Position.y &&
two.Position.y + two.Size.y >= this->Position.y;
return collisionX && collisionY;
}
};
‘this’ always gives the pointer to the current class instance in member methods.
So instead using ‘one’, i have now replaced that with 'this', and we access the data of the current object.
The result is the exact same as with the code snippet above. We do not need to write ‘this→’ each time to access member variables. But we can, if we like.
Though, the real reason why 'this' exists is something else:
class foo
{
float value;
void SetValue (float value)
{
this->value = value;
}
};
In this example the parameter of the member function has the same name as the m,ember variable.
Here we must use ‘this→’ to tell the compiler we mean the member variable, not the given function parameter.
Nothing of this is important, but maybe it helps.
Another option to fix your function would be this, in case you really want to give both boxes as parameter, but you don't want it to be a global function out of the class:
class GameObject
{
public:
float Position;
float Size;
static bool CheckCollision(GameObject &one, GameObject &two) // AABB - AABB collision
{
// collision x-axis?
bool collisionX = one.Position.x + one.Size.x >= two.Position.x &&
two.Position.x + two.Size.x >= one.Position.x;
// collision y-axis?
bool collisionY = one.Position.y + one.Size.y >= two.Position.y &&
two.Position.y + two.Size.y >= one.Position.y;
// collision only if on both axes
return collisionX && collisionY;
}
};
I made it a static function.
This way the function has no access to member variables, and does not refer to any instance of some GameObject at all.
We can call it like that:
GameObject enemy, projectile;
bool overlap = GameObject::CheckCollision(enemy, projectile);
It's the same as a global function, just we have it inside some class, eventually to keep things organized.
Finally, also the example of a global function again, just to be complete:
class GameObject
{
public:
float Position;
float Size;
};
bool CheckCollision(GameObject &one, GameObject &two) // AABB - AABB collision
{
// collision x-axis?
bool collisionX = one.Position.x + one.Size.x >= two.Position.x &&
two.Position.x + two.Size.x >= one.Position.x;
// collision y-axis?
bool collisionY = one.Position.y + one.Size.y >= two.Position.y &&
two.Position.y + two.Size.y >= one.Position.y;
// collision only if on both axes
return collisionX && collisionY;
};
To use it, we no longer need to add ‘GameObject::’ to access the function, since it's now global:
GameObject enemy, projectile;
bool overlap = CheckCollision(enemy, projectile);
Do you understand all this?
No?
Fine. Because it does not matter at all for now. Nobody cares.
Just make something work using some rectangles!
Try to do something with those structs or classes. And if it does not work, post code and we'll help.
We gave examples about collision tests and box classes weeks ago already in another thread.
Now the same here, again.
Stick at something instead constantly starting from scratch!