340 lines
7.7 KiB
Java
340 lines
7.7 KiB
Java
package break_out.model;
|
|
|
|
|
|
import break_out.Constants;
|
|
import break_out.controller.JSONReader;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
/**
|
|
* This class contains information about the running game
|
|
*
|
|
* @author dmlux
|
|
* @author I. Schumacher; modified by Gruppe 175 (Moritz Henseleit, Ruben Meyer)
|
|
*/
|
|
public class Level extends Thread implements ILevel {
|
|
|
|
/**
|
|
* The game to which the level belongs
|
|
*/
|
|
private Game game;
|
|
|
|
/**
|
|
* The number of the level
|
|
*/
|
|
private int levelnr;
|
|
|
|
/**
|
|
* The score of the level
|
|
*/
|
|
private int score;
|
|
|
|
/**
|
|
* The ball of the level
|
|
*/
|
|
private Ball ball;
|
|
|
|
/**
|
|
* Flag that shows if the ball was started
|
|
*/
|
|
private boolean ballWasStarted = false;
|
|
|
|
/**
|
|
* Flag that shows if the level was finished
|
|
*/
|
|
private boolean finished = false;
|
|
|
|
/**
|
|
* The paddles of the level
|
|
*/
|
|
private Paddle paddleTop, paddleBottom;
|
|
|
|
/**
|
|
* The stones of the level
|
|
*/
|
|
private ArrayList<Stone> stones = new ArrayList<>();
|
|
|
|
/**
|
|
* The life counter of the level
|
|
*/
|
|
private int lifeCounter;
|
|
|
|
/**
|
|
* The constructor creates a new level object and needs the current game object,
|
|
* the number of the level to be created and the current score
|
|
*
|
|
* @param game The game object
|
|
* @param levelnr The number of the new level object
|
|
* @param score The score
|
|
*/
|
|
public Level(Game game, int levelnr, int score) {
|
|
this.game = game;
|
|
this.levelnr = levelnr;
|
|
this.score = score;
|
|
this.ball = new Ball();
|
|
|
|
resetPaddles();
|
|
|
|
// set paddles color
|
|
this.paddleTop.setColor(Constants.COLOR_PADDLE_TOP);
|
|
this.paddleBottom.setColor(Constants.COLOR_PADDLE_BOTTOM);
|
|
|
|
loadLevelData(levelnr);
|
|
}
|
|
|
|
/**
|
|
* The getter for the ball object
|
|
*
|
|
* @return ball The ball of the level
|
|
*/
|
|
public Ball getBall() {
|
|
return this.ball;
|
|
}
|
|
|
|
/**
|
|
* Sets ballWasStarted to true, the ball is moving
|
|
*/
|
|
public void startBall() {
|
|
ballWasStarted = true;
|
|
}
|
|
|
|
/**
|
|
* Sets ballWasStarted to false, the ball is stopped
|
|
*/
|
|
public void stopBall() {
|
|
ballWasStarted = false;
|
|
}
|
|
|
|
/**
|
|
* Returns if the ball is moving or stopped
|
|
*
|
|
* @return ballWasStarted True: the ball is moving; false: the ball is stopped
|
|
*/
|
|
public boolean ballWasStarted() {
|
|
return ballWasStarted;
|
|
}
|
|
|
|
/**
|
|
* The method of the level thread
|
|
*/
|
|
public void run() {
|
|
game.notifyObservers();
|
|
|
|
// endless loop
|
|
while (!finished) {
|
|
// if ballWasStarted is true, the ball is moving
|
|
if (ballWasStarted()) {
|
|
|
|
// Call here the balls method for updating his position on the playground
|
|
getBall().updatePosition();
|
|
|
|
// Call here the balls method for reacting on the borders of the playground
|
|
getBall().reactOnBorder();
|
|
|
|
// Call here the balls method for reacting on lost ball state
|
|
if(getBall().isLost()) {
|
|
decreaseLives();
|
|
}
|
|
|
|
// if ball hits paddle (top|bottom), reflect ball
|
|
if(getBall().hitsPaddle(paddleTop)) getBall().reflectOnPaddle(paddleTop);
|
|
if(getBall().hitsPaddle(paddleBottom)) getBall().reflectOnPaddle(paddleBottom);
|
|
if(getBall().hitsPaddle(paddleTop) || getBall().hitsPaddle(paddleBottom)) {
|
|
getBall().setHitState(true);
|
|
// DEBUG OUTPUT
|
|
//System.out.println(String.format("hitstate: %s, color: %s", this.ball.getHitState(), this.ball.getColor().getRGB()));
|
|
}
|
|
|
|
// if ball has hit a paddle set a new random color to it
|
|
else if(getBall().getHitState()) {
|
|
getBall().setHitState(false);
|
|
getBall().newRandomColor();
|
|
}
|
|
|
|
// Call here the balls method for reacting on stones of the playground
|
|
if(getBall().hitsStone(getStones())) {
|
|
updateStonesAndScore();
|
|
//System.out.println("count: "+stones.size());
|
|
}
|
|
|
|
// if all stones are broken, go to next level
|
|
if(allStonesBroken()) {
|
|
// next level
|
|
//System.out.println("next level");
|
|
}
|
|
|
|
// update paddles position
|
|
getPaddleTop().updatePosition(getBall());
|
|
getPaddleBottom().updatePosition(getBall());
|
|
|
|
|
|
// Tells the observer to repaint the components on the playground
|
|
game.notifyObservers();
|
|
|
|
}
|
|
// The thread pauses for a short time
|
|
try {
|
|
Thread.sleep(4);
|
|
} catch (InterruptedException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Loads the information for the level from a json-file located in the folder /res of the project
|
|
*
|
|
* @param levelnr The number X for the LevelX.json file
|
|
*/
|
|
private void loadLevelData(int levelnr) {
|
|
JSONReader reader = new JSONReader(String.format("res/Level%s.json", levelnr));
|
|
int[][] stoneTypes = reader.getStones2DArray();
|
|
|
|
// life counter
|
|
lifeCounter = reader.getLifeCounter();
|
|
|
|
// clear stones list, not needed but could cause problems when not done
|
|
stones.clear();
|
|
|
|
// foreach column
|
|
for(int y = 0; y < stoneTypes.length; y++) {
|
|
// foreach element in column x
|
|
for(int x = 0; x < stoneTypes[y].length; x++) {
|
|
Position tempPos = new Position(-1, -1);
|
|
// position calculation, equivalent to grid calculation in "view.Field"
|
|
|
|
// size of grid blocks
|
|
int blockWidth = Constants.SCREEN_WIDTH / Constants.SQUARES_X;
|
|
int blockHeight = Constants.SCREEN_HEIGHT / Constants.SQUARES_Y;
|
|
|
|
tempPos.setX(blockWidth * x);
|
|
tempPos.setY(blockHeight * y);
|
|
Stone tempStone = new Stone(stoneTypes[y][x], tempPos);
|
|
|
|
// add stone to list
|
|
if(tempStone.getType() != 0)
|
|
stones.add(tempStone);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The getter for the top paddle object
|
|
*
|
|
* @return paddleTop The top paddle of the level
|
|
*/
|
|
public Paddle getPaddleTop() {
|
|
return paddleTop;
|
|
}
|
|
|
|
/**
|
|
* The getter for the bottom paddle object
|
|
*
|
|
* @return paddleBottom The bottom paddle of the level
|
|
*/
|
|
public Paddle getPaddleBottom() {
|
|
return paddleBottom;
|
|
}
|
|
|
|
/**
|
|
* The setter for the levels game state
|
|
* @param finished game state
|
|
*/
|
|
public void setFinished(boolean finished) {
|
|
this.finished = finished;
|
|
}
|
|
|
|
/**
|
|
* The getter for the levels stones
|
|
* @return stones The stones of the level
|
|
*/
|
|
public ArrayList<Stone> getStones() {
|
|
// hacky workaround for ConcurrentModificationExceptions
|
|
ArrayList<Stone> copy = new ArrayList<>();
|
|
copy.addAll(stones);
|
|
return copy;
|
|
}
|
|
|
|
/**
|
|
* The updater for the levels stones and the player score
|
|
*/
|
|
private void updateStonesAndScore() {
|
|
// hit stone
|
|
Stone stone = getBall().getHitStone();
|
|
|
|
// add value to score
|
|
score += stone.getValue();
|
|
|
|
// set new type
|
|
stone.setType(stone.getType()-1);
|
|
|
|
// stones type is 0? remove it!
|
|
if(stone.getType() == 0) {
|
|
stones.remove(stone);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* checks whether all stones are broken
|
|
* @return true when all stones are broken
|
|
*/
|
|
private boolean allStonesBroken() {
|
|
return stones.isEmpty();
|
|
}
|
|
|
|
/**
|
|
* decreases the lives and interact to the new count
|
|
*/
|
|
private void decreaseLives() {
|
|
lifeCounter--;
|
|
// reset paddles to center pos
|
|
if(lifeCounter > 0) {
|
|
resetPaddles();
|
|
getBall().resetPosition();
|
|
getBall().setLost(false);
|
|
stopBall();
|
|
// level failed
|
|
} else {
|
|
setFinished(true);
|
|
game.getController().toStartScreen();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* resets paddles position and or init them
|
|
*/
|
|
private void resetPaddles() {
|
|
// calc paddle positions
|
|
Position posPaddleTop = new Position((Constants.SCREEN_WIDTH - Constants.PADDLE_WIDTH) / 2.0, 0);
|
|
Position posPaddleBottom = new Position((Constants.SCREEN_WIDTH - Constants.PADDLE_WIDTH) / 2.0, Constants.SCREEN_HEIGHT - Constants.PADDLE_HEIGHT);
|
|
|
|
// resets top paddle
|
|
if(paddleTop == null) paddleTop = new Paddle(posPaddleTop);
|
|
else paddleTop.setPosition(posPaddleTop);
|
|
|
|
// resets bottom paddle
|
|
if(paddleBottom == null) paddleBottom = new Paddle(posPaddleBottom);
|
|
else paddleBottom.setPosition(posPaddleBottom);
|
|
}
|
|
|
|
/**
|
|
* The getter for levels score
|
|
* @return the score
|
|
*/
|
|
public int getScore() {
|
|
return score;
|
|
}
|
|
|
|
/**
|
|
* The getter for levels lives
|
|
* @return the life counter
|
|
*/
|
|
public int getLives() {
|
|
return lifeCounter;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|