1
0
Fork 0

Compare commits

...

53 Commits
A1.1 ... master

Author SHA1 Message Date
rxbn_ 2a27f74846 BreakOut 5 - reset direction 2020-02-04 21:24:35 +01:00
rxbn_ 5a5d661719 BreakOut 5 - new Level design and layout 2020-02-04 20:46:47 +01:00
rxbn_ 05a4463ba8 BreakOut 5.4 2020-02-03 23:35:01 +01:00
rxbn_ 59c2f83f49 BreakOut 5.3 2020-02-03 23:34:20 +01:00
rxbn_ 59fdc12e4f BreakOut 5.2 - methods are now written according to specifications to pass JUnit tests 2020-02-01 09:50:56 +01:00
rxbn_ 90afe2d72e BreakOut 5.2 - Scoreboard 2020-01-30 21:23:00 +01:00
rxbn_ 21a7b951d6 BreakOut 5.1 - b), c) 2020-01-30 19:15:16 +01:00
rxbn_ 5ea292bbae BreakOut 5.1 - a) 2020-01-30 19:10:49 +01:00
rxbn_ b51c1c4f62 BreakOut 5.* Vorgabe 2020-01-28 13:23:40 +01:00
rxbn_ f6e8e6fcc5 minor comments and refactoring in break_out.model.Level 2020-01-25 00:01:15 +01:00
rxbn_ 87048abd6f Aufgabe 3 Feedback - minor fixes 2020-01-23 18:45:36 +01:00
rxbn_ 49f431c236 neue Abgabegruppe - 262 2020-01-16 11:05:05 +01:00
rxbn_ 041092f121 quick fix - JavaDoc 2020-01-05 14:46:43 +01:00
rxbn_ 8668f6e2b5 minor fix - longer paddles - game design decision 2020-01-05 14:41:35 +01:00
rxbn_ 9210e43b6a Aufgabe 4.4 - updateStonesAndScore, allStonesBroken 2020-01-05 14:40:52 +01:00
rxbn_ 2102f5c27b Aufgabe 4.3 - hitsStone, reflectOnStone 2020-01-05 14:14:31 +01:00
rxbn_ 0fdd579b41 Aufgabe 4.2 - drawStones 2019-12-31 15:41:10 +01:00
rxbn_ 669c37029a minor fixes 2019-12-31 15:21:40 +01:00
rxbn_ 2870a5fc9a Aufgabe 4.1 - loadLevelData 2019-12-30 16:43:24 +01:00
rxbn_ 1b829fba1e BreakOut 4.* Vorgabe 2019-12-30 16:04:19 +01:00
rxbn_ 4bec1047ed Aufgabe 3.4 2019-12-19 17:44:50 +01:00
rxbn_ 94a394438d Aufgabe 3.3 2019-12-17 22:15:00 +01:00
rxbn_ 0548e10e6b Aufgabe 3.2 2019-12-17 21:26:34 +01:00
rxbn_ ba286f548f Aufgabe 3.1 2019-12-17 20:38:47 +01:00
rxbn_ 9182e79f6b BreakOut 3.* Vorgabe - missing IStone.java 2019-12-17 20:37:54 +01:00
rxbn_ 4fe42792ee BreakOut 3.* Vorgabe + Implementation 2019-12-17 18:10:30 +01:00
rxbn_ ce770c9cc7 fix - Ball - reflectOnPaddle - wrong estimation and therefore no bottom paddle behaviour 2019-12-15 07:27:18 +01:00
rxbn_ 341aa10277 fix - createRelease - wrong file prefix 2019-12-14 12:38:40 +01:00
rxbn_ c21af90605 Ball - no blue colors according to constant GAME_BACKGROUND to prevent ghosting 2019-12-13 01:51:03 +01:00
rxbn_ 463b562645 Field - grid color with alpha value 2019-12-13 01:35:49 +01:00
rxbn_ 7b416c205e Field - game background as a constant 2019-12-13 01:30:05 +01:00
rxbn_ 584d33ae07 quick fix - first draw grid then ball 2019-12-13 01:16:04 +01:00
rxbn_ 46e689dec3 ball - new color when ball hits paddle 2019-12-13 01:14:58 +01:00
rxbn_ 087650adc8 documentation - correct javadoc for paddle constructor 2019-12-13 00:41:14 +01:00
rxbn_ 75ee56adce custom color for paddles 2019-12-12 19:20:52 +01:00
rxbn_ e782ad2017 general - correct authors 2019-12-08 00:15:20 +01:00
rxbn_ 131dedb22e Ball - reflectOnPaddle - structuring and comments 2019-12-07 23:58:50 +01:00
Moritz Henseleit af40f082d6 message 2019-12-07 23:21:22 +01:00
rxbn_ 1a18e469ca Ball - hitsPaddle update 2019-12-07 17:24:39 +01:00
rxbn_ 8af4e653b2 Vector2D - rescaling fix - zero issue 2019-12-07 17:09:56 +01:00
rxbn_ 010cb5853a Aufgabe 2.2 - Vector2D constructor 2019-12-06 19:06:51 +01:00
rxbn_ 78159521c7 Aufgabe 2.2 - hitsPaddle(Paddle p) - tests whether the ball touches the paddle's hit box. 2019-12-03 00:03:36 +01:00
rxbn_ dcc68e837a Aufgabe 2 - neue Vorgabe fuer IBall + basic implementation 2019-12-02 22:51:46 +01:00
rxbn_ 7ba9618f63 README.md - mail fix 2019-12-01 21:58:53 +01:00
Ruben Meyer d2bcd4bc7e Update 'README.md'
correct syntax for new line
2019-12-01 17:55:15 +00:00
rxbn_ 8b61a4f022 Better README.md 2019-12-01 18:50:55 +01:00
rxbn c9f87ace17 Aufgabe 2.1 + reindent project 2019-12-01 18:39:53 +01:00
rxbn 1f5c6edd03 reindent project 2019-12-01 17:39:37 +01:00
rxbn a8982fc940 Breakout 2.* Vorgabe 2019-12-01 17:28:54 +01:00
rxbn 7a4bad32f6 comments: updated authors and group member notation 2019-11-27 23:05:33 +01:00
rxbn 2b166f4835 script to create release 2019-11-27 12:43:56 +01:00
rxbn 10ec639943 Breakout Aufgabe 1 - Fehlerkorrektur 2019-11-26 23:45:59 +01:00
Moritz Henseleit 3d74d9e5e0 updated 2019-11-22 15:56:57 +01:00
25 changed files with 1935 additions and 420 deletions

