Kontakt

Fakturační údaje

IČ: 87189224, BÚ: 1958653063/0800

Contact info in QR code

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í)

  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: