Sign in to follow this  
RaduIulianGabriel

How to check for collision between objects from 2 classes

Recommended Posts

Hi. I keep getting this error when trying to check for collision between ball for Ball class and char1 or char2 from Player or Player2 class.

[code] 'char1' was not declared in this scope|[/code]
[code] 'char2' was not declared in this scope|[/code]


I found another topic about this and for that the answer was to make from 2 classes, one. I'm not sure I can do this in my case. And if I can how do I do that?

[url="http://www.gamedev.net/topic/600197-collision-between-objects-from-separate-classes-sdl/"]http://www.gamedev.n...te-classes-sdl/[/url]

I've attached the files and codeblocks project.

EDIT: I updated the wrong version of the archive. Download the new one. I've commented the section that is not working. Anyway I will add the Y axis collision and I'll try to add public functions. I hope it'll work, thx for help. I'll will ask you if I have more q.

Share this post


Link to post
Share on other sites
Wooh    1088
Player and Player2 can (and should) be one class. You can also make Ball the same class but maybe that is one step too far. At least all classes can share the same base class. I advice you to read up on the OOP concept. classes/inheritence/virtual functions and things like that. It is clear you have not fully grasped these concepts.

The error messages you post here is not from the code you have attached so I have no idea what you have tried to do. You already have a function to test collision between two SDL_Rects. The function doesn't work because it ignores the Y-axis. If Player and Ball was derived from the same base class, let's call it Object. That class could have a function to test for collisions (bool Object::collides(const Object& obj) const {...}). If you are not going to change your code to use inheritance you will have to make a way to access the SDL_Rect of other objects. You can add public functions to access the SDL_Rect that can then be used from outside the class to test for collisions.

I guess this post is a bit confusing if all this is new to you. Just ask if you have more questions and if something is not clear.

Share this post


Link to post
Share on other sites
Can you give me some indications of how to merge Player and Player2?And yes I suck at classes so how can I: "You can add public functions to access the SDL_Rect that can then be used from outside the class to test for collisions." ? Thx in advance for helping me

Share this post


Link to post
Share on other sites
BrianJensen    343
Easy to fix if you make your own collision detection function rather than using SDL_Rect.
F = First, S = Second, M = Max, X and Y are obvious.
[code]
bool check_collision(int FX, int FY, int FMX, int FMY, int SX, int SY, int SMX, int SMY)
{
if (FMX >= SX && FMX <= SMX && FMY >= SY && FMY <= SMY ||
FX >= SX && FX <= SMX && FMY >= SY && FMY <= SMY ||
FX >= SX && FX <= SMX && FY >= SY && FY <= SMY ||
FMX >= SX && FMX <= SMX && FY >= SY && FY <= SMY ||
FX <= SX && FMX >= SMX && FY >= SY && FY <= SMY ||
FX >= SX && FMX <= SMX && FY >= SY && FY <= SMY ||
FX >= SX && FMX <= SMX && FY <= SY && FMY <= SY ||
FX <= SX && FMX >= SMX && FY <= SY && FMY >= SY ||
FX <= SX && FMX >= SMX && FY >= SY && FY <= SMY ||
FMX >= SX && FMX <= SMX && FY <= SY && FMY <= SMY ||
FMX >= SX && FMX <= SMX && FY >= SY && FMY <= SMY ||
FX >= SX && FX <= SMX && FY >= SY && FMY <= SMY ||
FX == SX && FMX == SMX && FY == SY && FMY == SMY)
return true;
else
return false;
}[/code]
Haven't looked at the classes, but just put position variables like

[code]
int x, y, mx, my; //Don't even have to use mx or my if the dimensions are always the same.
[/code]
or if you already have that in somewhere else, use those. Didn't check the code to much.

Instead of
[code]if (check_collision(ball, char1))
//you would use
if (check_collision(ball.x, ball.y, ball.mx, ball.my, char1.x, char1.y, char1.mx, char1.my))[/code]
or however you have your classes set up, but that code snippet is exactly what I use for my 2d games

Share this post


Link to post
Share on other sites
[quote name='0Circle0' timestamp='1312834028' post='4846345']
Easy to fix if you make your own collision detection function rather than using SDL_Rect.
F = First, S = Second, M = Max, X and Y are obvious.
[code]
bool check_collision(int FX, int FY, int FMX, int FMY, int SX, int SY, int SMX, int SMY)
{
if (FMX >= SX && FMX <= SMX && FMY >= SY && FMY <= SMY ||
FX >= SX && FX <= SMX && FMY >= SY && FMY <= SMY ||
FX >= SX && FX <= SMX && FY >= SY && FY <= SMY ||
FMX >= SX && FMX <= SMX && FY >= SY && FY <= SMY ||
FX <= SX && FMX >= SMX && FY >= SY && FY <= SMY ||
FX >= SX && FMX <= SMX && FY >= SY && FY <= SMY ||
FX >= SX && FMX <= SMX && FY <= SY && FMY <= SY ||
FX <= SX && FMX >= SMX && FY <= SY && FMY >= SY ||
FX <= SX && FMX >= SMX && FY >= SY && FY <= SMY ||
FMX >= SX && FMX <= SMX && FY <= SY && FMY <= SMY ||
FMX >= SX && FMX <= SMX && FY >= SY && FMY <= SMY ||
FX >= SX && FX <= SMX && FY >= SY && FMY <= SMY ||
FX == SX && FMX == SMX && FY == SY && FMY == SMY)
return true;
else
return false;
}[/code]
Haven't looked at the classes, but just put position variables like

