SFML community forums
Help => General => Topic started by: kintantee on February 08, 2012, 05:35:47 pm
-
Hi folks, I need your help with collision detection with my little sfml pong game.
First I can detect the collision with walls(window boundaries) however I can't do the same with rackets. I just don't get where the mistake is...
as a background information, my ball is a square.
fallowing lines belong to collision detection function. Firstly I'm trying to understand if ball is going left and did it hit the racket horizontally. Then I control if it's indeed hit the racket by checking the coordinate vertically.
int Ball::detectCollision(Racket &leftRacket, Racket &rightRacket)
{
sf::Vector2f bouncerPosition = geometry_.GetPosition();
sf::Vector2f leftRacketPosition = leftRacket.getRacketPosition();
sf::Vector2f rightRacketPosition = rightRacket.getRacketPosition();
float racketWidth = leftRacket.getRacketWidth();
float racketHeight = leftRacket.getRacketHeight();
if(bouncerPosition.x <= leftRacketPosition.x + racketWidth && velocity_.x < 0.0f)
{
if(bouncerPosition.y + ballHeight_ >= leftRacketPosition.y && bouncerPosition.y <= leftRacketPosition.y + racketHeight)
{
return COLLIDING_WITH_LEFT_PADDLE;
}
}
else if(bouncerPosition.x + ballWidth_ >= rightRacketPosition.x && velocity_.x > 0.0f)
{
if(bouncerPosition.y + ballHeight_ >= rightRacketPosition.y && bouncerPosition.y <= rightRacketPosition.y + racketHeight)
{
return COLLIDING_WITH_RIGHT_PADDLE;
}
}
else
{
return NO_COLLISION;
}
}
and here is my process function for collision. In essence, what I'm trying to do is firstly changing the x velocity and then altering the ball position for possible infinite strucks in paddle.
void Ball::processCollision(const int collisionInformation, Racket &leftRacket, Racket &rightRacket)
{
sf::Vector2f bouncerPosition = geometry_.GetPosition();
sf::Vector2f leftRacketPosition = leftRacket.getRacketPosition();
sf::Vector2f rightRacketPosition = rightRacket.getRacketPosition();
float racketWidth = leftRacket.getRacketWidth();
float fraction = 0.0f;
if(collisionInformation == COLLIDING_WITH_LEFT_PADDLE)
{
velocity_.x = -velocity_.x;
fraction = -(bouncerPosition.x - leftRacketPosition.x + racketWidth);
bouncerPosition.x += fraction;
geometry_.SetPosition(bouncerPosition);
}
else if(collisionInformation == COLLIDING_WITH_RIGHT_PADDLE)
{
velocity_.x = -velocity_.x;
fraction = -(bouncerPosition.x + ballWidth_ - leftRacketPosition.x);
bouncerPosition.x += fraction;
geometry_.SetPosition(bouncerPosition);
}
}
and enumartion for collision types:
enum COLLISION_INFORMATION
{
NO_COLLISION,
COLLIDING_WITH_UPPER_WALL,
COLLIDING_WITH_LOWER_WALL,
COLLIDING_WITH_LEFT_WALL,
COLLIDING_WITH_RIGHT_WALL,
COLLIDING_WITH_LEFT_PADDLE,
COLLIDING_WITH_RIGHT_PADDLE
};
Finally my driving code in the main game loop:
bouncer.calculateDisplacement(deltaTime);
if(collidingEdge = bouncer.detectCollision(leftRacket, rightRacket))
{
bouncer.processCollision(collidingEdge, leftRacket, rightRacket);
bouncer.accelerate();
}
else
{
bouncer.bounce();
bouncer.tailAnimation();
}
}
Thank you in advance!
-
I just don't get where the mistake is...
What exactly is going wrong? Does the ball go too far?
I think your fraction is wrong with the left panel. I think you have to add racketWidth instead of subtracting it.
fraction = leftRacketPosition.x + racketWidth - bouncerPosition.x;
Why are you adding 1 when colliding with the left paddle? You don't substract 1 when colliding with the right paddle.
-
What exactly is going wrong? Does the ball go too far?
It's not detecting the paddles
I think your fraction is wrong with the left panel. I think you have to add racketWidth instead of subtracting it.
fraction = leftRacketPosition.x + racketWidth - bouncerPosition.x;
What I'm trying to acheieve there is that getting the fraction that is inside the racket. Since my ball is a square I'm extracting the left side of ball(assuming it's inside or atleast at the same coordinate) from the right side of the racket which is leftRacketPosition.x + racketWidth
something like this :
(http://s19.postimage.org/6073d76xf/collision.png)
Why are you adding 1 when colliding with the left paddle? You don't substract 1 when colliding with the right paddle.
that was an experiment and didn't work. I'll fix it
-
I still think that your formula is wrong. Lets just use numbers as an example.
leftRacketPosition.x = 10
bouncerPosition.x = 12
racketWidth = 5
If I understand it correctly then the fraction would have to be 3.
You are doing 12 - 10 + 5 = 7 (bouncerPosition.x - leftRacketPosition.x + racketWidth)
My code does 10 + 5 - 12 = 3 (leftRacketPosition.x + racketWidth - bouncerPosition.x)
-
I still think that your formula is wrong. Lets just use numbers as an example.
leftRacketPosition.x = 10
bouncerPosition.x = 12
racketWidth = 5
If I understand it correctly then the fraction would have to be 3.
You are doing 12 - 10 + 5 = 7 (bouncerPosition.x - leftRacketPosition.x + racketWidth)
My code does 10 + 5 - 12 = 3 (leftRacketPosition.x + racketWidth - bouncerPosition.x)
I think I should put paranteses:
like fallowing:
-(12 - (10 + 5)) = 3
however, the major problem is I can not detect collision.
-
It's not detecting the paddles
Sorry, I misunderstood your sentence. I thought you meant that the problem did not lie with detecting the paddles.
the major problem is I can not detect collision.
You should be able to locate the problem a little better.
Debug your program: Is the detectCollision function returning NO_COLLISION? If so then check the values of the variables while performing the check.
-
It's not detecting the paddles
Sorry, I misunderstood your sentence. I thought you meant that the problem did not lie with detecting the paddles.
the major problem is I can not detect collision.
You should be able to locate the problem a little better.
Debug your program: Is the detectCollision function returning NO_COLLISION? If so then check the values of the variables while performing the check.
It's only detecting the collision with right racket if vy < 0 and if it hits the upper side of the racket and vice versa for left racket : detects the collision if vy > 0 and if it hits the upper sides of the racket.
-
Hello,
I don't think it's a problem with parenteses :
with operators priority...
if((bouncerPosition.x <= (leftRacketPosition.x + racketWidth)) && (velocity_.x < 0.0f))
{
if(((bouncerPosition.y + ballHeight_) >= leftRacketPosition.y) && (bouncerPosition.y <= (leftRacketPosition.y + racketHeight)))
...that's good.
you should check collision with anticipation (look after next time if collision will be detected) because you maybe think the ball collide with a wall, but it's just that you say "stop" too late to your ball colliding with paddles :
if (velocity.x<0)//check leftPaddle
{
if (leftRacketPosition.x >= (bouncerPosition.x + velocity.x)) //the ball is going to be in the left paddleX area
{
if ((BouncerPosition.y>=LeftRacketPosition.y)
&& (bouncerPosition.y<=leftracketPosition.y+Height)) //the ball is going to be in the left PaddleY area
{
return COLLIDING_WITH_LEFT_PADDLE;
}
}
}
else//check RightRacket
{//etc...}
-
Okay guys I found the problem and thank you for your help!
The problem occured because of the shape of my ball which is square. I was comparing the top left y-coordinate of the ball(for both vy > 0 and vy <0), however, I should have compared like fallowing:
if(vy > 0)
compare lower-left corner(bouncerPosition.y + ballHeight_)
else if(vy < 0)
compare top-left corner(bouncerPosition.y)
here is my code for solution:
if(velocity_.x < 0.0f)
{
if(bouncerPosition.x <= leftRacketPosition.x + racketWidth)
{
if(velocity_.y < 0.0f)
{
if(bouncerPosition.y <= leftRacketPosition.y + racketHeight &&
bouncerPosition.y >= leftRacketPosition.y)
{
return COLLIDING_WITH_LEFT_PADDLE;
}
}
else
{
if(bouncerPosition.y + ballHeight_ >= leftRacketPosition.y &&
bouncerPosition.y + ballHeight_ <= leftRacketPosition.y + racketHeight)
{
return COLLIDING_WITH_LEFT_PADDLE;
}
}
}
}
else if(velocity_.x > 0.0f)
{
if(bouncerPosition.x + ballWidth_ >= rightRacketPosition.x)
{
if(velocity_.y < 0.0f)
{
if(bouncerPosition.y <= rightRacketPosition.y + racketHeight &&
bouncerPosition.y >= rightRacketPosition.y)
{
return COLLIDING_WITH_RIGHT_PADDLE;
}
}
else
{
if(bouncerPosition.y + ballHeight_ >= rightRacketPosition.y &&
bouncerPosition.y + ballHeight_ <= rightRacketPosition.y + racketHeight)
{
return COLLIDING_WITH_RIGHT_PADDLE;
}
}
}
}
Thank you again!
-
Just a suggestion, but if you used sf::Rect's instead of vectors, you could reduce your code down to like 2 lines.
if(ballRect.Intersects(paddle1Rect) return PADDLE1HIT;
if(ballRect.Intersects(paddle2Rect) return PADDLE2HIT;