View File

@ -0,0 +1,15 @@
# Breakout Projekt
- Einführung in die Programmierung WS19/20
- Programmieren des Spieles "Breakout" basierend auf dem Framework des Instituts
# 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)

32
createRelease.sh Executable file
View File

@ -0,0 +1,32 @@
#!/usr/bin/env zsh
# project prefix
PREFIX="262-BreakOutA"
# get versioning
echo -n "Type your tag version for '$PREFIX' (like (2.1) followed by [ENTER] for ${PREFIX}2.1): "
read VERSION
echo "Your version: ${PREFIX}${VERSION}"
# to CTRL-C
echo -n "Press any key to continue..."
read -n 1
if [ -d "./src/break_out" ] && [ -f ".gitignore" ];
then
ln -s ./ "${PREFIX}${VERSION}" # create temporary soft link
#update .project version
xmlstarlet edit -L -u "//projectDescription/name" -v "${PREFIX}${VERSION}" .project
# file list
FILELIST=('.idea' 'doc' 'libs' 'res' 'src' '.classpath' '.project' 'README.md')
for i in "${FILELIST[@]}"; do
zip -r "${PREFIX}${VERSION}".zip "./${PREFIX}${VERSION}/${i}"
done
rm "${PREFIX}${VERSION}" # remove soft link
echo "Have fun"
else
echo "You are not in the correct working directory"
fi

View File

@ -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
}

33
res/Level2.json Normal file
View File

@ -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
}

33
res/Level3.json Normal file
View File

@ -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
}

View File

@ -1,78 +1,129 @@
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 {
/**
* The screen width in pixels
*/
public static final Integer SCREEN_WIDTH = 880;
/**
* The screen width in pixels
*/
public static final Integer SCREEN_WIDTH = 880;
/**
* The screen height in pixels
*/
public static final Integer SCREEN_HEIGHT = 750;
/**
* The screen height in pixels
*/
public static final Integer SCREEN_HEIGHT = 750;
/**
* the application name
*/
public static final String APP_TITLE = "BreakOut";
/**
* the application name
*/
public static final String APP_TITLE = "BreakOut";
/**
* Debugging flag for special rendering hints
*/
public static final boolean DEBUG_MODE = false;
/**
* Debugging flag for special rendering hints
*/
public static final boolean DEBUG_MODE = false;
/**
* The background color for the game menu
*/
public static final Color BACKGROUND = new Color(52, 152, 219);
/**
* The background color for the game menu
*/
public static final Color BACKGROUND = new Color(52, 152, 219);
/**
* Amount of columns for blocks
*/
public static final Integer SQUARES_X = 22;
/**
* Amount of columns for blocks
*/
public static final Integer SQUARES_X = 22;
/**
* Amount of the rows
*/
public static final Integer SQUARES_Y = 30;
/**
* Amount of the rows
*/
public static final Integer SQUARES_Y = 30;
/**
* The paddle width in pixels
*/
public static final Integer PADDLE_WIDTH = 70;
/**
* The paddle width in pixels
*/
public static final Integer PADDLE_WIDTH = 90;
/**
* The paddle height in pixels
*/
public static final Integer PADDLE_HEIGHT = 15;
/**
* The paddle height in pixels
*/
public static final Integer PADDLE_HEIGHT = 15;
/**
* The distance between paddle and the lower reflection offset.
*/
public static final Double REFLECTION_OFFSET = 25.0;
/**
* The distance between paddle and the lower reflection offset.
*/
public static final Double REFLECTION_OFFSET = 25.0;
/**
* The ball diameter in pixels
*/
public static final Integer BALL_DIAMETER = 15;
/**
* The ball diameter in pixels
*/
public static final Integer BALL_DIAMETER = 15;
/**
* The paddle speed
*/
public static final Double DX_MOVEMENT = 4.5;
/**
* The paddle speed
*/
public static final Double DX_MOVEMENT = 4.5;
/**
* The ball speed
*/
public static final Double BALL_SPEED = 1.20;
/**
* The ball speed
*/
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);
}

View File