[code]
int x, y, mx, my; //Don't even have to use mx or my if the dimensions are always the same.
[/code]
or if you already have that in somewhere else, use those. Didn't check the code to much.

Instead of
[code]if (check_collision(ball, char1))
//you would use
if (check_collision(ball.x, ball.y, ball.mx, ball.my, char1.x, char1.y, char1.mx, char1.my))[/code]
or however you have your classes set up, but that code snippet is exactly what I use for my 2d games
[/quote]

The problem is still there. I can't access char1 from Player class because I'm not checking for collision in that class, I'm doing it in Ball class (in void Ball::move). And char1 is not a constant value so I can't put a number instead of that variable.

Share this post


Link to post
Share on other sites
BrianJensen    343
[code]
class Player
{
public:
...junk
private:
int x, y, mx, my;
...junk
}
class Ball
{
public:
...junk
private:
int x, y, mx, my;
...junk
}

//Player char1; // or even better
//Player char2; // or even better
Player char[2];
Ball ball;
[/code]

Share this post


Link to post
Share on other sites
So in Player class, I have SDL_Rect char1 and Player(), in Player() i have char1.x, char1.y , velocity and height + width. So when doing Player char1 I still cant acces de data from Player() - at least that's how i'm thinking


EDIT: Maybe you can update one of yours 2d games with collision between 2 object from 2 classes. I may adapt it to my code aswell.

Share this post


Link to post
Share on other sites
BrianJensen    343
get rid of SDL_Rect char1; junk you don't need it any more. Use int x, y, mx, my instead.

[code]
char[0].x = 10;
char[0].y = 50
ball.x = 75;
ball.y = 50;
[/code]
[code]
if (check_collide(char[0].x, char[0].y, char[0].x + SIZEOFCHAR1, char[0].y + SIZEOFCHAR1, ball.x, ball.y, ball.x + SIZEOFBALL, ball.y + SIZEOFBALL))
{
...junk
}
[/code]

EDIT: this is the code from 2 objects. I test between usually a Character class and more then 10 up to 100 other class objects.IE space invader remake, I test against Ship > AlienShip and Ship > bullet and Ship > Rock, Rock > Bullet and Bullet > AlienShip. Just using the code I provided and how I have the classes set up. Let me pull up my BASIC collide program where I actually tested and debugged the code.

This is just 2 objects
[code]
class cMoveBall
{
public:
int x, y, frame, xi, yi, nyi, pyi, nxi, pxi;
//...other junk not relevant to this example
};
class cMovePlayer
{
public:
int x, y, frame, xi, yi, nyi, pyi, nxi, pxi;
//...other junk not relevant to this example
};
cMoveBall Bounce[10];
cMovePlayer Player;
[/code]
then I assign Player x and y locations and use those to keep track of the player, their speed. and use that exact collision detection function in every 2d game I make for testing collision.
The function I provided doesn't care about objects, as long as you provide int variables in its parameters it will work.

DOUBLE EDIT: nvm

Share this post


Link to post
Share on other sites
[quote name='0Circle0' timestamp='1312837558' post='4846376']
get rid of SDL_Rect char1; junk you don't need it any more. Use int x, y, mx, my instead.

[code]
char[0].x = 10;
char[0].y = 50
ball.x = 75;
ball.y = 50;
[/code]
[code]
if (check_collide(char[0].x, char[0].y, char[0].x + SIZEOFCHAR1, char[0].y + SIZEOFCHAR1, ball.x, ball.y, ball.x + SIZEOFBALL, ball.y + SIZEOFBALL))
{
...junk
}
[/code]

EDIT: this is the code from 2 objects. I test between usually a Character class and more then 10 up to 100 other class objects.IE space invader remake, I test against Ship > AlienShip and Ship > bullet and Ship > Rock, Rock > Bullet and Bullet > AlienShip. Just using the code I provided and how I have the classes set up. Let me pull up my BASIC collide program where I actually tested and debugged the code.

This is just 2 objects
[code]
class cMoveBall
{
public:
int x, y, frame, xi, yi, nyi, pyi, nxi, pxi;
//...other junk not relevant to this example
};
class cMovePlayer
{
public:
int x, y, frame, xi, yi, nyi, pyi, nxi, pxi;
//...other junk not relevant to this example
};
cMoveBall Bounce[10];
cMovePlayer Player;
[/code]
then I assign Player x and y locations and use those to keep track of the player, their speed. and use that exact collision detection function in every 2d game I make for testing collision.
The function I provided doesn't care about objects, as long as you provide int variables in its parameters it will work.
[/quote]


