diff --git a/src/break_out/model/Ball.java b/src/break_out/model/Ball.java index fc65d48..ff00243 100644 --- a/src/break_out/model/Ball.java +++ b/src/break_out/model/Ball.java @@ -2,7 +2,8 @@ package break_out.model; import break_out.Constants; -import java.awt.Color; +import java.awt.*; +import java.util.ArrayList; import java.util.Random; /** @@ -32,6 +33,11 @@ public class Ball implements IBall { */ private Color color = Constants.COLOR_COMPONENT; + /** + * The stone which has been hit by the ball + */ + private Stone hitStone = null; + /** * The constructor of a ball * The balls position and direction are initialized here. @@ -239,4 +245,128 @@ public class Ball implements IBall { this.direction.setDy(reflectionVector.getDy()); } + /** + * tests whether the ball touches any stone's hit box + * @param stones + * @return true if the ball touches a stone + */ + public boolean hitsStone(ArrayList stones) { + // ball as a Rectangle + Rectangle rectBall = new Rectangle((int) getPosition().getX(), (int) getPosition().getY(), Constants.BALL_DIAMETER, Constants.BALL_DIAMETER); + + // size of grid blocks + int blockWidth = Constants.SCREEN_WIDTH / Constants.SQUARES_X; + int blockHeight = Constants.SCREEN_HEIGHT / Constants.SQUARES_Y; + + // foreach stone in stones + for(Stone stone : stones) { + if(stone != null) { + // stone as a Rectangle based on view.Field + Rectangle rectStone = new Rectangle((int) stone.getPosition().getX()+1, (int) stone.getPosition().getY()+1, blockWidth-1, blockHeight-1); + + // if ball intersects with stone which is existent and visible + if(rectBall.intersects(rectStone) && stone.getColor() != null) { + // set stone and return true + hitStone = stone; + + // reflect ball + reflectOnStone(hitStone); + + return true; + } + } + } + return false; + } + + /** + * returns the stone which got hit, can be null + * @return + */ + public Stone getHitStone() { + return hitStone; + } + + /** + * Ball got hit by Stone stone + * @param stone hitbox mechanism of stone + */ + public void reflectOnStone(Stone stone) { + // reflection model based on view.Field rendering model + + // size of grid blocks + int blockWidth = Constants.SCREEN_WIDTH / Constants.SQUARES_X; + int blockHeight = Constants.SCREEN_HEIGHT / Constants.SQUARES_Y; + + // ball as a Rectangle + Rectangle rectBall = new Rectangle((int) getPosition().getX(), (int) getPosition().getY(), Constants.BALL_DIAMETER, Constants.BALL_DIAMETER); + + // stone as a Rectangle + Rectangle rectStone = new Rectangle((int) stone.getPosition().getX()+1, (int) stone.getPosition().getY()+1, blockWidth-1, blockHeight-1); + + // stones borders as Rectangle's + Rectangle topBorder = new Rectangle((int) stone.getPosition().getX(), (int) stone.getPosition().getY(), blockWidth, 1); + Rectangle bottomBorder = new Rectangle((int) stone.getPosition().getX(), (int) stone.getPosition().getY()+blockHeight, blockWidth, 1); + Rectangle leftBorder = new Rectangle((int) stone.getPosition().getX(), (int) stone.getPosition().getY(), 1, blockHeight); + Rectangle rightBorder = new Rectangle((int) stone.getPosition().getX()+blockWidth, (int) stone.getPosition().getY(), 1, blockHeight); + + //System.out.println(String.format("ball (%s, %s) stone (%s, %s)", getPosition().getX(), getPosition().getY(), stone.getPosition().getX(), stone.getPosition().getY())); + + // if stone intersects with any bounds + if(rectBall.intersects(rectStone.getBounds())) { + + // corner intersections + if((rectBall.intersects(leftBorder) || rectBall.intersects(rightBorder)) && (rectBall.intersects(topBorder) || rectBall.intersects(bottomBorder))) { + // intersections as Rectangle's + Rectangle intersTop = rectBall.intersection(topBorder); + Rectangle intersBottom = rectBall.intersection(bottomBorder); + Rectangle intersLeft = rectBall.intersection(leftBorder); + Rectangle intersRight = rectBall.intersection(rightBorder); + + // rectangles as area to determine corner + double areaIntersTop = intersTop.getHeight() * intersTop.getWidth(); + double areaIntersBottom = intersBottom.getHeight() * intersBottom.getWidth(); + double areaIntersLeft = intersLeft.getHeight() * intersLeft.getWidth(); + double areaIntersRight = intersRight.getHeight() * intersRight.getWidth(); + + //System.out.printf("ut, ub, ul, ur: %s %s %s %s\r\n", areaIntersTop, areaIntersBottom, areaIntersLeft, areaIntersRight); + + // top side + if(areaIntersTop > 0) { + // left|right border + if(areaIntersLeft > areaIntersTop || areaIntersRight > areaIntersTop) direction.setDx(-getDirection().getDx()); + + // top border + else direction.setDy(-getDirection().getDy()); + } + + // bottom side + if(areaIntersBottom > 0) { + // left|right border + if(areaIntersLeft > areaIntersBottom || areaIntersRight > areaIntersBottom) direction.setDx(-getDirection().getDx()); + + // bottom border + else direction.setDy(-getDirection().getDy()); + } + + // return; intersection already handled + return; + } + + // vertical bounds + if(rectBall.intersects(leftBorder) || rectBall.intersects(rightBorder)) { + //System.out.println("left|right border"); + direction.setDx(-getDirection().getDx()); + } + + // horizontal bounds + if(rectBall.intersects(topBorder) || rectBall.intersects(bottomBorder)) { + //System.out.println("top|bottom border"); + direction.setDy(-getDirection().getDy()); + } + + } + + } + } diff --git a/src/break_out/model/Level.java b/src/break_out/model/Level.java index e65d072..54edab2 100644 --- a/src/break_out/model/Level.java +++ b/src/break_out/model/Level.java @@ -152,6 +152,11 @@ public class Level extends Thread implements ILevel { getBall().newRandomColor(); } + // Call here the balls method for reacting on stones of the playground + if(getBall().hitsStone(getStones())) { + + } + // update paddles position getPaddleTop().updatePosition(getBall()); getPaddleBottom().updatePosition(getBall());