@ -6,15 +6,14 @@ import break_out.view.View;
/**
* The entry point of the program. The game get started here and all components
* are initialized here.
*
*
* @author dmlux, modified by I. Schumacher
*
*/
public class Main {
/**
* The main method
*
*
* @param args The arguments that were passed by the command line.
*/
public static void main(String[] args) {

View File

@ -13,9 +13,8 @@ import break_out.view.View;
/**
* The controller takes care of the input events and reacts on those events by
* manipulating the view and updates the model.
*
* @author dmlux, modified by I. Schumacher and I. Traupe
*
*
* @author dmlux, modified by I. Schumacher and I. Traupe, modified by Gruppe 175 (Moritz Henseleit, Ruben Meyer)
*/
public class Controller implements ActionListener, KeyListener {
@ -31,9 +30,8 @@ public class Controller implements ActionListener, KeyListener {
/**
* The constructor expects a view to construct itself.
*
* @param view
* The view that is connected to this controller
*
* @param view The view that is connected to this controller
*/
public Controller(View view) {
this.view = view;
@ -101,37 +99,76 @@ public class Controller implements ActionListener, KeyListener {
/**
* This method will be called, after a key was typed. This means, that the key
* was pressed and released, before this method get called.
*
* @param e The key event
*/
@Override
public void keyTyped(KeyEvent e) {
}
/**
* This method will be called, after a key was pressed down.
*
* @param e The key event
*/
@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;
}
}
/**
* This method will be called, after a key was released.
*
* @param e The key event
*/
@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();
}
/**

View File

@ -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();
}
}
}

View File

@ -2,81 +2,406 @@ 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
*
* @author iSchumacher
* @author modified by 175
*
* @author iSchumacher; modified by Gruppe 175 (Moritz Henseleit, Ruben Meyer)
*/
public class Ball implements IBall{
public class Ball implements IBall {
/**
* The balls position on the playground
*/
private Position position;
/**
* The balls direction
*/
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/2);
this.position.setY(Constants.SCREEN_HEIGHT-3*Constants.BALL_DIAMETER);
// reset direction
resetDirection();
// reset position to bottom-center
resetPosition();
}
/**
* The getter for the balls position
*
* @return position The balls current position
*/
public Position getPosition() {
return this.position;
}
/**
* The getter for the balls direction
*
* @return direction The balls current direction
*/
public Vector2D getDirection() {
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
*/
public void updatePosition() {
// sets X position
this.position.setX(this.position.getX()+this.direction.getDx());
this.position.setX(this.position.getX() + this.direction.getDx());
// sets Y position
this.position.setY(this.position.getY()+this.direction.getDy());
// sets Y position
this.position.setY(this.position.getY() + this.direction.getDy());
}
/**
* Ball reacts to contact with the borders
*/
public void reactOnBorder() {
// reacts on left border
if(this.position.getX() < 0) this.direction.setDx(-(this.direction.getDx()));
// reacts on left border
if (this.position.getX() <= 0) {
this.position.setX(0);
this.direction.setDx(-(this.direction.getDx()));
}
// reacts on right border (+Diameter because of hitbox)
if(this.position.getX()+Constants.BALL_DIAMETER > Constants.SCREEN_WIDTH) this.direction.setDx(-(this.direction.getDx()));
// reacts on right border (-Diameter because of hitbox)
if (this.position.getX() >= Constants.SCREEN_WIDTH - Constants.BALL_DIAMETER) {
this.position.setX(Constants.SCREEN_WIDTH - Constants.BALL_DIAMETER);
this.direction.setDx(-(this.direction.getDx()));
}
// reacts on top border
if(this.position.getY() < 0) this.direction.setDy(-(this.direction.getDy()));
// reacts on top border
if (this.position.getY() <= 0) {
isLost = true;
}
// reacts on bottom border (+Diameter because of hitbox)
if(this.position.getY()+Constants.BALL_DIAMETER > Constants.SCREEN_HEIGHT) this.direction.setDy(-(this.direction.getDy()));
// reacts on bottom border (+Diameter because of hitbox)
if (this.position.getY() >= Constants.SCREEN_HEIGHT - Constants.BALL_DIAMETER) {
isLost = true;
}
}
/**
* tests whether the ball touches the paddle's hit box.
* @param paddle paddle which will be tested
* @return true when ball hits the paddle
*/
public boolean hitsPaddle(Paddle paddle) {
// paddles position
Position posPaddle = paddle.getPosition();
// balls position
Position posBall = this.getPosition();
// test balls y position against paddles y values
// paddles y values can be interpreted as a closed interval therefore if balls y position is in the interval, its true
boolean testPaddleY = (
posPaddle.getY() <= posBall.getY() && posBall.getY() <= posPaddle.getY()+paddle.getHeight() ||
posPaddle.getY() <= posBall.getY()+Constants.BALL_DIAMETER && posBall.getY()+Constants.BALL_DIAMETER <= posPaddle.getY()+paddle.getHeight()
);
// test balls x position against paddles x values
// paddles x values can be interpreted as a closed interval therefore if balls x position is in the interval, its true
boolean testPaddleX = (
posPaddle.getX() <= posBall.getX() && posBall.getX() <= posPaddle.getX()+paddle.getWidth() ||
posPaddle.getX() <= posBall.getX()+Constants.BALL_DIAMETER && posBall.getX()+Constants.BALL_DIAMETER <= posPaddle.getX()+paddle.getWidth()
);
// if balls y position is in paddles y values, verify x position
if(testPaddleY) {
// DEBUG OUTPUT
//System.out.println("ball is in y area of paddle: "+String.format("x, y, w, h: %s, %s, %s, %s", posPaddle.getX(), posPaddle.getY(), paddle.getWidth(), paddle.getHeight()));
// if ball is in paddles hit box
if(testPaddleX) {
// DEBUG OUTPUT
//System.out.println("ball hits paddle: "+String.format("x, y, w, h: %s, %s, %s, %s", posPaddle.getX(), posPaddle.getY(), paddle.getWidth(), paddle.getHeight()));
return true;
}
}
// default output, ball doesn't hit paddle
return false;
}
/**
* Ball got hit by Paddle paddle
* @param paddle hitbox mechanism of paddle
*/
public void reflectOnPaddle(Paddle paddle) {
// reflection point / offset point
Position reflectionPoint = new Position(
paddle.getPosition().getX() + (paddle.getWidth() / 2.0),
paddle.getPosition().getY() + (paddle.getHeight() / 2.0)
);
// new direction vector; assignment not here
Vector2D reflectionVector;
// no general solution, estimation required
// 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/2.0) {
// top paddle
reflectionPoint.setY(reflectionPoint.getY() - Constants.REFLECTION_OFFSET);
} else {
// bottom paddle
reflectionPoint.setY(reflectionPoint.getY() + Constants.REFLECTION_OFFSET);
}
// calculating the center of the ball; needed for correct vector calculation
Position ballCenter = new Position(
position.getX() + (Constants.BALL_DIAMETER/2.0),
position.getY() + (Constants.BALL_DIAMETER/2.0)
);
// The direction is set to the vector between offset point and the ball's center
reflectionVector = new Vector2D(reflectionPoint, ballCenter);
// normalize vector
reflectionVector.rescale();
// 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();
}
}

View File

@ -8,9 +8,8 @@ import break_out.view.View;
/**
* This class contains information about the game (the model in MVC)
*
* @author dmlux, modified by I. Schumacher
*
*
* @author dmlux, modified by I. Schumacher, modified by Gruppe 175 (Moritz Henseleit, Ruben Meyer)
*/
public class Game {
@ -37,7 +36,7 @@ public class Game {
/**
* The last levelnumber
*/
private int maxLevel = 1;
private int maxLevel = 3;
/**
* The total score of the game
@ -46,9 +45,8 @@ public class Game {
/**
* The constructor creates a new game instance with the given Controller
*
* @param controller
* The controller to manage this instance (MVC-patter)
*
* @param controller The controller to manage this instance (MVC-patter)
*/
public Game(Controller controller) {
this.controller = controller;
@ -72,7 +70,7 @@ public class Game {
/**
* Getter for the Controller
*
*
* @return controller The controller of this game
*/
public Controller getController() {
@ -81,7 +79,7 @@ public class Game {
/**
* Getter for the current Level
*
*
* @return level The current level of the game
*/
public Level getLevel() {
@ -90,7 +88,7 @@ public class Game {
/**
* Getter for the total score
*
*
* @return score The current score of the game
*/
public int getScore() {
@ -101,11 +99,9 @@ public class Game {
* Creates the first or the next level, if the level number is less or equal
* maxLevel. If the current level is higher than maxLevel the view will be
* switched to the startScreen.
*
* @param levelnr
* The number for the next level
* @param score
* The current players score after finishing the previous level.
*
* @param levelnr The number for the next level
* @param score The current players score after finishing the previous level.
*/
public void createLevel(int levelnr, int score) {
this.score = score;
@ -118,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());
}

View File

@ -1,10 +1,23 @@
package break_out.model;
import java.util.ArrayList;
public interface IBall {
// Exercise 1
public void updatePosition();
public void reactOnBorder();
public Position getPosition();
public Vector2D getDirection();
}
// Exercise 1
public void updatePosition();
public void reactOnBorder();
public Position getPosition();
public Vector2D getDirection();
// 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();
}

View File

@ -0,0 +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();
}

View File

@ -0,0 +1,21 @@
package break_out.model;
import java.awt.*;
public interface IPaddle {
// Exercise 2
public Position getPosition();
public void setPosition(Position position);
public Color getColor();
public void setColor(Color color);
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);
}

View File

@ -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);
}

View File

@ -2,11 +2,11 @@ package break_out.model;
public interface IVector2D {
// Exercise 1
public double getDx();
public void setDx(double dx);
public double getDy();
public void setDy(double dy);
// Exercise 1
public double getDx();
public void setDx(double dx);
public double getDy();
public void setDy(double dy);
public void rescale();
public void rescale();
}

View File

@ -1,125 +1,350 @@
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
*
*
* @author dmlux
* @author I. Schumacher
* @author modified by 175
* @author I. Schumacher; modified by Gruppe 175 (Moritz Henseleit, Ruben Meyer)
*/
public class Level extends Thread {
public class Level extends Thread implements ILevel {
/**
* The game to which the level belongs
*/
private Game game;
/**
* The number of the level
*/
private int levelnr;
/**
/**
* The game to which the level belongs
*/
private Game game;
/**
* The number of the level
*/
private int levelnr;
/**
* The score of the level
*/
private int score;
/**
* The ball of the level
*/
private Ball ball;
/**
* Flag that shows if the ball was started
*/
private boolean ballWasStarted = true;
/**
* 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
* @param game The game object
* @param levelnr The number of the new level object
* @param score The score
*/
public Level(Game game, int levelnr, int score) {
this.game = game;
this.levelnr = levelnr;
this.score = score;
this.ball = new Ball();
loadLevelData(levelnr);
}
private int score;
/**
* The getter for the ball object
* @return ball The ball of the level
*/
public Ball getBall() {
return this.ball;
}
/**
* Sets ballWasStarted to true, the ball is moving
*/
public void startBall() {
ballWasStarted = true;
}
/**
* The ball of the level
*/
private Ball ball;
/**
* Sets ballWasStarted to false, the ball is stopped
*/
public void stopBall() {
ballWasStarted = false;
}
/**
* Returns if the ball is moving or stopped
* @return ballWasStarted True: the ball is moving; false: the ball is stopped
*/
public boolean ballWasStarted() {
return ballWasStarted;
}
/**
* Flag that shows if the ball was started
*/
private boolean ballWasStarted = false;
/**
* The method of the level thread
*/
public void run() {
game.notifyObservers();
// endless loop
while (true) {
// if ballWasStarted is true, the ball is moving
if (ballWasStarted) {
// Call here the balls method for updating his position on the playground
this.ball.updatePosition();
// Call here the balls method for reacting on the borders of the playground
this.ball.reactOnBorder();
// Tells the observer to repaint the components on the playground
game.notifyObservers();
}
// The thread pauses for a short time
try {
Thread.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* Loads the information for the level from a json-file located in the folder /res of the project
* @param levelnr The number X for the LevelX.json file
*/
private void loadLevelData(int levelnr) {
}
/**
* 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
*
* @param game The game object
* @param levelnr The number of the new level object
* @param score The score
*/
public Level(Game game, int levelnr, int score) {
this.game = game;
this.levelnr = levelnr;
this.score = score;
this.ball = new Ball();
resetPaddles();
// set paddles color
this.paddleTop.setColor(Constants.COLOR_PADDLE_TOP);
this.paddleBottom.setColor(Constants.COLOR_PADDLE_BOTTOM);
loadLevelData(levelnr);
}
/**
* The getter for the ball object
*
* @return ball The ball of the level
*/
public Ball getBall() {
return this.ball;
}
/**
* Sets ballWasStarted to true, the ball is moving
*/
public void startBall() {
ballWasStarted = true;
}
/**
* Sets ballWasStarted to false, the ball is stopped
*/
public void stopBall() {
ballWasStarted = false;
}
/**
* Returns if the ball is moving or stopped
*
* @return ballWasStarted True: the ball is moving; false: the ball is stopped
*/
public boolean ballWasStarted() {
return ballWasStarted;
}
/**
* The method of the level thread
*/
public void run() {
game.notifyObservers();
// endless loop
while (!finished) {
// if ballWasStarted is true, the ball is moving
if (ballWasStarted()) {
// Call here the balls method for updating his position on the playground
getBall().updatePosition();
// Call here the balls method for reacting on the borders of the playground
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(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
game.notifyObservers();
}
// The thread pauses for a short time
try {
Thread.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* Loads the information for the level from a json-file located in the folder /res of the project
*
* @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);
}
}
}
/**
* The getter for the top paddle object
*
* @return paddleTop The top paddle of the level
*/
public Paddle getPaddleTop() {
return paddleTop;
}
/**
* The getter for the bottom paddle object
*
* @return paddleBottom The bottom paddle of the level
*/
public Paddle getPaddleBottom() {
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);
}
}

View File

@ -0,0 +1,171 @@
package break_out.model;
import break_out.Constants;
import java.awt.*;
/**
* This class contains the information about the paddles characteristics and behavior
*
* @author Gruppe 175: Moritz Henseleit, Ruben Meyer
*/
public class Paddle implements IPaddle {
/**
* The paddles position on the playground
*/
private Position position;
/**
* The paddles direction on the playground
* only -1,0,+1 are valid values
*/
private int direction;
/**
* The paddles sizing
*/
private int width;
private int height;
/**
* The paddles color
*/
private Color color;
/**
* The constructor of a paddle
*
* @param position paddles initial position
*/
public Paddle(Position position) {
this.position = position;
// set sizing
width = Constants.PADDLE_WIDTH;
height = Constants.PADDLE_HEIGHT;
// set color
color = Color.CYAN;
}
/**
* The getter for the paddles position
*
* @return position The paddles current position
*/
public Position getPosition() {
return position;
}
/**
* The setter for the paddles position
*
* @param position The paddles new position
*/
public void setPosition(Position position) {
this.position = position;
}
/**
* The getter for the paddles color
*
* @return color The paddles current color
*/
public Color getColor() {
return color;
}
/**
* The setter for the paddles color
*
* @param color The paddles new color
*/
public void setColor(Color color) {
this.color = color;
}
/**
* The getter for the paddles width
*
* @return width The paddles current width
*/
public int getWidth() {
return width;
}
/**
* The setter for the paddles width
*
* @param width The paddles new width
*/
public void setWidth(int width) {
this.width = width;
}
/**
* The getter for the paddles height
*
* @return height The paddles current height
*/
public int getHeight() {
return height;
}
/**
* The setter for the paddles height
*
* @param height The paddles new height
*/
public void setHeight(int height) {
this.height = height;
}
/**
* The getter for the paddles direction
*
* @return direction The paddles current direction
*/
public int getDirection() {
return direction;
}
/**
* The setter for the paddles direction
*
* @param direction The paddles new direction
*/
public void setDirection(int direction) {
// normalization not needed
// normalize to valid values
//if(direction > 0) direction = 1;
//if(direction < 0) direction = -1;
this.direction = direction;
}
/**
* Updates paddles position based on balls position
*
* @param ball The ball
*/
public void updatePosition(Ball ball) {
// move paddle, if it is the nearest paddle
if(ball.getPosition().getY() < Constants.SCREEN_HEIGHT/2.0 && getPosition().getY() < Constants.SCREEN_HEIGHT/2.0 ||
ball.getPosition().getY() > Constants.SCREEN_HEIGHT/2.0 && getPosition().getY() > Constants.SCREEN_HEIGHT/2.0) {
// temporary position to modify x value
Position tmp = getPosition();
// modify x value; getDirection is normalized to the values {-1, 0, 1}
// therefore we can just multiply it with DX_MOVEMENT
tmp.setX(getPosition().getX() + getDirection()*Constants.DX_MOVEMENT);
// out of border boundaries
if(tmp.getX() <= 0) tmp.setX(0);
if(tmp.getX() >= Constants.SCREEN_WIDTH-getWidth()) tmp.setX(Constants.SCREEN_WIDTH-getWidth());
setPosition(tmp);
}
}
}

View File

@ -3,9 +3,8 @@ package break_out.model;
/**
* This class represents a position within the board in pixel coordinates
*
*
* @author dmlux
*
*/
public class Position {
@ -18,10 +17,10 @@ public class Position {
* Y coordinate
*/
private double y;
/**
* The constructor needs a x and y coordinate to be called
*
*
* @param x The x position of the object on the board
* @param y The y position of the object on the board
*/
@ -32,7 +31,7 @@ public class Position {
/**
* Getter for the x-coordinate
*
*
* @return x The x value of this position
*/
public double getX() {
@ -41,6 +40,7 @@ public class Position {
/**
* Setter for the x-coordinate
*
* @param x The new x-coordinate
*/
public void setX(double x) {
@ -49,7 +49,7 @@ public class Position {
/**
* Getter for y-coordinate
*
*
* @return y The y value of the position
*/
public double getY() {
@ -58,10 +58,11 @@ public class Position {
/**
* Setter for the y-coordinate
*
* @param y The new y-coordinate
*/
public void setY(double y) {
this.y = y;
}
}

View File

@ -0,0 +1,147 @@
package break_out.model;
import java.awt.*;
/**
* This class contains information about the stones characteristics and behaviour
*
* @author Gruppe 175: Moritz Henseleit, Rubn Meyer
*/
public class Stone implements IStone {
/**
* The stones type
*/
private int type;
/**
* The stones value according to the stones type to calculate players score
*/
private int value;
/**
* The stones color according to the stones type
*/
private Color color;
/**
* The stones position on the playground
*/
private Position position;
/**
* The constructor of a stone
*
* @param type stones initial type
* @param position stones initial position
*/
public Stone(int type, Position position) {
// sets type; and value and color according to stone type
setType(type);
// sets position
setPosition(position);
}
/**
* The getter for the stones value to calculate players score
*
* @return stones value
*/
public int getValue() {
return this.value;
}
/**
* The setter for the stones value
*
* @param value The stones new value
*/
public void setValue(int value) {
this.value = value;
}
/**
* The getter for the stones color
* Can be null because a stone could not exist
*
* @return The stones color
*/
public Color getColor() {
return this.color;
}
/**
* The setter for the stones color
*
* @param color The stones new color
*/
public void setColor(Color color) {
this.color = color;
}
/**
* The getter for the stones position
*
* @return The stones position
*/
public Position getPosition() {
return this.position;
}
/**
* The setter for the stones position
*
* @param position The stones new position
*/
public void setPosition(Position position) {
this.position = position;
}
/**
* The getter for the stones type
*
* @return The stones type
*/
public int getType() {
return this.type;
}
/**
* The setter for the stones type
*
* @param type The stones new type
*/
public void setType(int type) {
// set the type; no verification needed;
this.type = type;
switch(type) {
// multi-case, hacky, but dont care
case 0:
// nah, isn't a stone
default:
// default case, not in range
// setting to not a stone
setColor(null);
break;
case 1:
// stone type one
setColor(new Color(77, 80, 140));
setValue(1);
break;
case 2:
// stone type two
setColor(new Color(242, 191, 94));
setValue(2);
break;
case 3:
// stone type three
setColor(new Color(242, 80, 65));
setValue(3);
break;
}
}
}

View File

@ -5,9 +5,8 @@ import break_out.model.Position;
/**
* This class represent a two dimensional vector.
*
* @author I. Schumacher
* @author modified by 175
*
* @author I. Schumacher; modified by Gruppe 175 (Moritz Henseleit, Ruben Meyer)
*/
public class Vector2D implements IVector2D {
@ -23,7 +22,7 @@ public class Vector2D implements IVector2D {
/**
* This constructor creates a new vector with the given x and y parts.
*
*
* @param dx the delta x part for the new vector
* @param dy the delty y part for the new vector
*/
@ -32,9 +31,21 @@ public class Vector2D implements IVector2D {
this.dy = dy;
}
/**
* This constructor creates a new vector based on the given positions start and end.
*
* @param start first position
* @param end second position
*/
public Vector2D(Position start, Position end) {
// vector(AB) = (B.x - A.x, B.y - A.y)
this.dx = end.getX() - start.getX();
this.dy = end.getY() - start.getY();
}
/**
* Getter for the dx-part
*
*
* @return dx The dx part of this vector
*/
public double getDx() {
@ -43,7 +54,7 @@ public class Vector2D implements IVector2D {
/**
* Setter for the dx-part
*
*
* @param dx The new dx part of this vector
*/
public void setDx(double dx) {
@ -52,7 +63,7 @@ public class Vector2D implements IVector2D {
/**
* Getter for the dy-part
*
*
* @return dy The dy part of this vector
*/
public double getDy() {
@ -61,7 +72,7 @@ public class Vector2D implements IVector2D {
/**
* Setter for the dy-part
*
*
* @param dy The new dy part of this vector
*/
public void setDy(double dy) {
@ -73,8 +84,10 @@ public class Vector2D implements IVector2D {
*/
public void rescale() {
// calc unit vector and set it
double vectorlength = Math.sqrt(Math.pow(getDx(), 2) + Math.pow(getDy(), 2));
setDx((1/vectorlength) * getDx() * Constants.BALL_SPEED);
setDy((1/vectorlength) * getDy() * Constants.BALL_SPEED);
double vectorLength = Math.sqrt(Math.pow(getDx(), 2) + Math.pow(getDy(), 2)); //using the square root of x and y
// rescaling only needed, if value is not zero
if(getDx() != 0) setDx((1 / vectorLength) * getDx() * Constants.BALL_SPEED);
if(getDy() != 0) setDy((1 / vectorLength) * getDy() * Constants.BALL_SPEED);
}
}

View File

@ -1,21 +1,27 @@
package break_out.view;
import java.awt.Color;
import java.awt.Dimension;
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
* @author modified by 175
*
* @author dmlux, modified by iSchumacher, modified by Gruppe 175 (Moritz Henseleit, Ruben Meyer)
*/
public class Field extends JPanel {
@ -36,14 +42,14 @@ public class Field extends JPanel {
/**
* The constructor needs a view
*
*
* @param view The view of this board
*/
public Field(View view) {
super();
this.view = view;
this.background = new Color(177, 92, 107);
this.background = Constants.COLOR_GAME_BACKGROUND;
setFocusable(true);
@ -61,15 +67,17 @@ public class Field extends JPanel {
/**
* 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
@ -91,43 +99,253 @@ public class Field extends JPanel {
// Setting the background color
g2.setColor(background);
g2.fillRect(0, 0, getWidth(), getHeight());
// Setting the color for the following components
g2.setColor(new Color(200, 200, 200));
// Calls the method for drawing the ball
drawBall(g2);
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) {
// vertical lines
for(int i = 1 ; i < Math.round(Constants.SCREEN_WIDTH/Constants.SQUARES_X); i++) {
g2.drawLine(i*Constants.SQUARES_X, 0, i*Constants.SQUARES_X, Constants.SCREEN_HEIGHT);
// 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);
}
// horizontal lines
for(int i = 1 ; i < Math.round(Constants.SCREEN_HEIGHT/Constants.SQUARES_Y); i++) {
g2.drawLine(0, i*Constants.SQUARES_Y, Constants.SCREEN_WIDTH, i*Constants.SQUARES_Y);
// 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<Stone> 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: <a href="https://stackoverflow.com/questions/18249592/"> Stackoverflow Question - 18249592 </a>
Map<TextAttribute, Object> 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);
}
}

View File

@ -12,134 +12,133 @@ import javax.swing.JPanel;
/**
* This panel represents the background for special divisions in this application
*
*
* @author dmlux
*
*/
public class SectionPanel extends JPanel {
/**
* Automatic generated serial version UID
*/
private static final long serialVersionUID = -7773487090869704154L;
/**
* Automatic generated serial version UID
*/
private static final long serialVersionUID = -7773487090869704154L;
/**
* Color of the panel
*/
private Color color;
/**
* Color of the panel
*/
private Color color;
/**
* Thickness of the border
*/
protected int strokeSize = 1;
/**
* Thickness of the border
*/
protected int strokeSize = 1;
/**
* Color of the shadow
*/
protected Color shadowColor = new Color(50, 50, 50);
/**
* Color of the shadow
*/
protected Color shadowColor = new Color(50, 50, 50);
/**
* Shadow flag
*/
protected boolean shady = true;
/**
* Shadow flag
*/
protected boolean shady = true;
/**
* Double value for the vertical curvature
*/
protected Dimension arcs = new Dimension(10, 10);
/**
* Double value for the vertical curvature
*/
protected Dimension arcs = new Dimension(10, 10);
/**
* Distance of shadow to the panel border
*/
protected int shadowGap = 3;
/**
* Distance of shadow to the panel border
*/
protected int shadowGap = 3;
/**
* Shadow offset
*/
protected int shadowOffset = 3;
/**
* Shadow offset
*/
protected int shadowOffset = 3;
/**
* Shadow transparency
*/
protected int shadowAlpha = 200;
/**
* Shadow transparency
*/
protected int shadowAlpha = 200;
/**
* A constructor for the section panel
*/
public SectionPanel() {
super();
setOpaque(false);
// set background color
this.color = new Color(220, 220, 220);
}
/**
* A constructor for the section panel
*/
public SectionPanel() {
super();
setOpaque(false);
/**
* A constructor that expects a background color for this panel
*
* @param background The background color
*/
public SectionPanel(Color background) {
super();
setOpaque(false);
// set background color
this.color = new Color(220, 220, 220);
}
// set background
this.color = background;
}
/**
* A constructor that expects a background color for this panel
*
* @param background The background color
*/
public SectionPanel(Color background) {
super();
setOpaque(false);
@Override
public void setBackground(Color bg) {
color = bg;
repaint();
}
// set background
this.color = background;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int width = getWidth();
int height = getHeight();
int shadowGap = this.shadowGap;
@Override
public void setBackground(Color bg) {
color = bg;
repaint();
}
Color shadowColorA = new Color(shadowColor.getRed(),
shadowColor.getGreen(), shadowColor.getBlue(), shadowAlpha);
Graphics2D g2 = (Graphics2D) g;
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// Sets antialiasing
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
int width = getWidth();
int height = getHeight();
int shadowGap = this.shadowGap;
// Draws shadow borders if any.
if (shady) {
g2.setColor(shadowColorA);
g2.fillRoundRect(shadowOffset, // X position
shadowOffset, // Y position
width - strokeSize - shadowOffset, // width
height - strokeSize - shadowOffset, // height
arcs.width, arcs.height); // arc Dimension
} else
shadowGap = 1;
Color shadowColorA = new Color(shadowColor.getRed(),
shadowColor.getGreen(), shadowColor.getBlue(), shadowAlpha);
Graphics2D g2 = (Graphics2D) g;
// Draws the rounded opaque panel with borders.
Color c1 = color;
int nr = Math.min((color.getRed() + 40), 255);
int ng = Math.min((color.getGreen() + 40), 255);
int nb = Math.min((color.getBlue() + 40), 255);
Color c2 = new Color(nr, ng, nb);
GradientPaint gradient = new GradientPaint(0, 0, c1, getWidth(),
getHeight(), c2, true);
g2.setPaint(gradient);
g2.fillRoundRect(0, 0, width - shadowGap, height - shadowGap,
arcs.width, arcs.height);
// Sets antialiasing
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(new Color(120, 120, 120));
g2.setStroke(new BasicStroke(strokeSize));
g2.drawRoundRect(0, 0, width - shadowGap, height - shadowGap,
arcs.width, arcs.height);
// Draws shadow borders if any.
if (shady) {
g2.setColor(shadowColorA);
g2.fillRoundRect(shadowOffset, // X position
shadowOffset, // Y position
width - strokeSize - shadowOffset, // width
height - strokeSize - shadowOffset, // height
arcs.width, arcs.height); // arc Dimension
} else
shadowGap = 1;
// Sets strokes to default, is better.
g2.setStroke(new BasicStroke());
}
// Draws the rounded opaque panel with borders.
Color c1 = color;
int nr = Math.min((color.getRed() + 40), 255);
int ng = Math.min((color.getGreen() + 40), 255);
int nb = Math.min((color.getBlue() + 40), 255);
Color c2 = new Color(nr, ng, nb);
GradientPaint gradient = new GradientPaint(0, 0, c1, getWidth(),
getHeight(), c2, true);
g2.setPaint(gradient);
g2.fillRoundRect(0, 0, width - shadowGap, height - shadowGap,
arcs.width, arcs.height);
g2.setColor(new Color(120, 120, 120));
g2.setStroke(new BasicStroke(strokeSize));
g2.drawRoundRect(0, 0, width - shadowGap, height - shadowGap,
arcs.width, arcs.height);
// Sets strokes to default, is better.
g2.setStroke(new BasicStroke());
}
}

View File

@ -16,9 +16,8 @@ import net.miginfocom.swing.MigLayout;
/**
* This screen serves the configuration of the game.
*
*
* @author dmlux, modified by I. Schumacher
*
*/
public class StartScreen extends JPanel {
@ -52,10 +51,15 @@ public class StartScreen extends JPanel {
*/
private JLabel error;
/**
* The scoreMenu
*/
private SectionPanel scoreMenu;
/**
* The constructor needs a view
*
*
* @param view The view of this board
*/
public StartScreen(View view) {
@ -71,7 +75,7 @@ public class StartScreen extends JPanel {
initialize();
}
/**
* Initializes the settings for this screen
*/
@ -126,22 +130,23 @@ public class StartScreen extends JPanel {
*/
private void initializeScoreMenu() {
// The layout
SectionPanel scoreMenu = new SectionPanel(Color.WHITE);
scoreMenu = new SectionPanel(Color.WHITE);
scoreMenu.shady = false;
scoreMenu.setLayout(new MigLayout("", "10[center, grow, fill]10",
"5[center]5"));
// adding the compoenents to the layout
// adding the components to the layout
JLabel headline = new JLabel("Scores");
headline.setFont(new Font("Sans-serif", Font.PLAIN, 16));
headline.setHorizontalAlignment(SwingConstants.CENTER);
scoreMenu.add(headline, "cell 0 0, gaptop 5");
scoreMenu.add(headline, "cell 0 0, gaptop 5, wrap");
add(scoreMenu, "cell 1 0, gapleft 5");
}
/**
* Adds an action listener to the start button
*
* @param l The actionListener
*/
public void addActionListenerToStartButton(ActionListener l) {
@ -150,6 +155,7 @@ public class StartScreen extends JPanel {
/**
* Returns the start button
*
* @return startGame The button for starting the game
*/
public JButton getStartButton() {
@ -158,6 +164,7 @@ public class StartScreen extends JPanel {
/**
* Adds an action listener to the quit button
*
* @param l The actionListener
*/
public void addActionListenerToQuitButton(ActionListener l) {
@ -166,6 +173,7 @@ public class StartScreen extends JPanel {
/**
* Returns the quit button
*
* @return quitGame The button for ending the game
*/
public JButton getQuitButton() {
@ -174,6 +182,7 @@ public class StartScreen extends JPanel {
/**
* Returns the players name
*
* @return The name of the player in the JTextField playersName
*/
public String getPlayersName() {
@ -182,6 +191,7 @@ public class StartScreen extends JPanel {
/**
* Shows an error in the menu
*
* @param message The String to be shown
*/
public void showError(String message) {
@ -195,4 +205,28 @@ public class StartScreen extends JPanel {
error.setText("");
}
/**
* Adds a score to the scoreboard
* @param score
*/
public void addScore(int score) {
// adding the components to the layout
// name
JLabel lName = new JLabel(getPlayersName());
lName.setFont(new Font("Sans-serif", Font.PLAIN, 16));
lName.setHorizontalAlignment(SwingConstants.CENTER);
scoreMenu.add(lName, "gaptop 5");
// spacing
JLabel space = new JLabel();
scoreMenu.add(space);
// score
JLabel lScore = new JLabel(String.valueOf(score));
lScore.setFont(new Font("Sans-serif", Font.PLAIN, 16));
lScore.setHorizontalAlignment(SwingConstants.CENTER);
scoreMenu.add(lScore, "gaptop 5, wrap");
}
}

View File

@ -10,12 +10,10 @@ import break_out.model.Game;
/**
* The view class manages the depiction of the components inside the JFrames. It
* gets the components from the game which is connected to this class
*
* @author dmlux
* @author modified by 175
*
*
* @author dmlux, modified by Gruppe 175 (Moritz Henseleit, Ruben Meyer)
*/
public class View extends JFrame {
public class View extends JFrame {
/**
* Automatic generated serial version UID
@ -42,7 +40,7 @@ public class View extends JFrame {
*/
private Field field;
/**
* The constructor of the view
*/
@ -78,6 +76,7 @@ public class View extends JFrame {
/**
* Getter for the start screen
*
* @return startScreen
*/
public StartScreen getStartScreen() {
@ -86,6 +85,7 @@ public class View extends JFrame {
/**
* Getter for the playground
*
* @return field
*/
public Field getField() {
@ -94,14 +94,16 @@ public class View extends JFrame {
/**
* Getter for the game
*
* @return game
*/
public Game getGame() {
return game;
}
/**
* Setter for the game
*
* @param game The current game
*/
public void setGame(Game game) {
@ -109,9 +111,10 @@ public class View extends JFrame {
this.game = game;
game.addObserver(this);
}
/**
* Shows a given screen if the card layout contains this screen
*
* @param screenName The screen to be shown
*/
public void showScreen(String screenName) {
@ -121,6 +124,7 @@ public class View extends JFrame {
/**
* Called by game.notifyObservers() in the run()-method of Level class
* to repaint the playground
*
* @param game The game to observe
*/
public void modelChanged(Game game) {