Board.java (8705B)
1 package game; 2 3 import java.awt.Color; 4 5 import java.awt.Dimension; 6 import java.awt.Font; 7 import java.awt.Graphics; 8 import java.util.ArrayList; 9 10 import javax.swing.BorderFactory; 11 import javax.swing.JPanel; 12 13 import blocks.Tile; 14 import blocks.Tileable; 15 import blocks.Poly; 16 17 public class Board extends JPanel { 18 // size of window 19 private final Dimension size = new Dimension(490, 788); 20 21 private final Color backgroundColor = Color.DARK_GRAY; 22 23 // size of each individual tile 24 private final int tileSize = 25; 25 26 private int score; 27 28 private Tileable[][] grid; 29 30 private ArrayList<Poly> polys = new ArrayList<Poly>(); 31 32 private boolean polyFalling; 33 34 35 /** 36 * Constructs board. 37 * Calculates the size of the grid based of the size of the window. 38 */ 39 public Board() { 40 grid = new Tileable[Math.abs(size.width / tileSize)][Math.abs(size.height / tileSize)]; 41 setBorder(BorderFactory.createLineBorder(Color.black)); 42 polyFalling = false; 43 score = 0; 44 fillGrid(); 45 } 46 47 /** 48 * Fills the grid with unoccupied Tiles. 49 */ 50 public void fillGrid() { 51 for (int x = 0; x < grid[0].length; x++) { 52 for (int y = 0; y < grid.length; y++) { 53 grid[y][x] = new Tile(false); 54 } 55 } 56 } 57 58 /** 59 * Detects full rows. Then calls on ClearRow and fall which together 60 * makes sure full rows are handled correctly. 61 */ 62 public void detectFullRow() { 63 for (int row = 0; row < grid[0].length; row++) { 64 for (int col = 0; col < grid.length; col++) { 65 if (!(grid[col][row].isOccupied())) { 66 break; 67 } 68 if (col == grid.length - 1) { 69 score += 10; 70 clearRow(row); 71 fall(row); 72 } 73 } 74 } 75 } 76 77 /** 78 * Getter for score. 79 * @return current score. 80 */ 81 public int getScore() { 82 return score; 83 } 84 85 /** 86 * Sets all Tiles on a given row to be unoccupied. 87 * @param rowNumber 88 */ 89 private void clearRow(int rowNumber) { 90 for (int col = 0; col < grid.length; col++) { 91 grid[col][rowNumber].setOccupied(false); 92 grid[col][rowNumber].setColor(backgroundColor); 93 } 94 } 95 96 /** 97 * increase score by given amount. 98 * @param amount 99 */ 100 public void givePoints(int amount) { 101 score += amount; 102 } 103 104 /** 105 * Returns the size of the window. 106 * @return size. 107 */ 108 public Dimension getSize() { 109 return this.size; 110 } 111 112 /** 113 * Used for the graphical components of the game. 114 * Draws all components of the board. 115 */ 116 public void paintComponent(Graphics g) { 117 super.paintComponent(g); 118 g.setColor(Color.gray); 119 draw(g); 120 } 121 122 /** 123 * Move a Poly in given direction 124 * @param poly the poly to move 125 * @param x movement in X direction. 126 * @param y movement in Y direction. 127 * @return return whether movement was carried through or not. 128 */ 129 public boolean move(Poly poly, int x, int y) { 130 if (isLegal(poly, x, y)) { 131 poly.move(x, y); 132 return true; 133 } 134 return false; 135 } 136 137 /** 138 * Checks if a movement, or current position of poly is allowed. 139 * @param poly the poly to check. 140 * @param x offset in X direction. 141 * @param y offset in Y direction. 142 * @return boolean movement legal or not. 143 */ 144 public boolean isLegal(Poly poly, int x, int y) { 145 int[][] shape = poly.getShape(); 146 int[] position = poly.getPos(); 147 148 // iterate over every "tile" in poly shape 149 for (int i = 0; i < shape.length; i++) { 150 for (int j = 0; j < shape[0].length; j++) { 151 int realX = position[0] + j; 152 int realY = position[1] + i; 153 if (shape[i][j] == 1) { 154 155 // check X direction 156 if (realX + x >= grid.length || realX + x < 0) { 157 return false; 158 } 159 if (grid[realX + x][realY].isOccupied()) { 160 return false; 161 } 162 163 // check y direction 164 if (realY + y >= grid[0].length - 1) { 165 return false; 166 } 167 if (grid[realX][realY + y].isOccupied()) { 168 return false; 169 } 170 } 171 } 172 } 173 174 return true; 175 } 176 177 /** 178 * Returns the currently falling poly, if any. 179 * @return falling poly. 180 */ 181 public Poly getFallingPoly() { 182 if (!(polys.isEmpty())) { 183 return polys.get(polys.size() - 1); 184 } 185 return null; 186 } 187 188 /** 189 * Converts a poly in to Tiles at its current position. 190 * After conversion the Poly is no longer controllable. 191 * @param poly the poly to convert. 192 */ 193 private void freeze(Poly poly) { 194 int[][] shape = poly.getShape(); 195 int[] position = poly.getPos(); 196 for (int i = 0; i < shape.length; i++) { 197 for (int j = 0; j < shape[0].length; j++) { 198 if (shape[i][j] == 1) { 199 grid[position[0] + j][position[1] + i] = new Tile(poly.getColor()); 200 } 201 } 202 } 203 polyFalling = false; 204 polys.remove(poly); 205 } 206 207 /** 208 * Is there a Poly falling currently. 209 * @return is there a falling poly. 210 */ 211 public boolean isFalling() { 212 return polyFalling; 213 } 214 215 /** 216 * Moves a given Poly one step down, for as long as possible. 217 * When movement is no longer possible, freeze it into position. 218 * @param poly to move. 219 */ 220 public void fall(Poly poly) { 221 polyFalling = true; 222 if (move(poly, 0, 1)) { 223 return; 224 } else { 225 freeze(poly); 226 } 227 } 228 229 /** 230 * Move given row down one number in grid. 231 * @param row the row number to move downwards. 232 */ 233 public void fall(int row) { 234 for (int j = row; j > 0; j--) { 235 for (int i = grid.length - 1; i >= 0; i--) { 236 grid[i][j] = grid[i][j - 1]; 237 } 238 } 239 } 240 241 /** 242 * Moves a Poly to its lowest possible position and freezes it. 243 * @param poly 244 */ 245 public void instaFall(Poly poly) { 246 polyFalling = true; 247 boolean result = true; 248 do { 249 result = move(poly, 0, 1); 250 } while (result); 251 freeze(poly); 252 } 253 254 /** 255 * Has the user lost. 256 * @return whether the user has lost or not. 257 */ 258 public boolean hasLost() { 259 for (int i = 0; i < grid.length; i++) { 260 if (grid[i][0].isOccupied()) { 261 return true; 262 } 263 } 264 return false; 265 } 266 267 /** 268 * Add a new poly to the board. 269 * @param poly 270 */ 271 public void addPoly(Poly poly) { 272 polys.add(poly); 273 polyFalling = true; 274 } 275 276 /** 277 * Get the spawnpoint for new Polys. 278 * @return coordinates of spawnpoint. 279 */ 280 public int[] getPrefferedSpawn() { 281 int[] spawn = { grid.length / 2, 0 }; 282 return spawn; 283 } 284 285 /** 286 * Turns the entire board into the desired background color. 287 * @param g Java graphics. 288 */ 289 private void clearBoard(Graphics g) { 290 g.setColor(backgroundColor); 291 g.fillRect(0, 0, size.width, size.height); 292 } 293 294 /** 295 * Draw all elements of the board that are to be displayed. 296 * @param g Java graphics. 297 */ 298 public void draw(Graphics g) { 299 clearBoard(g); 300 301 // generate grid lines 302 drawGrid(g); 303 304 // draw guidelines 305 drawPolyGuide(g); 306 307 // draw polys 308 drawPoly(g); 309 310 // draw tiles 311 drawTiles(g); 312 313 // show score 314 drawScore(g); 315 } 316 317 /** 318 * Draws the falling poly(s). 319 * @param g 320 */ 321 private void drawPoly(Graphics g) { 322 // draw polys 323 if (polys.size() > 0) { 324 for (Poly poly : polys) { 325 g.setColor(poly.getColor()); 326 int[][] shape = poly.getShape(); 327 328 for (int i = 0; i < shape.length; i++) { 329 for (int j = 0; j < shape[0].length; j++) { 330 if (shape[i][j] == 1) { 331 g.fillRect(poly.getPos()[0] * tileSize + (j * tileSize), 332 poly.getPos()[1] * tileSize + (i * tileSize), tileSize, tileSize); 333 334 } 335 } 336 } 337 } 338 } 339 } 340 341 /** 342 * Draws all the Tiles. 343 * @param g 344 */ 345 private void drawTiles(Graphics g) { 346 for (int x = 0; x < grid[0].length; x++) { 347 for (int y = 0; y < grid.length; y++) { 348 if (grid[y][x].isOccupied()) { 349 g.setColor(grid[y][x].getColor()); 350 g.fillRect(y * tileSize, x * tileSize, tileSize, tileSize); 351 } 352 } 353 } 354 } 355 356 /** 357 * Draws the guidelines that show where the falling Poly is going to land. 358 * @param g 359 */ 360 private void drawPolyGuide(Graphics g) { 361 g.setColor(Color.white); 362 if (getFallingPoly() != null) { 363 Poly poly = getFallingPoly(); 364 int[][] shape = poly.getShape(); 365 g.drawLine(poly.getPos()[0] * tileSize + (shape[0].length * tileSize), 0, 366 poly.getPos()[0] * tileSize + (shape[0].length * tileSize), size.height); 367 g.drawLine(poly.getPos()[0] * tileSize, 0, poly.getPos()[0] * tileSize, size.height); 368 } 369 } 370 371 /** 372 * Displays the score at the top left of the window. 373 * @param g 374 */ 375 private void drawScore(Graphics g) { 376 // show score 377 g.setColor(Color.white); 378 String scoreText = "Score: " + String.valueOf(score); 379 g.setFont(new Font("Helvetica", Font.PLAIN, tileSize)); 380 g.drawString(scoreText, tileSize, g.getFontMetrics().getHeight()); 381 } 382 383 /** 384 * Draws the gridlines representing the board. 385 * @param g 386 */ 387 private void drawGrid(Graphics g) { 388 g.setColor(Color.gray); 389 390 for (int x = 0; x < grid.length; x++) { 391 for (int y = 0; y < grid[0].length; y++) { 392 //draw x lines 393 g.drawLine(x * tileSize, 0, x * tileSize, grid[0].length * tileSize); 394 //draw y lines 395 g.drawLine(0, y * tileSize, grid[1].length * tileSize, y * tileSize); 396 } 397 } 398 } 399 }