1
0
Fork 0

Compare commits

...

35 Commits
A2.1 ... master

Author SHA1 Message Date
rxbn_ 2a27f74846 BreakOut 5 - reset direction 3 years ago
rxbn_ 5a5d661719 BreakOut 5 - new Level design and layout 3 years ago
rxbn_ 05a4463ba8 BreakOut 5.4 3 years ago
rxbn_ 59c2f83f49 BreakOut 5.3 3 years ago
rxbn_ 59fdc12e4f BreakOut 5.2 - methods are now written according to specifications to pass JUnit tests 3 years ago
rxbn_ 90afe2d72e BreakOut 5.2 - Scoreboard 3 years ago
rxbn_ 21a7b951d6 BreakOut 5.1 - b), c) 3 years ago
rxbn_ 5ea292bbae BreakOut 5.1 - a) 3 years ago
rxbn_ b51c1c4f62 BreakOut 5.* Vorgabe 3 years ago
rxbn_ f6e8e6fcc5 minor comments and refactoring in break_out.model.Level 3 years ago
rxbn_ 87048abd6f Aufgabe 3 Feedback - minor fixes 3 years ago
rxbn_ 49f431c236 neue Abgabegruppe - 262 3 years ago
rxbn_ 041092f121 quick fix - JavaDoc 3 years ago
rxbn_ 8668f6e2b5 minor fix - longer paddles - game design decision 3 years ago
rxbn_ 9210e43b6a Aufgabe 4.4 - updateStonesAndScore, allStonesBroken 3 years ago
rxbn_ 2102f5c27b Aufgabe 4.3 - hitsStone, reflectOnStone 3 years ago
rxbn_ 0fdd579b41 Aufgabe 4.2 - drawStones 3 years ago
rxbn_ 669c37029a minor fixes 3 years ago
rxbn_ 2870a5fc9a Aufgabe 4.1 - loadLevelData 3 years ago
rxbn_ 1b829fba1e BreakOut 4.* Vorgabe 3 years ago
rxbn_ 4bec1047ed Aufgabe 3.4 3 years ago
rxbn_ 94a394438d Aufgabe 3.3 3 years ago
rxbn_ 0548e10e6b Aufgabe 3.2 3 years ago
rxbn_ ba286f548f Aufgabe 3.1 3 years ago
rxbn_ 9182e79f6b BreakOut 3.* Vorgabe - missing IStone.java 3 years ago
rxbn_ 4fe42792ee BreakOut 3.* Vorgabe + Implementation 3 years ago
rxbn_ ce770c9cc7 fix - Ball - reflectOnPaddle - wrong estimation and therefore no bottom paddle behaviour 3 years ago
rxbn_ 341aa10277 fix - createRelease - wrong file prefix 3 years ago
rxbn_ c21af90605 Ball - no blue colors according to constant GAME_BACKGROUND to prevent ghosting 3 years ago
rxbn_ 463b562645 Field - grid color with alpha value 3 years ago
rxbn_ 7b416c205e Field - game background as a constant 3 years ago
rxbn_ 584d33ae07 quick fix - first draw grid then ball 3 years ago
rxbn_ 46e689dec3 ball - new color when ball hits paddle 3 years ago
rxbn_ 087650adc8 documentation - correct javadoc for paddle constructor 3 years ago
rxbn_ 75ee56adce custom color for paddles 3 years ago
  1. 7
      README.md
  2. 2
      createRelease.sh
  3. 62
      res/Level1.json
  4. 33
      res/Level2.json
  5. 33
      res/Level3.json
  6. 56
      src/break_out/Constants.java
  7. 42
      src/break_out/controller/Controller.java
  8. 111
      src/break_out/controller/JSONReader.java
  9. 248
      src/break_out/model/Ball.java
  10. 4
      src/break_out/model/Game.java
  11. 9
      src/break_out/model/IBall.java
  12. 10
      src/break_out/model/ILevel.java
  13. 12
      src/break_out/model/IPaddle.java
  14. 17
      src/break_out/model/IStone.java
  15. 211
      src/break_out/model/Level.java
  16. 68
      src/break_out/model/Paddle.java
  17. 147
      src/break_out/model/Stone.java
  18. 186
      src/break_out/view/Field.java
  19. 35
      src/break_out/view/StartScreen.java