I'm now realizing that my biggest mistake is using void Ball::move, I can either make a simple void move() function or I can type the collision code directly in main. I will start to rewrite my program but I will probably be off soon, so I'll post a reply tommorow. Thx for helping me, check back on this thread in 12 hours if I still have problems to fix.


EDIT: How can you use in the collide code variables from 2 classes but with same name? like first x is x and second x is x again?

Share this post


Link to post
Share on other sites
BrianJensen    343
[code]
Player player[2];
Ball ball;
[/code]
each player (player[0] and player[1] in this case) and ball are assigned its own x variable
and you call that variable x by
[code]
player[0].x, player[1].x, ball.x. //You can also do
player[0].x = player[1].x; // which puts player 0(char1) x location at player[1] (char2)s x location.
player[0].x = 50;
player[0].x += 2;
player[0].x++; //or any other way you can manipulate a int variable.
[/code]
If x is an int variable anywhere you could use an int variable you can put player[0].x, player[1].x, or ball.x( or any of that classes private int variables for that matter) as that variable as it is a valid form of int.
Also x for player[0] is not the same x variable for player[1] or ball, as they are each assigned their own variable called x when you create each class object
[code]
Player player[2]; //this class object player[0] and player[1] is given its own variable named x each
Ball ball;// this class object ball is given a variable named x as well
[/code]
Every variable you give a class object in the private: section is used by that object only, if you do
[code]Player player[1000];[/code] there are 1000 Player objects called player each with their own x variable.

Share this post


Link to post
Share on other sites
I ended up using a backup with my code, one with SDL_Rect's. I only moved the player-ball collision to the main function and guess what...it worked. Was a very simple solution. Now I'm wondering if I should use you're check_collision algorithm or this one. Anyway, thank you very much for helping me, I will add the game to this post when is ready in case any other amateur SDL programmer gets in trouble:)
[code]Player player1;

Player player2;

Ball myball;

[/code]



[code]if (check_collision(myball.ball, player1.char1))
{
if ((myball.xVel == - BALL_SPEED) && (myball.yVel == BALL_SPEED))
{
myball.xVel = BALL_SPEED;
myball.yVel = BALL_SPEED;
}
else if ((myball.xVel == - BALL_SPEED) && (myball.yVel == - BALL_SPEED))
{
myball.xVel = BALL_SPEED;
myball.yVel = - BALL_SPEED;
}
}
if (check_collision(myball.ball, player2.char2))
{
if ((myball.xVel == BALL_SPEED) && (myball.yVel == - BALL_SPEED))
{
myball.xVel = - BALL_SPEED;
myball.yVel = - BALL_SPEED;
}
else if ((myball.xVel == BALL_SPEED) && (myball.yVel == BALL_SPEED))
{
myball.xVel = - BALL_SPEED;
myball.yVel = BALL_SPEED;
}
}[/code]

Share this post


Link to post
Share on other sites
BrianJensen    343
Mine is optimized for objects of any size to be compared to other objects of any size where yours only checks if the 2nd object is smaller or equal to the 1st object. For your game it may work, but not every game. Mine however works for any as it check every single possible collision no matter the size of the object.

By the way, the code you linked only changes the direction of the ball, it isn't the collision detection code

[code]
bool check_collision(SDL_Rect A, SDL_Rect B)
{
//Sides of rect
int leftA, leftB;
int rightA, rightB;

//Sides of rect A
leftA = A.x;
rightA = A.x + A.w;

//Sides of rect B
leftB = B.x;
rightB = B.x + B.w;

//If any of the sides from A are outside of B
if(rightA<=leftB)
{
return false;
}

if (rightB<=leftA)
{
return false;
}
//If none are outside
return true;
}
[/code]

That is the collision code.Which should look like this.
[code]
bool check_collision(SDL_Rect A, SDL_Rect B)
{
if (A.x + A.w <= B.x)
return false;
if (B.x + B.w <= A.x)
return false;
return true;
}
[/code]
or even shorter:
[code]
bool check_collision(SDL_Rect A, SDL_Rect B)
{
if (A.x + A.w <= B.x || B.x + B.w <= A.x)
return false; //Funny to return false on a collision detected
return true; //and true when there isn't one
}
[/code]
Note the comments
[code]
if (!check_collision(a, b)) //This says if check_collision == false, how you have it setup this would only
{ // execute if the statement were actually true as your function passes true when it is false.
...junk
}
[/code]
Once it is that short, no reason to even waste time with a function call. Also:
No reason to add more variables when you do not need them.I just finished checking over your code a bit, and it seems you initialize a lot of variables that you don't need. So many that it isn't feasible to mention them all here. I'll assume you're new to programming, and if so you're headed in the right direction, but you're just doing some things the hard/long way as you can see from the above example.

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