1
0
Fork 0
uni_informatik_projekt/src/break_out/model/Ball.java

243 lines
7.0 KiB
Java

package break_out.model;
import break_out.Constants;
import java.awt.Color;
import java.util.Random;
/**
* This class contains the information about the balls characteristics and behavior
*
* @author iSchumacher; modified by Gruppe 175 (Moritz Henseleit, Ruben Meyer)
*/
public class Ball implements IBall {
/**
* The balls position on the playground
*/
private Position position;
/**
* The balls direction
*/
private Vector2D direction;
/**
* The balls hit state for paddles; custom implementation
*/
private boolean hitsPaddle;
/**
* The balls color with default component color
*/
private Color color = Constants.COLOR_COMPONENT;
/**
* The constructor of a ball
* The balls position and direction are initialized here.
*/
public Ball() {
this.position = new Position(0, 0);
this.direction = new Vector2D(Constants.BALL_SPEED, Constants.BALL_SPEED);
this.direction.rescale();
// start at bottom-center
this.position.setX((Constants.SCREEN_WIDTH - Constants.BALL_DIAMETER) / 2.0);
this.position.setY(Constants.SCREEN_HEIGHT - Constants.BALL_DIAMETER - Constants.PADDLE_HEIGHT);
}
/**
* The getter for the balls position
*
* @return position The balls current position
*/
public Position getPosition() {
return this.position;
}
/**
* The getter for the balls direction
*
* @return direction The balls current direction
*/
public Vector2D getDirection() {
return this.direction;
}
/**
* The getter for the balls color
*
* @return color The balls current color
*/
public Color getColor() { return this.color; }
/**
* The setter for the balls color
*
* @param color The balls new color
*/
public void setColor(Color color) { this.color = color; }
/**
* Creates new random color for the ball and sets it
*
* @see <a href="https://stackoverflow.com/a/4247219">Stackoverflow Answer 4247219</a>
*/
public void newRandomColor() {
Random random = new Random();
// random hue without blue colors to prevent ghosting
// 65 <~ 170/255
float hue = (random.nextInt(65)) / 100f;
// saturation between 0.5 and 0.7
float saturation = (random.nextInt(2000) + 5000) / 10000f;
float luminance = 0.9f;
Color randColor = Color.getHSBColor(hue, saturation, luminance);
setColor(randColor);
}
/**
* The getter for the balls hit state
*
* @return hitsPaddle The balls current hit state
*/
public boolean getHitState() { return this.hitsPaddle; }
/**
* The setter for the balls hit state
*
* @param state The balls new hit state
*/
public void setHitState(boolean state) { this.hitsPaddle = state; }
/**
* updates ball position
*/
public void updatePosition() {
// sets X position
this.position.setX(this.position.getX() + this.direction.getDx());
// sets Y position
this.position.setY(this.position.getY() + this.direction.getDy());
}
/**
* Ball reacts to contact with the borders
*/
public void reactOnBorder() {
// reacts on left border
if (this.position.getX() <= 0) {
this.position.setX(0);
this.direction.setDx(-(this.direction.getDx()));
}
// reacts on right border (-Diameter because of hitbox)
if (this.position.getX() >= Constants.SCREEN_WIDTH - Constants.BALL_DIAMETER) {
this.position.setX(Constants.SCREEN_WIDTH - Constants.BALL_DIAMETER);
this.direction.setDx(-(this.direction.getDx()));
}
// reacts on top border
if (this.position.getY() <= 0) {
this.position.setY(0);
this.direction.setDy(-(this.direction.getDy()));
}
// reacts on bottom border (+Diameter because of hitbox)
if (this.position.getY() >= Constants.SCREEN_HEIGHT - Constants.BALL_DIAMETER) {
this.position.setY(Constants.SCREEN_HEIGHT - Constants.BALL_DIAMETER);
this.direction.setDy(-(this.direction.getDy()));
}
}
/**
* tests whether the ball touches the paddle's hit box.
* @param paddle paddle which will be tested
* @return true when ball hits the paddle
*/
public boolean hitsPaddle(Paddle paddle) {
// paddles position
Position posPaddle = paddle.getPosition();
// balls position
Position posBall = this.getPosition();
// test balls y position against paddles y values
// paddles y values can be interpreted as a closed interval therefore if balls y position is in the interval, its true
boolean testPaddleY = (
posPaddle.getY() <= posBall.getY() && posBall.getY() <= posPaddle.getY()+paddle.getHeight() ||
posPaddle.getY() <= posBall.getY()+Constants.BALL_DIAMETER && posBall.getY()+Constants.BALL_DIAMETER <= posPaddle.getY()+paddle.getHeight()
);
// test balls x position against paddles x values
// paddles x values can be interpreted as a closed interval therefore if balls x position is in the interval, its true
boolean testPaddleX = (
posPaddle.getX() <= posBall.getX() && posBall.getX() <= posPaddle.getX()+paddle.getWidth() ||
posPaddle.getX() <= posBall.getX()+Constants.BALL_DIAMETER && posBall.getX()+Constants.BALL_DIAMETER <= posPaddle.getX()+paddle.getWidth()
);
// if balls y position is in paddles y values, verify x position
if(testPaddleY) {
// DEBUG OUTPUT
//System.out.println("ball is in y area of paddle: "+String.format("x, y, w, h: %s, %s, %s, %s", posPaddle.getX(), posPaddle.getY(), paddle.getWidth(), paddle.getHeight()));
// if ball is in paddles hit box
if(testPaddleX) {
// DEBUG OUTPUT
//System.out.println("ball hits paddle: "+String.format("x, y, w, h: %s, %s, %s, %s", posPaddle.getX(), posPaddle.getY(), paddle.getWidth(), paddle.getHeight()));
return true;
}
}
// default output, ball doesn't hit paddle
return false;
}
/**
* Ball got hit by Paddle paddle
* @param paddle hitbox mechanism of paddle
*/
public void reflectOnPaddle(Paddle paddle) {
// reflection point / offset point
Position reflectionPoint = new Position(
paddle.getPosition().getX() + (paddle.getWidth() / 2.0),
paddle.getPosition().getY() + (paddle.getHeight() / 2.0)
);
// new direction vector; assignment not here
Vector2D reflectionVector;
// no general solution, estimation required
// only two paddles defined in the game design, therefore greater or smaller than middle of screen
//deciding if the paddle is at the top or bottom to adjust if its +or- y direction
if (paddle.getPosition().getY() <= Constants.SCREEN_HEIGHT/2.0) {
// top paddle
reflectionPoint.setY(reflectionPoint.getY() - Constants.REFLECTION_OFFSET);
} else {
// bottom paddle
reflectionPoint.setY(reflectionPoint.getY() + Constants.REFLECTION_OFFSET);
}
// calculating the center of the ball; needed for correct vector calculation
Position ballCenter = new Position(
position.getX() + (Constants.BALL_DIAMETER/2.0),
position.getY() + (Constants.BALL_DIAMETER/2.0)
);
// The direction is set to the vector between offset point and the ball's center
reflectionVector = new Vector2D(reflectionPoint, ballCenter);
// normalize vector
reflectionVector.rescale();
// replace direction vector
this.direction.setDx(reflectionVector.getDx());
this.direction.setDy(reflectionVector.getDy());
}
}