package break_out.view; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Dimension; import java.awt.RenderingHints; import java.awt.Font; import java.awt.font.TextAttribute; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import javax.swing.JPanel; import break_out.Constants; import break_out.model.Position; import break_out.model.Stone; import net.miginfocom.swing.MigLayout; /** * The field represents the board of the game. All components are on the board * * @author dmlux, modified by iSchumacher, modified by Gruppe 175 (Moritz Henseleit, Ruben Meyer) */ public class Field extends JPanel { /** * Automatic generated serial version UID */ private static final long serialVersionUID = 2434478741721823327L; /** * The connected view object */ private View view; /** * The background color */ private Color background; /** * The constructor needs a view * * @param view The view of this board */ public Field(View view) { super(); this.view = view; this.background = Constants.COLOR_GAME_BACKGROUND; setFocusable(true); // Load settings initialize(); } /** * Initializes the settings for the board */ private void initialize() { // creates a layout setLayout(new MigLayout("", "0[grow, fill]0", "0[grow, fill]0")); } /** * Change the background color * * @param color The new color */ public void changeBackground(Color color) { background = color; repaint(); } /** * This method is called when painting/repainting the playground * * @param g the graphics object */ @Override protected void paintComponent(Graphics g) { super.paintComponent(g); double w = Constants.SCREEN_WIDTH; double h = Constants.SCREEN_HEIGHT; // Setting the dimensions of the playground setPreferredSize(new Dimension((int) w, (int) h)); setMaximumSize(new Dimension((int) w, (int) h)); setMinimumSize(new Dimension((int) w, (int) h)); Graphics2D g2 = (Graphics2D) g; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // Setting the background color g2.setColor(background); g2.fillRect(0, 0, getWidth(), getHeight()); // Setting the color for the following components g2.setColor(Constants.COLOR_COMPONENT); // Calls the method for drawing the grid drawGrid(g2); // Calls the method for drawing the stones drawStones(g2); // Calls the method for drawing the ball drawBall(g2); // Calls the method for drawing the bottom paddle drawPaddleBottom(g2); // Calls the method for drawing the top paddle drawPaddleTop(g2); // Calls the method for drawing the scoreboard drawScoreboard(g2); } /** * Draws the ball * * @param g2 The graphics object */ private void drawBall(Graphics2D g2) { // temporarily save default component color to draw ball in specific color Color temp = g2.getColor(); g2.setColor(view.getGame().getLevel().getBall().getColor()); g2.fillOval((int) view.getGame().getLevel().getBall().getPosition().getX(), (int) view.getGame().getLevel().getBall().getPosition().getY(), Constants.BALL_DIAMETER, Constants.BALL_DIAMETER); // reset color to default g2.setColor(temp); } /** * Draws the grid * * @param g2 The graphics object */ private void drawGrid(Graphics2D g2) { // size of grid blocks int blockWidth = Constants.SCREEN_WIDTH / Constants.SQUARES_X; int blockHeight = Constants.SCREEN_HEIGHT / Constants.SQUARES_Y; // temporarily save default component color to draw ball in specific color Color temp = g2.getColor(); // Component color with alpha Color withAlpha = new Color(g2.getColor().getRed(), g2.getColor().getGreen(), g2.getColor().getBlue(), 170); g2.setColor(withAlpha); // draw vertical lines for (int i = 1; i < Constants.SQUARES_X; i++) { g2.drawLine(i * blockWidth, 0, i * blockWidth, Constants.SCREEN_HEIGHT); } // draw horizontal lines for (int i = 1; i < Constants.SQUARES_Y; i++) { g2.drawLine(0, i * blockHeight, Constants.SCREEN_WIDTH, i * blockHeight); } // reset color to default g2.setColor(temp); } /** * Draws the bottom paddle * * @param g2 The graphics object */ private void drawPaddleBottom(Graphics2D g2) { // temporarily save default component color to draw paddle in specific color Color temp = g2.getColor(); g2.setColor(view.getGame().getLevel().getPaddleBottom().getColor()); // fillRoundRect(x, y, width, height, arcWidth, arcHeight) g2.fillRoundRect((int) view.getGame().getLevel().getPaddleBottom().getPosition().getX(), (int) view.getGame().getLevel().getPaddleBottom().getPosition().getY(), (int) view.getGame().getLevel().getPaddleBottom().getWidth(), (int) view.getGame().getLevel().getPaddleBottom().getHeight(), 10, 10); // reset color to default g2.setColor(temp); } /** * Draws the top paddle * * @param g2 The graphics object */ private void drawPaddleTop(Graphics2D g2) { // temporarily save default component color to draw paddle in specific color Color temp = g2.getColor(); g2.setColor(view.getGame().getLevel().getPaddleTop().getColor()); // fillRoundRect(x, y, width, height, arcWidth, arcHeight) g2.fillRoundRect((int) view.getGame().getLevel().getPaddleTop().getPosition().getX(), (int) view.getGame().getLevel().getPaddleTop().getPosition().getY(), (int) view.getGame().getLevel().getPaddleTop().getWidth(), (int) view.getGame().getLevel().getPaddleTop().getHeight(), 10, 10); // reset color to default g2.setColor(temp); } /** * Draws the stones * * @param g2 The graphics object */ private void drawStones(Graphics2D g2) { // query stones ArrayList stones = view.getGame().getLevel().getStones(); // foreach stone for(Stone stone : stones) { Position pos = stone.getPosition(); // size of grid blocks int blockWidth = Constants.SCREEN_WIDTH / Constants.SQUARES_X; int blockHeight = Constants.SCREEN_HEIGHT / Constants.SQUARES_Y; // if stone has a color, draw it if(stone.getColor() != null) { // temporarily save default component color to draw stone in specific color Color temp = g2.getColor(); g2.setColor(stone.getColor()); // fillRoundRect(x, y, width, height, arcWidth, arcHeight) g2.fillRoundRect((int) pos.getX()+1, (int) pos.getY()+1, (int) blockWidth-1, (int) blockHeight-1, 0, 0); // reset color to default g2.setColor(temp); } } } /** * Draws the scoreboard with score and lives * @param g2 */ private void drawScoreboard(Graphics2D g2) { Font currentFont = g2.getFont(); // source: Stackoverflow Question - 18249592 Map attributes = new HashMap<>(); attributes.put(TextAttribute.FAMILY, currentFont.getFamily()); attributes.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD); attributes.put(TextAttribute.SIZE, (int) (currentFont.getSize() * 1.8)); Font myFont = Font.getFont(attributes); g2.setFont(myFont); // temporarily save default component color to draw text and background in specific color Color temp = g2.getColor(); // draw background in specific color g2.setColor(Constants.COLOR_SCOREBOARD); // bottom centered mid-point int midX = (int) Constants.SCOREBOARD_MIDPOINT.getX(); int midY = (int) Constants.SCOREBOARD_MIDPOINT.getY(); int offset = Constants.SCOREBOARD_OFFSET; // calculate rendered string width int scoreWidth = g2.getFontMetrics().stringWidth(Constants.SCOREBOARD_SCORE + view.getGame().getLevel().getScore()); int lifeWidth = g2.getFontMetrics().stringWidth(Constants.SCOREBOARD_LIVES + view.getGame().getLevel().getLives()); int maxWidth = Math.max(scoreWidth, lifeWidth); // max width int fontSize = g2.getFontMetrics().getHeight(); // font size // fillRoundRect(x, y, width, height, arcWidth, arcHeight) g2.fillRoundRect((midX)-offset-maxWidth/2, midY-2*offset-3*fontSize, maxWidth+2*offset, 2*(fontSize+offset), 5, 5); // draw text in specific color (sharing g2 object and therefore also color) g2.setColor(Constants.COLOR_TEXT); // draw score and lives drawScore(g2); drawLives(g2); // reset color and font g2.setColor(temp); g2.setFont(currentFont); } /** * Draws the score * * @param g2 The graphics object */ private void drawScore(Graphics2D g2) { int score = view.getGame().getLevel().getScore(); int fontSize = g2.getFontMetrics().getHeight(); // font size // bottom centered mid-point int x = (int) Constants.SCOREBOARD_MIDPOINT.getX(); int y = (int) Constants.SCOREBOARD_MIDPOINT.getY()-(int)((3.0/2.0)*fontSize); String str = Constants.SCOREBOARD_SCORE+score; x -= g2.getFontMetrics().stringWidth(str)/2; // because x is middle position on x axis // draw string g2.drawString(str, x, y); } /** * Draws the life counter * * @param g2 The graphics object */ private void drawLives(Graphics2D g2) { int lives = view.getGame().getLevel().getLives(); int fontSize = g2.getFontMetrics().getHeight(); // font size // bottom centered mid-point int x = (int) Constants.SCOREBOARD_MIDPOINT.getX(); int y = (int) Constants.SCOREBOARD_MIDPOINT.getY()-3*fontSize; String str = Constants.SCOREBOARD_LIVES+lives; x -= g2.getFontMetrics().stringWidth(str)/2; // because x is middle position on x axis // draw string g2.drawString(str, x, y); } }