Falling Bricks
Informace
Legendární logická hra ve zbrusu novém silně návykovém provedení!
Tento projekt byl vytvořen jako semestrální práce do předmětu
Y36ALG (Algoritmizace).
Popis hry na Wikipedii.
Stáhni a hraj!
Dokumentace
Zdrojové kódy (prohlížení)
- fallingbricks
1: package fallingbricks; 2: import javax.swing.Timer; 3: import java.awt.event.*; 4: import java.awt.*; 5: import java.util.Random; 6: 7: /** 8: * Representing single brick 9: * 10: * @author Ondrej Macoszek 11: */ 12: public class Brick implements ActionListener 13: { 14: 15: /** 16: * Determine shape of brick 17: */ 18: public boolean[][] shape; 19: 20: /** 21: * Current position of brick 22: */ 23: public Point position; 24: 25: /** 26: * Determine if brick is blocked in matrix 27: */ 28: public boolean isBlocked = false; 29: 30: /** 31: * Timer for falling loop 32: */ 33: public Timer falling; 34: 35: /** 36: * Game controller instance 37: */ 38: private Game game = Game.getInstance(); 39: 40: /** 41: * Brick constructor. Create shape according to given id. 42: * @param idx id of brick shape 43: */ 44: public Brick(int idx) 45: { 46: init(idx); 47: } 48: 49: /** 50: * Brick constructor. Create random shape. 51: */ 52: public Brick() 53: { 54: Random rg = new Random(); 55: init(rg.nextInt(7)); 56: } 57: 58: /** 59: * Initialize shape according to given id. 60: * @param idx id of brick shape 61: */ 62: public void init(int idx) 63: { 64: // Copy shape object 65: switch (idx) 66: { 67: case 0: 68: shape = Shapes.TEE.clone(); 69: break; 70: case 1: 71: shape = Shapes.ES.clone(); 72: break; 73: case 2: 74: shape = Shapes.ZET.clone(); 75: break; 76: case 3: 77: shape = Shapes.SQUARE.clone(); 78: break; 79: case 4: 80: shape = Shapes.LONG_I.clone(); 81: break; 82: case 5: 83: shape = Shapes.EL_LEFT.clone(); 84: break; 85: case 6: 86: shape = Shapes.EL_RIGHT.clone(); 87: break; 88: case 7: 89: default: 90: shape = Shapes.ONE.clone(); 91: break; 92: } 93: // starting position of brick, default is [middle,up] 94: position = new Point( 95: (int) Math.floor( ((double)Matrix.dimension.width/(double)2)-((double)shape[0].length/2)), 96: 0 97: ); 98: } 99: 100: /** 101: * Start falling (run timer) 102: */ 103: public void start() 104: { 105: falling = new Timer(game.fallingInterval, this); 106: falling.start(); 107: } 108: 109: /** 110: * Stop falling 111: */ 112: public void stop() 113: { 114: falling.stop(); 115: } 116: 117: /** 118: * Method called by timer. Will attempt moving the brick down 119: * @param evt parameter not used 120: */ 121: public void actionPerformed(ActionEvent evt) 122: { 123: moveDown(); 124: } 125: 126: /** 127: * Will rotate 90° to right with brick if it is possible in surrounding area 128: */ 129: public void rotate() 130: { 131: Debug.msg("Request - rotate (brick > x: "+position.x+" y:"+position.y+")"); 132: // cancel rotating if rotated brick would overflow the matrix field 133: // (brick is most right of most down) or is brick blocked 134: if ( (position.x+shape.length > game.matrix.fields[0].length) 135: || (position.y+shape[0].length > game.matrix.fields.length) 136: || isBlocked ) 137: { 138: return; 139: } 140: // create rotated shape 141: boolean[][] tmp = new boolean[shape[0].length][shape.length]; 142: for (int line = 0, line_counter=shape.length - 1; line < shape.length; line++, line_counter--) 143: { 144: for (int field = 0; field < shape[line].length; field++) 145: { 146: // test for collision if brick 147: if (position.x+shape.length < game.matrix.fields[0].length) 148: { 149: // cancel rotating if there is a collision with matrix filled fields 150: if (game.matrix.fields[position.y+line][position.x+shape.length]==true) 151: { 152: return; 153: } 154: } 155: // copy shape field to new position 156: tmp[field][line_counter] = shape[line][field]; 157: } 158: } 159: shape = tmp; 160: tmp = null; 161: Debug.msg("== Rotating =="); 162: } 163: 164: /** 165: * Will move down the brick if possible 166: */ 167: public void moveDown() 168: { 169: Debug.msg("Request - move down (brick > x: "+position.x+" y:"+position.y+")"); 170: // Cancel moving if brick is on the last row or is blocked 171: if( ((shape.length + position.y) >= game.matrix.fields.length) || isBlocked ) 172: { 173: isBlocked = true; 174: return; 175: } 176: // Searching for possible collision with filled fields in matrix 177: searching: 178: for (int h=shape.length-1; h >= 0; h--) // Begin from lower row (faster) 179: { 180: for (int w=0; w < shape[h].length; w++) // Walk fields inside row 181: { 182: // Cancel moving down if under filled field in shape, 183: // there is filled field in matrix 184: if ( 185: (game.matrix.fields[position.y + h + 1][position.x + w] == true) 186: && (shape[h][w] == true) 187: ) 188: { 189: isBlocked = true; 190: return; 191: } 192: } 193: } 194: position.y++; 195: Debug.msg("== Moving down == "); 196: } 197: 198: /** 199: * Will move left the brick if possible 200: */ 201: public void moveLeft() 202: { 203: Debug.msg("Request - move left (brick > x: "+position.x+" y:"+position.y+")"); 204: // Cancel moving if brick position is on the most left side 205: if ( (position.x<=0) || isBlocked ) 206: { 207: return; 208: } 209: 210: // Searching for collision with filled matrix fields 211: int w = 0; // Will check only first column (of shape) on left 212: searching: 213: for (int h = 0; h < shape.length; h++) 214: { 215: // Cancel moving if matrix field on left is filled 216: if ( 217: (game.matrix.fields[position.y + h][position.x + w - 1] == true) 218: && (shape[h][w] == true) 219: ) 220: { 221: return; 222: } 223: } 224: position.x--; 225: Debug.msg("== Moving left == "); 226: } 227: 228: /** 229: * ¨Will move right if possible 230: */ 231: public void moveRight() 232: { 233: Debug.msg("Request - move right (brick > x: "+position.x+" y:"+position.y+")"); 234: // Cancel moving if brick position is on the most right side 235: if ( ((position.x+shape[0].length) >= (game.matrix.fields[0].length)) || isBlocked ) 236: { 237: return; 238: } 239: 240: // Searching for collision with filled matrix fields 241: int w = shape[0].length-1; // Will check only first column on right 242: searching: 243: for (int h = 0; h < shape.length; h++) 244: { 245: // Cancel moving if matrix field on left is filled 246: if ( 247: (game.matrix.fields[position.y + h][position.x + w + 1] == true) 248: && (shape[h][w] == true) 249: ) 250: { 251: return; 252: } 253: } 254: position.x++; 255: Debug.msg("== Moving right == "); 256: } 257: 258: /** 259: * Rendering current brick in its position 260: * @param g Graphic enviroment 261: */ 262: public void render(Graphics g) 263: { 264: g.setColor(Color.RED); 265: for (int h = 0; h < shape.length; h++) 266: { 267: for (int w = 0; w < shape[h].length; w++) 268: { 269: if ( (shape[h][w]==true) ) { 270: g.fillRect( 271: game.fieldDim.width*(w+position.x), 272: game.fieldDim.height*(h+position.y), 273: game.fieldDim.width, 274: game.fieldDim.height 275: ); 276: } 277: } 278: } 279: } 280: 281: /* 282: * Shapes (Brick inner class) 283: * holds info about brick shapes 284: */ 285: public static class Shapes 286: { 287: public final static boolean[][] TEE = { 288: {true,true,true}, 289: {false,true,false} 290: }; 291: public final static boolean[][] LONG_I = { 292: {true,true,true,true} 293: }; 294: public final static boolean[][] SQUARE = { 295: {true,true}, 296: {true,true} 297: }; 298: public final static boolean[][] ES = { 299: {false,true,true}, 300: {true,true,false} 301: }; 302: public final static boolean[][] ZET = { 303: {true,true,false}, 304: {false,true,true} 305: }; 306: public final static boolean[][] ONE = { 307: {true}, 308: }; 309: public final static boolean[][] EL_LEFT = { 310: {true,false,false}, 311: {true,true,true} 312: }; 313: public final static boolean[][] EL_RIGHT = { 314: {false,false,true}, 315: {true,true,true} 316: }; 317: public final static boolean[][] CROSS = { 318: {false,true,false}, 319: {true,true,true}, 320: {false,true,false} 321: }; 322: public final static boolean[][] KILLER = { 323: {false,true,false,true,false,true}, 324: {true,false,true,false,true,false}, 325: {false,true,false,true,false,true}, 326: {true,false,true,false,true,false}, 327: {false,true,false,true,false,true}, 328: {true,false,true,false,true,false} 329: }; 330: } 331: } 332:
