/* Copyright 2010, 2013 Christian Matt
*
* This file is part of PonkOut.
*
* PonkOut is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PonkOut is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PonkOut. If not, see <http://www.gnu.org/licenses/>.
*/
package ponkOut.logic;
import org.lwjgl.util.vector.Vector2f;
import ponkOut.logic.Paddle.HemispherePlace;
public class PaddleHemisphereCollision extends Collision {
private Paddle paddle;
private Paddle.HemispherePlace hemispherePlace;
public PaddleHemisphereCollision(float time, Ball ball, Paddle paddle, HemispherePlace hemispherePlace) {
super(time, ball);
this.paddle = paddle;
this.hemispherePlace = hemispherePlace;
}
@Override
public void apply() {
if (!ball.isMovable()) {
// collision with WallBall - stop paddle
paddle.setVelocity(new Vector2f(0.0f, 0.0f));
// stop attached ball
if (paddle.isBallAttached()) {
GameBall attachedBall = paddle.getAttachedBall();
attachedBall.setVelocity(new Vector2f(0.0f, 0.0f));
}
} else { // ball is movable
Vector2f hemispherePos;
hemispherePos = paddle.getHemispherePosition(hemispherePlace);
// if paddle is not movable, reflect ball at hemisphere
if (!paddle.isMovable())
reflectAtBall(ball, hemispherePos);
else {
// ball and paddle are movable
// decompose the velocities of the balls into a component in the
// direction of the line between the balls (normal) and a
// perpendicular one (tangential)
Vector2f v1 = paddle.getVelocity();
Vector2f v2 = ball.getVelocity();
float m1 = paddle.getMass();
float m2 = ball.getMass();
Vector2f n = new Vector2f();
Vector2f.sub(ball.getPosition(), paddle.getHemispherePosition(hemispherePlace), n);
n.normalise();
Vector2f t = new Vector2f(n.y, -n.x);
float v1_n = Vector2f.dot(v1, n);
float v2_n = Vector2f.dot(v2, n);
float v2_t = Vector2f.dot(v2, t);
float u2_n;
if (v1_n * v2_n <= 0.0f || Math.abs(v1_n) < Math.abs(v2_n)) {
// directions are different or ball hits paddle
// reflect ball and add some momentum of paddle to ball
u2_n = 2.0f * m1 / (m1 + m2) * v1_n - v2_n;
// stop paddle if directions are different
if (v1_n * v2_n <= 0.0f)
paddle.setVelocity(new Vector2f(0.0f, 0.0f));
} else {
// directions are the same and paddle hits ball
// add some momentum of paddle to ball
u2_n = 2.0f * m1 / (m1 + m2) * v1_n + v2_n;
}
// tangential components are not changed
// transform to x- and y-components
Vector2f n2 = new Vector2f(n.x, n.y);
Vector2f t2 = new Vector2f(t.x, t.y);
Vector2f.add((Vector2f) n2.scale(u2_n), (Vector2f) t2.scale(v2_t), v2);
ball.setVelocity(v2);
}
// detach ball after collision
ball.detach();
}
// update ball's last paddle
if (paddle.isMovable()) {
ball.setLastPaddle(paddle);
}
}
}