@ -3,8 +3,13 @@
- Einführung in die Programmierung WS19/20
- Programmieren des Spieles "Breakout" basierend auf dem Framework des Instituts
# Gruppe
# alte Gruppe (bis inkl. 3.)
Gruppennummer: 175
Gruppenmitglieder
- [Ruben Meyer](mailto:ruben.meyer@student.uni-luebeck.de)
- [Moritz Henseleit](mailto:moritz.henseleit@student.uni-luebeck.de)
# neue Gruppe (ab inkl. 4.)
Gruppennummer: 262
Gruppenmitglieder:
- [Ruben Meyer](mailto:ruben.meyer@student.uni-luebeck.de)

@ -1,7 +1,7 @@
#!/usr/bin/env zsh
# project prefix
PREFIX="175-BreakoutA"
PREFIX="262-BreakOutA"
# get versioning
echo -n "Type your tag version for '$PREFIX' (like (2.1) followed by [ENTER] for ${PREFIX}2.1): "

@ -1,33 +1,35 @@
{
"field" : [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 2, 0, 2, 2, 2, 0, 2, 2, 0, 2, 2, 0, 0, 0, 0, 2, 2, 2, 0, 0],
[0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0],
[0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 3, 0, 0, 3, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 3, 3, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
"field" : [
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
[0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0],
[0, 1, 0, 3, 0, 1, 0, 0, 0, 1, 2, 1, 0, 0, 0, 1, 0, 3, 0, 1, 0],
[0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 3, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 3, 3, 3, 3, 2, 1, 2, 3, 3, 3, 3, 0, 0, 0, 0, 0],
[0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0],
[0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0],
[0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
],
"maxLives" : 5
}

@ -0,0 +1,33 @@
{
"field" : [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 2, 0, 2, 2, 2, 0, 2, 2, 0, 2, 2, 0, 0, 0, 0, 2, 2, 2, 0, 0],
[0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0],
[0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 3, 0, 0, 3, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 3, 3, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
"maxLives" : 5
}

@ -0,0 +1,33 @@
{
"field" : [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 1, 1, 1, 0, 0, 2, 0, 0, 0, 0, 3, 0, 0, 3, 0, 0, 0, 3, 0, 0],
[0, 1, 0, 0, 1, 1, 0, 2, 2, 2, 2, 0, 3, 3, 0, 3, 3, 0, 0, 3, 3, 0],
[0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 3, 3, 0, 0, 3, 0, 0, 3, 3, 0],
[0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 3, 0, 0, 3, 0, 0, 3, 0, 0],
[0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 3, 0, 0, 3, 0, 0, 3, 0, 0],
[0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 2, 0, 0, 3, 0, 0, 3, 0, 3, 3, 0, 0],
[0, 1, 0, 0, 0, 1, 0, 0, 2, 2, 0, 0, 0, 3, 0, 0, 3, 0, 3, 0, 0, 0],
[0, 1, 0, 0, 0, 1, 0, 2, 2, 0, 0, 0, 0, 3, 0, 3, 3, 0, 3, 0, 0, 0],
[0, 1, 1, 1, 1, 1, 0, 2, 0, 0, 0, 0, 0, 3, 0, 3, 0, 0, 3, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 3, 3, 3, 0, 0, 3, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
"maxLives" : 5
}

@ -1,11 +1,13 @@
package break_out;
import break_out.model.Position;
import java.awt.Color;
/**
* A class that contains all constant values to configure the game
*
* @author dmlux, modified by I. Schumacher
* @author dmlux, modified by I. Schumacher, modified by Gruppe 175: Ruben Meyer und Moritz Henseleit
*/
public class Constants {
@ -47,7 +49,7 @@ public class Constants {
/**
* The paddle width in pixels
*/
public static final Integer PADDLE_WIDTH = 70;
public static final Integer PADDLE_WIDTH = 90;
/**
* The paddle height in pixels
@ -74,4 +76,54 @@ public class Constants {
*/
public static final Double BALL_SPEED = 1.20;
/**
* The background color for the field
*/
public static final Color COLOR_GAME_BACKGROUND = new Color(64, 45, 61);
/**
* The default component color
*/
public static final Color COLOR_COMPONENT = new Color(191, 105, 145);
/**
* The component color for the bottom paddle
*/
public static final Color COLOR_PADDLE_BOTTOM = new Color(242, 173, 148);
/**
* The component color for the top paddle
*/
public static final Color COLOR_PADDLE_TOP = new Color(242, 196, 141);
/**
* The component color for the text
*/
public static final Color COLOR_TEXT = new Color(0, 0, 0);
/**
* The component color for the scoreboard
*/
public static final Color COLOR_SCOREBOARD = new Color(140, 140, 140, 144);
/**
* The padding / offset of the scoreboard to the inner text elements
*/
public static final int SCOREBOARD_OFFSET = 15;
/**
* The string for the score on the scoreboard
*/
public static final String SCOREBOARD_SCORE = "Score: ";
/**
* The string for the lives on the scoreboard
*/
public static final String SCOREBOARD_LIVES = "Lives: ";
/**
* The position for the scoreboards midpoint (bottom center)
*/
public static final Position SCOREBOARD_MIDPOINT = new Position(SCREEN_WIDTH*5/6, SCREEN_HEIGHT);
}

@ -104,7 +104,6 @@ public class Controller implements ActionListener, KeyListener {
*/
@Override
public void keyTyped(KeyEvent e) {
}
/**
@ -114,6 +113,32 @@ public class Controller implements ActionListener, KeyListener {
*/
@Override
public void keyPressed(KeyEvent e) {
switch(e.getKeyCode()) {
// space bar was pressed
case KeyEvent.VK_SPACE:
// start-stop mechanism for the ball
if(!game.getLevel().ballWasStarted()) game.getLevel().startBall();
else game.getLevel().stopBall();
break;
// arrow facing left was pressed
case KeyEvent.VK_LEFT:
// paddle shall go left
game.getLevel().getPaddleBottom().setDirection(-1);
game.getLevel().getPaddleTop().setDirection(-1);
break;
// arrow facing right was pressed
case KeyEvent.VK_RIGHT:
// paddle shall go right
game.getLevel().getPaddleBottom().setDirection(+1);
game.getLevel().getPaddleTop().setDirection(+1);
break;
// escape was pressed
case KeyEvent.VK_ESCAPE:
// exit current level
game.getLevel().setFinished(true);
toStartScreen(game.getLevel().getScore());
break;
}
}
@ -124,15 +149,26 @@ public class Controller implements ActionListener, KeyListener {
*/
@Override
public void keyReleased(KeyEvent e) {
switch(e.getKeyCode()) {
case KeyEvent.VK_LEFT: // arrow facing left was released
case KeyEvent.VK_RIGHT: // arrow facing right was released
// paddle shall stop
game.getLevel().getPaddleBottom().setDirection(0);
game.getLevel().getPaddleTop().setDirection(0);
break;
}
}
/**
* This method switches the view to the StartScreen view.
* @param score The player score
*/
public void toStartScreen() {
public void toStartScreen(int score) {
view.showScreen(StartScreen.class.getName());
view.getStartScreen().requestFocusInWindow();
view.getStartScreen().addScore(score);
view.getStartScreen().repaint();
}
/**

@ -0,0 +1,111 @@
package break_out.controller;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import break_out.Constants;
/**
* The <code>JSONReader</code> reads the content of an json file.
*
* @author dmlux, modified by I.Schumacher
*
*/
public class JSONReader {
/**
* The project path to the JSON file
*/
private String path;
/**
* The stones stored as List&lt;List&lt;Long&gt;&gt;
*/
private List<List<Long>> rects = new ArrayList<List<Long>>();
/**
* The stones stored as 2D-int-array
*/
private int[][] stones = new int[Constants.SQUARES_Y][Constants.SQUARES_X];
/**
* The counter with the number of trials that are allowed to break out the stones of the level
*/
private Long lifecount = null;
/**
* The constructor needs an path to create the JSONReader
*
* @param path
* The absolute path to the JSON file
*/
public JSONReader(String path) {
this.path = path;
loadJsonValues();
}
/**
* Getter for the stones of the JSON file
*
* @return The List&lt;List&lt;Long&gt;&gt; of stones
*/
public List<List<Long>> getStonesListOfLists() {
return rects;
}
/**
* Getter for the stones of the JSON file
*
* @return The stones as 2D-Array
*/
public int[][] getStones2DArray() {
for (int i = 0; i < rects.size(); i++) {
for (int j = 0; j < rects.get(i).size(); j++) {
stones[i][j] = (int)rects.get(i).get(j).longValue();
}
}
return stones;
}
/**
* Getter for the lifeCounter of the JSON file
*
* @return The lifeCounter
*/
public int getLifeCounter() {
return (int)lifecount.longValue();
}
/**
* Loader for the both values "fields" and "maxDrops" of the JSON file
*
*/
@SuppressWarnings("unchecked")
private void loadJsonValues() {
JSONParser parser = new JSONParser();
try {
Object obj = parser.parse(new FileReader(path));
String jsonStr = obj.toString();
JSONObject json = (JSONObject) JSONValue.parse(jsonStr);
rects = (List<List<Long>>) json.get("field");
lifecount = (Long)json.get("maxLives");
} catch (ParseException ex) {
ex.printStackTrace();
} catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}

@ -2,6 +2,10 @@ package break_out.model;
import break_out.Constants;
import java.awt.*;
import java.util.ArrayList;
import java.util.Random;
/**
* This class contains the information about the balls characteristics and behavior
*
@ -19,18 +23,38 @@ public class Ball implements IBall {
*/
private Vector2D direction;
/**
* The balls hit state for paddles; custom implementation
*/
private boolean hitsPaddle;
/**
* The balls lost state for upper and lower borders
*/
private boolean isLost;
/**
* The balls color with default component color
*/
private Color color = Constants.COLOR_COMPONENT;
/**
* The stone which has been hit by the ball
*/
private Stone hitStone = null;
/**
* The constructor of a ball
* The balls position and direction are initialized here.
*/
public Ball() {
this.position = new Position(0, 0);
this.direction = new Vector2D(Constants.BALL_SPEED, Constants.BALL_SPEED);
this.direction.rescale();
// start at bottom-center
this.position.setX((Constants.SCREEN_WIDTH - Constants.BALL_DIAMETER) / 2.0);
this.position.setY(Constants.SCREEN_HEIGHT - Constants.BALL_DIAMETER - Constants.PADDLE_HEIGHT);
// reset direction
resetDirection();
// reset position to bottom-center
resetPosition();
}
/**
@ -51,6 +75,53 @@ public class Ball implements IBall {
return this.direction;
}
/**
* The getter for the balls color
*
* @return color The balls current color
*/
public Color getColor() { return this.color; }
/**
* The setter for the balls color
*
* @param color The balls new color
*/
public void setColor(Color color) { this.color = color; }
/**
* Creates new random color for the ball and sets it
*
* @see <a href="https://stackoverflow.com/a/4247219">Stackoverflow Answer 4247219</a>
*/
public void newRandomColor() {
Random random = new Random();
// random hue without blue colors to prevent ghosting
float hue = (random.nextInt(200)+50) / 360f;
// saturation between 0.5 and 0.7
float saturation = (random.nextInt(2000) + 5000) / 10000f;
float luminance = 0.9f;
Color randColor = Color.getHSBColor(hue, saturation, luminance);
setColor(randColor);
}
/**
* The getter for the balls hit state
*
* @return hitsPaddle The balls current hit state
*/
public boolean getHitState() { return this.hitsPaddle; }
/**
* The setter for the balls hit state
*
* @param state The balls new hit state
*/
public void setHitState(boolean state) { this.hitsPaddle = state; }
/**
* updates ball position
*/
@ -80,14 +151,12 @@ public class Ball implements IBall {
// reacts on top border
if (this.position.getY() <= 0) {
this.position.setY(0);
this.direction.setDy(-(this.direction.getDy()));
isLost = true;
}
// reacts on bottom border (+Diameter because of hitbox)
if (this.position.getY() >= Constants.SCREEN_HEIGHT - Constants.BALL_DIAMETER) {
this.position.setY(Constants.SCREEN_HEIGHT - Constants.BALL_DIAMETER);
this.direction.setDy(-(this.direction.getDy()));
isLost = true;
}
}
@ -153,7 +222,7 @@ public class Ball implements IBall {
// only two paddles defined in the game design, therefore greater or smaller than middle of screen
//deciding if the paddle is at the top or bottom to adjust if its +or- y direction
if (paddle.getPosition().getY() <= Constants.SCREEN_HEIGHT) {
if (paddle.getPosition().getY() <= Constants.SCREEN_HEIGHT/2.0) {
// top paddle
reflectionPoint.setY(reflectionPoint.getY() - Constants.REFLECTION_OFFSET);
} else {
@ -176,6 +245,163 @@ public class Ball implements IBall {
// replace direction vector
this.direction.setDx(reflectionVector.getDx());
this.direction.setDy(reflectionVector.getDy());
}
}
/**
* tests whether the ball touches any stone's hit box
* @param stones list of stones on the playground
* @return true if the ball touches a stone
*/
public boolean hitsStone(ArrayList<Stone> stones) {
// ball as a Rectangle
Rectangle rectBall = new Rectangle((int) getPosition().getX(), (int) getPosition().getY(), Constants.BALL_DIAMETER, Constants.BALL_DIAMETER);
// size of grid blocks
int blockWidth = Constants.SCREEN_WIDTH / Constants.SQUARES_X;
int blockHeight = Constants.SCREEN_HEIGHT / Constants.SQUARES_Y;
// foreach stone in stones
for(Stone stone : stones) {
if(stone != null) {
// stone as a Rectangle based on view.Field
Rectangle rectStone = new Rectangle((int) stone.getPosition().getX()+1, (int) stone.getPosition().getY()+1, blockWidth-1, blockHeight-1);
// if ball intersects with stone which is existent and visible
if(rectBall.intersects(rectStone) && stone.getColor() != null) {
// set stone and return true
hitStone = stone;
// reflect ball
reflectOnStone(hitStone);
return true;
}
}
}
return false;
}
/**
* returns the stone which got hit, can be null
* @return the stone which got hit
*/
public Stone getHitStone() {
return hitStone;
}
/**
* Ball got hit by Stone stone
* @param stone hitbox mechanism of stone
*/
public void reflectOnStone(Stone stone) {
// reflection model based on view.Field rendering model
// size of grid blocks
int blockWidth = Constants.SCREEN_WIDTH / Constants.SQUARES_X;
int blockHeight = Constants.SCREEN_HEIGHT / Constants.SQUARES_Y;
// ball as a Rectangle
Rectangle rectBall = new Rectangle((int) getPosition().getX(), (int) getPosition().getY(), Constants.BALL_DIAMETER, Constants.BALL_DIAMETER);
// stone as a Rectangle
Rectangle rectStone = new Rectangle((int) stone.getPosition().getX()+1, (int) stone.getPosition().getY()+1, blockWidth-1, blockHeight-1);
// stones borders as Rectangle's
Rectangle topBorder = new Rectangle((int) stone.getPosition().getX(), (int) stone.getPosition().getY(), blockWidth, 1);
Rectangle bottomBorder = new Rectangle((int) stone.getPosition().getX(), (int) stone.getPosition().getY()+blockHeight, blockWidth, 1);
Rectangle leftBorder = new Rectangle((int) stone.getPosition().getX(), (int) stone.getPosition().getY(), 1, blockHeight);
Rectangle rightBorder = new Rectangle((int) stone.getPosition().getX()+blockWidth, (int) stone.getPosition().getY(), 1, blockHeight);
//System.out.println(String.format("ball (%s, %s) stone (%s, %s)", getPosition().getX(), getPosition().getY(), stone.getPosition().getX(), stone.getPosition().getY()));
// if stone intersects with any bounds
if(rectBall.intersects(rectStone.getBounds())) {
// corner intersections
if((rectBall.intersects(leftBorder) || rectBall.intersects(rightBorder)) && (rectBall.intersects(topBorder) || rectBall.intersects(bottomBorder))) {
// intersections as Rectangle's
Rectangle intersTop = rectBall.intersection(topBorder);
Rectangle intersBottom = rectBall.intersection(bottomBorder);
Rectangle intersLeft = rectBall.intersection(leftBorder);
Rectangle intersRight = rectBall.intersection(rightBorder);
// rectangles as area to determine corner
double areaIntersTop = intersTop.getHeight() * intersTop.getWidth();
double areaIntersBottom = intersBottom.getHeight() * intersBottom.getWidth();
double areaIntersLeft = intersLeft.getHeight() * intersLeft.getWidth();
double areaIntersRight = intersRight.getHeight() * intersRight.getWidth();
//System.out.printf("ut, ub, ul, ur: %s %s %s %s\r\n", areaIntersTop, areaIntersBottom, areaIntersLeft, areaIntersRight);
// top side
if(areaIntersTop > 0) {
// left|right border
if(areaIntersLeft > areaIntersTop || areaIntersRight > areaIntersTop) direction.setDx(-getDirection().getDx());
// top border
else direction.setDy(-getDirection().getDy());
}
// bottom side
if(areaIntersBottom > 0) {
// left|right border
if(areaIntersLeft > areaIntersBottom || areaIntersRight > areaIntersBottom) direction.setDx(-getDirection().getDx());
// bottom border
else direction.setDy(-getDirection().getDy());
}
// return; intersection already handled
return;
}
// vertical bounds
if(rectBall.intersects(leftBorder) || rectBall.intersects(rightBorder)) {
//System.out.println("left|right border");
direction.setDx(-getDirection().getDx());
}
// horizontal bounds
if(rectBall.intersects(topBorder) || rectBall.intersects(bottomBorder)) {
//System.out.println("top|bottom border");
direction.setDy(-getDirection().getDy());
}
}
}
/**
* The getter for balls lost state
* @return balls lost state
*/
public boolean isLost() {
return isLost;
}
/**
* The setter for balls lost state
* @param lost balls lost state
*/
public void setLost(boolean lost) {
isLost = lost;
}
/**
* resets balls position
*/
public void resetPosition() {
// start at bottom-center
position.setX((Constants.SCREEN_WIDTH - Constants.BALL_DIAMETER) / 2.0);
position.setY(Constants.SCREEN_HEIGHT - Constants.BALL_DIAMETER - Constants.PADDLE_HEIGHT);
}
/**
* resets balls direction
*/
public void resetDirection() {
direction = new Vector2D(Constants.BALL_SPEED, Constants.BALL_SPEED);
direction.rescale();
}
}

@ -36,7 +36,7 @@ public class Game {
/**
* The last levelnumber
*/
private int maxLevel = 1;
private int maxLevel = 3;
/**
* The total score of the game
@ -114,7 +114,7 @@ public class Game {
controller.toPlayground();
} else {
// tells the controller to switch to the startScreen of the game
controller.toStartScreen();
controller.toStartScreen(level.getScore());
}

@ -1,5 +1,7 @@
package break_out.model;
import java.util.ArrayList;
public interface IBall {
// Exercise 1
@ -11,4 +13,11 @@ public interface IBall {
// Exercise 2
public boolean hitsPaddle(Paddle paddle);
public void reflectOnPaddle(Paddle paddle);
// Exercise 4
public boolean hitsStone(ArrayList<Stone> stones);
public Stone getHitStone();
// Exercise 5
public boolean isLost();
}

@ -1,8 +1,18 @@
package break_out.model;
import java.util.ArrayList;
public interface ILevel {
// Exercise 1
public Ball getBall();
// Exercise 2
public Paddle getPaddleTop();
public Paddle getPaddleBottom();
// Exercise 3
public void setFinished(boolean finished);
// Exercise 4
public ArrayList<Stone> getStones();
}

@ -9,9 +9,13 @@ public interface IPaddle {
public void setPosition(Position position);
public Color getColor();
public void setColor(Color color);
public double getWidth();
public void setWidth(double width);
public double getHeight();
public void setHeight(double height);
public int getWidth();
public void setWidth(int width);
public int getHeight();
public void setHeight(int height);
// Exercise 3
public int getDirection();
public void setDirection(int direction);
public void updatePosition(Ball ball);
}

@ -0,0 +1,17 @@
package break_out.model;
import java.awt.*;
public interface IStone {
// Exercise 3
public int getType();
public int getValue();
public Color getColor();
public Position getPosition();
public void setType(int type);
public void setValue(int value);
public void setColor(Color color);
public void setPosition(Position position);
}

@ -2,6 +2,9 @@ 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
@ -34,13 +37,28 @@ public class Level extends Thread implements ILevel {
/**
* Flag that shows if the ball was started
*/
private boolean ballWasStarted = true;
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
@ -55,13 +73,11 @@ public class Level extends Thread implements ILevel {
this.score = score;
this.ball = new Ball();
// 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);
resetPaddles();
// set paddles
this.paddleTop = new Paddle(posPaddleTop);
this.paddleBottom = new Paddle(posPaddleBottom);
// set paddles color
this.paddleTop.setColor(Constants.COLOR_PADDLE_TOP);
this.paddleBottom.setColor(Constants.COLOR_PADDLE_BOTTOM);
loadLevelData(levelnr);
}
@ -105,19 +121,51 @@ public class Level extends Thread implements ILevel {
game.notifyObservers();
// endless loop
while (true) {
while (!finished) {
// if ballWasStarted is true, the ball is moving
if (ballWasStarted) {
if (ballWasStarted()) {
// Call here the balls method for updating his position on the playground
this.ball.updatePosition();
getBall().updatePosition();
// Call here the balls method for reacting on the borders of the playground
this.ball.reactOnBorder();
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(this.ball.hitsPaddle(paddleTop)) this.ball.reflectOnPaddle(paddleTop);
if(this.ball.hitsPaddle(paddleBottom)) this.ball.reflectOnPaddle(paddleBottom);
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
@ -139,7 +187,35 @@ public class Level extends Thread implements ILevel {
* @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);
}
}
}
/**
@ -160,6 +236,115 @@ public class Level extends Thread implements ILevel {
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);
}
if(allStonesBroken()) {
setFinished(true);
nextLevel();
}
}
/**
* 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().resetDirection();
getBall().setLost(false);
stopBall();
// level failed
} else {
setFinished(true);
game.getController().toStartScreen(getScore());
}
}
/**
* 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;
}
/**
* switch to next level
*/
public void nextLevel() {
game.createLevel(++levelnr, score);
}
}