36 Commits

Author SHA1 Message Date
Johannes Schmelz
4ecccc5951 Merge branch 'gui' into 'connect'
# Conflicts:
#   Projekte/monopoly/client/src/main/java/pp/monopoly/client/MonopolyApp.java
#   Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/LobbyMenu.java
#   Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/popups/BuildingPropertyCard.java
#   Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/popups/BuyCard.java
#   Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/popups/FoodFieldCard.java
#   Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/popups/GateFieldCard.java
#   Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/popups/WinnerPopUp.java
#   Projekte/monopoly/model/src/main/java/pp/monopoly/game/client/ClientGameLogic.java
2024-11-25 02:45:02 +00:00
Johannes Schmelz
f90ce5aa81 all button sounds now 2024-11-25 03:35:32 +01:00
Yvonne Schmidt
4a9eba255b restyled selector 2024-11-25 03:24:00 +01:00
Johannes Schmelz
4713a526b3 Merge branch 'connect' of https://athene2.informatik.unibw-muenchen.de/progproj/gruppen-ht24/Gruppe-02 into connect 2024-11-25 03:08:01 +01:00
Johannes Schmelz
362c0e5679 added serialisables 2024-11-25 03:07:57 +01:00
Yvonne Schmidt
fab2457715 added header to CreateGameMenu 2024-11-25 02:51:43 +01:00
Yvonne Schmidt
7b3f31f099 Merge remote-tracking branch 'origin/connect' into connect
# Conflicts:
#	Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/CreateGameMenu.java
2024-11-25 02:48:26 +01:00
Johannes Schmelz
ed105f1b70 cleanup 2024-11-25 02:43:58 +01:00
Yvonne Schmidt
cd4331aee3 added header to CreateGameMenu 2024-11-25 02:43:08 +01:00
Yvonne Schmidt
acc797f2ff Merge remote-tracking branch 'origin/connect' into connect 2024-11-25 02:12:01 +01:00
Yvonne Schmidt
853c32a5b8 fixed Buttons 2024-11-25 02:11:05 +01:00
Johannes Schmelz
72bef7143a serialize messages 2024-11-25 02:05:56 +01:00
Yvonne Schmidt
b1ed571950 added background to CreateGameMenu 2024-11-25 02:01:38 +01:00
Johannes Schmelz
1a75d6d6a8 buttons now work as intended 2024-11-25 01:51:27 +01:00
Yvonne Schmidt
c990e7b562 added button sounds 2024-11-25 01:50:52 +01:00
Johannes Schmelz
c87406f60e fixed esc menu 2024-11-25 00:52:10 +01:00
Johannes Schmelz
21914a1294 fixed startmenu 2024-11-25 00:33:05 +01:00
Johannes Schmelz
a344145732 fixed sounds 2024-11-25 00:28:42 +01:00
Yvonne Schmidt
a27ac31086 Merge remote-tracking branch 'origin/connect' into connect 2024-11-25 00:24:43 +01:00
Yvonne Schmidt
9a7f75b76b added effect sound slider 2024-11-25 00:24:25 +01:00
Johannes Schmelz
3e487c00d5 accidentally deleted volumeSlider 2024-11-24 23:29:59 +01:00
Johannes Schmelz
4820b8cf46 added looser popup 2024-11-24 23:28:04 +01:00
Johannes Schmelz
caa4cb5262 winner popup 2024-11-24 23:23:56 +01:00
Johannes Schmelz
1b2a7d73b5 extend dialog 2024-11-24 22:41:53 +01:00
Johannes Schmelz
55778dbcea removed the buttons on start 2024-11-24 22:29:19 +01:00
Johannes Schmelz
422faec281 send player ready 2024-11-24 22:06:19 +01:00
Johannes Schmelz
dcf10e0819 automatically join lobby when selfhosting 2024-11-24 21:36:03 +01:00
Johannes Schmelz
6b78733a5d fixed server join 2024-11-24 21:30:18 +01:00
Johannes Schmelz
c124a99901 fixed screen size 2024-11-24 21:29:41 +01:00
Johannes Schmelz
d7df4002da lobby menu 2024-11-24 21:01:57 +01:00
Johannes Schmelz
8b0ef97a82 connect menu cow working 2024-11-24 20:52:29 +01:00
Johannes Schmelz
75d3bef5c8 move start menu 2024-11-24 20:42:07 +01:00
Johannes Schmelz
c2d5611ab9 changed settings menu to match 2024-11-24 19:10:59 +01:00
Johannes Schmelz
fb28f3fefc tmp settings menu fix 2024-11-24 19:02:56 +01:00
Johannes Schmelz
6a34dab00c changed app to match battleship 2024-11-24 18:27:41 +01:00
Johannes Schmelz
c7bd7d18b7 removed bodged server connection 2024-11-24 18:03:22 +01:00
229 changed files with 3658 additions and 13355 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 518 KiB

View File

@@ -1,152 +0,0 @@
# Blender 4.2.2 LTS MTL File: 'Hotel.V.1.2.blend'
# www.blender.org
newmtl Material
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 2
map_Kd -o 0 0.6 0 -s 3.8 4 0 Hotel_texture2.png
newmtl Material.002
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Kd 0.799099 0.004025 0.021219
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 2
newmtl Material.008
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Kd 0.215859 0.215861 0.215861
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 2
newmtl Material.010
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 2
map_Kd -o 0 0 -15 -s 4.28 4 0 Hotel_texture3.jpeg
newmtl Material.011
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 2
map_Kd -o 0 0.6 0 -s 3.8 4 0 Hotel_texture2.png
newmtl Material.012
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 2
map_Kd -o 0 0 -15 -s 4.28 4 0 Hotel_texture3.jpeg
newmtl Material.013
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Kd 0.799099 0.004025 0.021219
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 2
newmtl Material.014
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 2
map_Kd -o 0 0.6 0 -s 3.8 4 0 Hotel_texture2.png
newmtl Material.015
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 2
map_Kd -o 0 0 -15 -s 4.28 4 0 Hotel_texture3.jpeg
newmtl Material.016
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Kd 0.799099 0.004025 0.021219
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 2
newmtl Material.019
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 2
map_Kd -o 0 0.6 0 -s 4.15 3.9 0 Hotel_texture1.jpeg
newmtl Material.022
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 2
map_Kd -o 0 0.6 0 -s 4.15 3.8 0 Hotel_texture1.jpeg
newmtl Material.023
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 2
map_Kd -o 0 0.6 0 -s 4.15 3.8 0 Hotel_texture1.jpeg
newmtl Material.024
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 2
map_Kd -o 0 0.6 0 -s 4.15 3.9 0 Hotel_texture1.jpeg
newmtl Material.025
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Kd 0.215859 0.215861 0.215861
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 2

View File

@@ -1,558 +0,0 @@
# Blender 4.2.2 LTS
# www.blender.org
mtllib Hotel.V.1.2.mtl
o Korridor
v 1.832325 0.743096 0.449194
v 1.832325 0.295686 0.449194
v 0.271347 0.743096 0.429009
v 0.271347 0.295686 0.429009
v 1.837850 0.743096 0.022004
v 1.837850 0.295686 0.022004
v 0.276871 0.743096 0.001818
v 0.276871 0.295686 0.001818
vn -0.0129 -0.0000 0.9999
vn -0.9999 -0.0000 -0.0129
vn 0.0129 -0.0000 -0.9999
vn 0.9999 -0.0000 0.0129
vn -0.0000 1.0000 -0.0000
vn -0.0000 -1.0000 -0.0000
vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.250000
vt 0.625000 0.500000
vt 0.375000 0.500000
vt 0.625000 0.750000
vt 0.375000 0.750000
vt 0.625000 1.000000
vt 0.375000 1.000000
vt 0.125000 0.500000
vt 0.125000 0.750000
vt 0.875000 0.500000
vt 0.875000 0.750000
s 0
usemtl Material.008
f 1/1/1 3/4/1 4/3/1 2/2/1
f 3/4/2 7/6/2 8/5/2 4/3/2
f 7/6/3 5/8/3 6/7/3 8/5/3
f 5/8/4 1/10/4 2/9/4 6/7/4
f 3/11/5 1/12/5 5/8/5 7/6/5
f 8/5/6 6/7/6 2/14/6 4/13/6
o Dach300.002
v 2.503119 1.817345 1.102498
v 2.142795 1.919807 1.102498
v 2.503119 1.817345 -0.809905
v 2.142795 1.919807 -0.809905
v 1.831221 1.817345 1.102498
v 2.138520 1.919807 1.102498
v 1.831221 1.817345 -0.809905
v 2.138520 1.919807 -0.809905
vn 0.2735 0.9619 -0.0000
vn -0.0000 -0.0000 -1.0000
vn -0.3163 0.9487 -0.0000
vn -0.0000 -0.0000 1.0000
vn -0.0000 -1.0000 -0.0000
vn -0.0000 1.0000 -0.0000
vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.250000
vt 0.625000 0.500000
vt 0.375000 0.500000
vt 0.625000 0.750000
vt 0.375000 0.750000
vt 0.625000 1.000000
vt 0.375000 1.000000
vt 0.125000 0.500000
vt 0.125000 0.750000
vt 0.875000 0.500000
vt 0.875000 0.750000
s 0
usemtl Material.002
f 9/15/7 11/18/7 12/17/7 10/16/7
f 11/18/8 15/20/8 16/19/8 12/17/8
f 15/20/9 13/22/9 14/21/9 16/19/9
f 13/22/10 9/24/10 10/23/10 14/21/10
f 11/25/11 9/26/11 13/22/11 15/20/11
f 16/19/12 14/21/12 10/28/12 12/27/12
o neu1
v 1.833977 0.294749 1.094962
v 1.833977 1.817107 1.094962
v 1.833977 0.294749 -0.825603
v 1.833977 1.817107 -0.825603
v 2.517500 0.294749 1.094962
v 2.517500 1.817107 1.094962
v 2.517500 0.294749 -0.825603
v 2.517500 1.817107 -0.825603
vn -1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 1.0000
vn -0.0000 -1.0000 -0.0000
vn -0.0000 1.0000 -0.0000
vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.250000
vt 0.625000 0.500000
vt 0.375000 0.500000
vt 0.625000 0.750000
vt 0.375000 0.750000
vt 0.625000 1.000000
vt 0.375000 1.000000
vt 0.125000 0.500000
vt 0.125000 0.750000
vt 0.875000 0.500000
vt 0.875000 0.750000
s 0
usemtl Material
f 17/29/13 18/30/13 20/31/13 19/32/13
f 19/32/14 20/31/14 24/33/14 23/34/14
f 23/34/15 24/33/15 22/35/15 21/36/15
f 21/36/16 22/35/16 18/37/16 17/38/16
f 19/39/17 23/34/17 21/36/17 17/40/17
f 24/33/18 20/41/18 18/42/18 22/35/18
o Frontfassade
v 1.837487 0.305766 1.101834
v 1.837487 1.807752 1.101834
v 1.837487 0.305766 1.092930
v 1.837487 1.807752 1.092930
v 2.509542 0.305766 1.101834
v 2.509542 1.807752 1.101834
v 2.509542 0.305766 1.092930
v 2.509542 1.807752 1.092930
vn -1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 1.0000
vn -0.0000 -1.0000 -0.0000
vn -0.0000 1.0000 -0.0000
vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.250000
vt 0.625000 0.500000
vt 0.375000 0.500000
vt 0.625000 0.750000
vt 0.375000 0.750000
vt 0.625000 1.000000
vt 0.375000 1.000000
vt 0.125000 0.500000
vt 0.125000 0.750000
vt 0.875000 0.500000
vt 0.875000 0.750000
s 0
usemtl Material.010
f 25/43/19 26/44/19 28/45/19 27/46/19
f 27/46/20 28/45/20 32/47/20 31/48/20
f 31/48/21 32/47/21 30/49/21 29/50/21
f 29/50/22 30/49/22 26/51/22 25/52/22
f 27/53/23 31/48/23 29/50/23 25/54/23
f 32/47/24 28/55/24 26/56/24 30/49/24
o neu1.001
v -2.645782 0.310702 1.102233
v -2.645782 1.833060 1.102233
v -2.645782 0.310702 -0.818333
v -2.645782 1.833060 -0.818333
v -1.962258 0.310702 1.102233
v -1.962258 1.833060 1.102233
v -1.962258 0.310702 -0.818333
v -1.962258 1.833060 -0.818333
vn -1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 1.0000
vn -0.0000 -1.0000 -0.0000
vn -0.0000 1.0000 -0.0000
vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.250000
vt 0.625000 0.500000
vt 0.375000 0.500000
vt 0.625000 0.750000
vt 0.375000 0.750000
vt 0.625000 1.000000
vt 0.375000 1.000000
vt 0.125000 0.500000
vt 0.125000 0.750000
vt 0.875000 0.500000
vt 0.875000 0.750000
s 0
usemtl Material.011
f 33/57/25 34/58/25 36/59/25 35/60/25
f 35/60/26 36/59/26 40/61/26 39/62/26
f 39/62/27 40/61/27 38/63/27 37/64/27
f 37/64/28 38/63/28 34/65/28 33/66/28
f 35/67/29 39/62/29 37/64/29 33/68/29
f 40/61/30 36/69/30 34/70/30 38/63/30
o Frontfassade.001
v -2.642272 0.321718 1.109104
v -2.642272 1.823704 1.109104
v -2.642272 0.321718 1.100200
v -2.642272 1.823704 1.100200
v -1.970217 0.321718 1.109104
v -1.970217 1.823704 1.109104
v -1.970217 0.321718 1.100200
v -1.970217 1.823704 1.100200
vn -1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 1.0000
vn -0.0000 -1.0000 -0.0000
vn -0.0000 1.0000 -0.0000
vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.250000
vt 0.625000 0.500000
vt 0.375000 0.500000
vt 0.625000 0.750000
vt 0.375000 0.750000
vt 0.625000 1.000000
vt 0.375000 1.000000
vt 0.125000 0.500000
vt 0.125000 0.750000
vt 0.875000 0.500000
vt 0.875000 0.750000
s 0
usemtl Material.012
f 41/71/31 42/72/31 44/73/31 43/74/31
f 43/74/32 44/73/32 48/75/32 47/76/32
f 47/76/33 48/75/33 46/77/33 45/78/33
f 45/78/34 46/77/34 42/79/34 41/80/34
f 43/81/35 47/76/35 45/78/35 41/82/35
f 48/75/36 44/83/36 42/84/36 46/77/36
o Dach300.001
v -1.976640 1.833298 1.092314
v -2.336963 1.935760 1.092314
v -1.976640 1.833298 -0.785180
v -2.336963 1.935760 -0.785180
v -2.648537 1.833298 1.092314
v -2.341239 1.935760 1.092314
v -2.648537 1.833298 -0.785180
v -2.341239 1.935760 -0.785180
vn 0.2735 0.9619 -0.0000
vn -0.0000 -0.0000 -1.0000
vn -0.3163 0.9487 -0.0000
vn -0.0000 -0.0000 1.0000
vn -0.0000 -1.0000 -0.0000
vn -0.0000 1.0000 -0.0000
vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.250000
vt 0.625000 0.500000
vt 0.375000 0.500000
vt 0.625000 0.750000
vt 0.375000 0.750000
vt 0.625000 1.000000
vt 0.375000 1.000000
vt 0.125000 0.500000
vt 0.125000 0.750000
vt 0.875000 0.500000
vt 0.875000 0.750000
s 0
usemtl Material.013
f 49/85/37 51/88/37 52/87/37 50/86/37
f 51/88/38 55/90/38 56/89/38 52/87/38
f 55/90/39 53/92/39 54/91/39 56/89/39
f 53/92/40 49/94/40 50/93/40 54/91/40
f 51/95/41 49/96/41 53/92/41 55/90/41
f 56/89/42 54/91/42 50/98/42 52/97/42
o neu1.002
v -0.141720 0.277559 1.245076
v -0.141720 1.799917 1.245076
v -0.526580 0.277559 -0.636534
v -0.526580 1.799917 -0.636534
v 0.527939 0.277559 1.108105
v 0.527939 1.799917 1.108105
v 0.143079 0.277559 -0.773505
v 0.143079 1.799917 -0.773505
vn -0.9797 -0.0000 0.2004
vn -0.2004 -0.0000 -0.9797
vn 0.9797 -0.0000 -0.2004
vn 0.2004 -0.0000 0.9797
vn -0.0000 -1.0000 -0.0000
vn -0.0000 1.0000 -0.0000
vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.250000
vt 0.625000 0.500000
vt 0.375000 0.500000
vt 0.625000 0.750000
vt 0.375000 0.750000
vt 0.625000 1.000000
vt 0.375000 1.000000
vt 0.125000 0.500000
vt 0.125000 0.750000
vt 0.875000 0.500000
vt 0.875000 0.750000
s 0
usemtl Material.014
f 57/99/43 58/100/43 60/101/43 59/102/43
f 59/102/44 60/101/44 64/103/44 63/104/44
f 63/104/45 64/103/45 62/105/45 61/106/45
f 61/106/46 62/105/46 58/107/46 57/108/46
f 59/109/47 63/104/47 61/106/47 57/110/47
f 64/103/48 60/111/48 58/112/48 62/105/48
o Frontfassade.002
v -0.136904 0.288576 1.251104
v -0.136904 1.790561 1.251104
v -0.138688 0.288576 1.242381
v -0.138688 1.790561 1.242381
v 0.521519 0.288576 1.116432
v 0.521519 1.790561 1.116432
v 0.519735 0.288576 1.107709
v 0.519735 1.790561 1.107709
vn -0.9797 -0.0000 0.2004
vn -0.2004 -0.0000 -0.9797
vn 0.9797 -0.0000 -0.2004
vn 0.2004 -0.0000 0.9797
vn -0.0000 -1.0000 -0.0000
vn -0.0000 1.0000 -0.0000
vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.250000
vt 0.625000 0.500000
vt 0.375000 0.500000
vt 0.625000 0.750000
vt 0.375000 0.750000
vt 0.625000 1.000000
vt 0.375000 1.000000
vt 0.125000 0.500000
vt 0.125000 0.750000
vt 0.875000 0.500000
vt 0.875000 0.750000
s 0
usemtl Material.015
f 65/113/49 66/114/49 68/115/49 67/116/49
f 67/116/50 68/115/50 72/117/50 71/118/50
f 71/118/51 72/117/51 70/119/51 69/120/51
f 69/120/52 70/119/52 66/121/52 65/122/52
f 67/123/53 71/118/53 69/120/53 65/124/53
f 72/117/54 68/125/54 66/126/54 70/119/54
o Dach300.003
v 0.511862 1.800155 1.101269
v 0.158847 1.902617 1.173474
v 0.135633 1.800155 -0.738143
v -0.217382 1.902617 -0.665938
v -0.146407 1.800155 1.235910
v 0.154658 1.902617 1.174331
v -0.522636 1.800155 -0.603502
v -0.221571 1.902617 -0.665081
vn 0.2680 0.9619 -0.0548
vn -0.2004 -0.0000 -0.9797
vn -0.3099 0.9487 0.0634
vn 0.2004 -0.0000 0.9797
vn -0.0000 -1.0000 -0.0000
vn -0.0000 1.0000 -0.0000
vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.250000
vt 0.625000 0.500000
vt 0.375000 0.500000
vt 0.625000 0.750000
vt 0.375000 0.750000
vt 0.625000 1.000000
vt 0.375000 1.000000
vt 0.125000 0.500000
vt 0.125000 0.750000
vt 0.875000 0.500000
vt 0.875000 0.750000
s 0
usemtl Material.016
f 73/127/55 75/130/55 76/129/55 74/128/55
f 75/130/56 79/132/56 80/131/56 76/129/56
f 79/132/57 77/134/57 78/133/57 80/131/57
f 77/134/58 73/136/58 74/135/58 78/133/58
f 75/137/59 73/138/59 77/134/59 79/132/59
f 80/131/60 78/133/60 74/140/60 76/139/60
o Korridor.002
v 0.294809 0.748953 0.441551
v 0.294809 0.301543 0.441551
v 1.816918 0.748953 0.453486
v 1.816918 0.301543 0.453486
v 0.294640 0.748953 0.463026
v 0.294640 0.301543 0.463026
v 1.816749 0.748953 0.474962
v 1.816749 0.301543 0.474962
vn 0.0078 -0.0000 -1.0000
vn 1.0000 -0.0000 0.0078
vn -0.0078 -0.0000 1.0000
vn -1.0000 -0.0000 -0.0078
vn -0.0000 1.0000 -0.0000
vn -0.0000 -1.0000 -0.0000
vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.250000
vt 0.625000 0.500000
vt 0.375000 0.500000
vt 0.625000 0.750000
vt 0.375000 0.750000
vt 0.625000 1.000000
vt 0.375000 1.000000
vt 0.125000 0.500000
vt 0.125000 0.750000
vt 0.875000 0.500000
vt 0.875000 0.750000
s 0
usemtl Material.019
f 81/141/61 83/144/61 84/143/61 82/142/61
f 83/144/62 87/146/62 88/145/62 84/143/62
f 87/146/63 85/148/63 86/147/63 88/145/63
f 85/148/64 81/150/64 82/149/64 86/147/64
f 83/151/65 81/152/65 85/148/65 87/146/65
f 88/145/66 86/147/66 82/154/66 84/153/66
o Korridor.003
v 0.295923 0.753172 -0.007372
v 0.295923 0.305763 -0.007372
v 1.818032 0.753172 0.004563
v 1.818032 0.305763 0.004563
v 0.295755 0.753172 0.014104
v 0.295755 0.305763 0.014104
v 1.817863 0.753172 0.026039
v 1.817863 0.305763 0.026039
vn 0.0078 -0.0000 -1.0000
vn 1.0000 -0.0000 0.0078
vn -0.0078 -0.0000 1.0000
vn -1.0000 -0.0000 -0.0078
vn -0.0000 1.0000 -0.0000
vn -0.0000 -1.0000 -0.0000
vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.250000
vt 0.625000 0.500000
vt 0.375000 0.500000
vt 0.625000 0.750000
vt 0.375000 0.750000
vt 0.625000 1.000000
vt 0.375000 1.000000
vt 0.125000 0.500000
vt 0.125000 0.750000
vt 0.875000 0.500000
vt 0.875000 0.750000
s 0
usemtl Material.022
f 89/155/67 91/158/67 92/157/67 90/156/67
f 91/158/68 95/160/68 96/159/68 92/157/68
f 95/160/69 93/162/69 94/161/69 96/159/69
f 93/162/70 89/164/70 90/163/70 94/161/70
f 91/165/71 89/166/71 93/162/71 95/160/71
f 96/159/72 94/161/72 90/168/72 92/167/72
o Korridor.004
v -2.035452 0.753172 0.001578
v -2.035452 0.305763 0.001578
v -0.305429 0.753172 0.015144
v -0.305429 0.305763 0.015144
v -2.035621 0.753172 0.023054
v -2.035621 0.305763 0.023054
v -0.305598 0.753172 0.036620
v -0.305598 0.305763 0.036620
vn 0.0078 -0.0000 -1.0000
vn 1.0000 -0.0000 0.0078
vn -0.0078 -0.0000 1.0000
vn -1.0000 -0.0000 -0.0078
vn -0.0000 1.0000 -0.0000
vn -0.0000 -1.0000 -0.0000
vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.250000
vt 0.625000 0.500000
vt 0.375000 0.500000
vt 0.625000 0.750000
vt 0.375000 0.750000
vt 0.625000 1.000000
vt 0.375000 1.000000
vt 0.125000 0.500000
vt 0.125000 0.750000
vt 0.875000 0.500000
vt 0.875000 0.750000
s 0
usemtl Material.023
f 97/169/73 99/172/73 100/171/73 98/170/73
f 99/172/74 103/174/74 104/173/74 100/171/74
f 103/174/75 101/176/75 102/175/75 104/173/75
f 101/176/76 97/178/76 98/177/76 102/175/76
f 99/179/77 97/180/77 101/176/77 103/174/77
f 104/173/78 102/175/78 98/182/78 100/181/78
o Korridor.005
v -2.036718 0.748953 0.450501
v -2.036718 0.301543 0.450501
v -0.306695 0.748953 0.464067
v -0.306695 0.301543 0.464067
v -2.036887 0.748953 0.471977
v -2.036887 0.301543 0.471977
v -0.306864 0.748953 0.485542
v -0.306864 0.301543 0.485542
vn 0.0078 -0.0000 -1.0000
vn 1.0000 -0.0000 0.0078
vn -0.0078 -0.0000 1.0000
vn -1.0000 -0.0000 -0.0078
vn -0.0000 1.0000 -0.0000
vn -0.0000 -1.0000 -0.0000
vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.250000
vt 0.625000 0.500000
vt 0.375000 0.500000
vt 0.625000 0.750000
vt 0.375000 0.750000
vt 0.625000 1.000000
vt 0.375000 1.000000
vt 0.125000 0.500000
vt 0.125000 0.750000
vt 0.875000 0.500000
vt 0.875000 0.750000
s 0
usemtl Material.024
f 105/183/79 107/186/79 108/185/79 106/184/79
f 107/186/80 111/188/80 112/187/80 108/185/80
f 111/188/81 109/190/81 110/189/81 112/187/81
f 109/190/82 105/192/82 106/191/82 110/189/82
f 107/193/83 105/194/83 109/190/83 111/188/83
f 112/187/84 110/189/84 106/196/84 108/195/84
o Korridor.006
v -0.288805 0.743096 0.460344
v -0.288805 0.295686 0.460344
v -2.062986 0.743096 0.437401
v -2.062986 0.295686 0.437401
v -0.283281 0.743096 0.033143
v -0.283281 0.295686 0.033143
v -2.057462 0.743096 0.010200
v -2.057462 0.295686 0.010200
vn -0.0129 -0.0000 0.9999
vn -0.9999 -0.0000 -0.0129
vn 0.0129 -0.0000 -0.9999
vn 0.9999 -0.0000 0.0129
vn -0.0000 1.0000 -0.0000
vn -0.0000 -1.0000 -0.0000
vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.250000
vt 0.625000 0.500000
vt 0.375000 0.500000
vt 0.625000 0.750000
vt 0.375000 0.750000
vt 0.625000 1.000000
vt 0.375000 1.000000
vt 0.125000 0.500000
vt 0.125000 0.750000
vt 0.875000 0.500000
vt 0.875000 0.750000
s 0
usemtl Material.025
f 113/197/85 115/200/85 116/199/85 114/198/85
f 115/200/86 119/202/86 120/201/86 116/199/86
f 119/202/87 117/204/87 118/203/87 120/201/87
f 117/204/88 113/206/88 114/205/88 118/203/88
f 115/207/89 113/208/89 117/204/89 119/202/89
f 120/201/90 118/203/90 114/210/90 116/209/90

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 552 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

View File

@@ -19,8 +19,6 @@ import java.util.Deque;
import static java.lang.Math.max;
import java.lang.System.Logger;
/**
* Manages dialog boxes within the application, handling their display, positioning, and focus.
*/
@@ -30,15 +28,11 @@ public class DialogManager {
*/
private final SimpleApplication app;
private final static Logger LOGGER = System.getLogger(DialogManager.class.getName());
/**
* A stack to keep track of the dialogs.
*/
private final Deque<Dialog> dialogStack = new ArrayDeque<>();
private final Deque<PopupDialog> popUpStack = new ArrayDeque<>();
/**
* Constructs a DialogManager for the specified application.
*
@@ -118,45 +112,11 @@ public class DialogManager {
* @param dialog the dialog to open
*/
public void open(Dialog dialog) {
if(dialog instanceof PopupDialog) {
popUpStack.push((PopupDialog) dialog);
processPopUps();
} else {
showDialog(dialog);
}
}
private void showDialog(Dialog dialog) {
dialogStack.push(dialog);
if(dialog instanceof PopupDialog) {
((PopupDialog)dialog).show();
}
dialog.update();
app.getGuiNode().attachChild(dialog);
}
private void processPopUps() {
if (popUpStack.isEmpty()) {
return; // Nothing to process
}
// Check if a popup dialog is already on top
if (dialogStack.peek() instanceof PopupDialog) {
LOGGER.log(Logger.Level.DEBUG, "Popup dialog already on top");
return; // Already a popup dialog on top
} else {
// Pop the next popup from the stack and validate before showing
PopupDialog popUp = popUpStack.pop();
showDialog( (Dialog) popUp);
}
}
/**
* Checks if the specified dialog is the topmost dialog in the dialog stack.
*
@@ -180,8 +140,6 @@ public class DialogManager {
if (!dialogStack.isEmpty())
dialogStack.peek().update();
app.getGuiNode().detachChild(dialog);
processPopUps();
}
/**

View File

@@ -1,5 +0,0 @@
package pp.dialog;
public interface PopupDialog {
void show();
}

View File

@@ -3,7 +3,6 @@
// https://github.com/jMonkeyEngine-Contributions/Lemur/wiki/Styling
import com.jme3.math.ColorRGBA
import com.jme3.texture.Texture
import com.simsilica.lemur.*
import com.simsilica.lemur.component.QuadBackgroundComponent
import com.simsilica.lemur.Button
@@ -13,8 +12,6 @@ import com.simsilica.lemur.HAlignment
import com.simsilica.lemur.Insets3f
import com.simsilica.lemur.component.QuadBackgroundComponent
import com.simsilica.lemur.component.TbtQuadBackgroundComponent
import pp.monopoly.client.MonopolyApp
import pp.monopoly.game.server.Player
def bgColor = color(1, 1, 1, 1)
def buttonEnabledColor = color(0, 0, 0, 1)
@@ -50,23 +47,6 @@ def orangeBorder = TbtQuadBackgroundComponent.create(
1f, false)
orangeBorder.color = color(1, 0.5, 0, 1) // Orange color
def createCustomBackground(app) {
// Load the texture from the assets
Texture texture = app.getAssetManager().loadTexture("Pictures/kontobg.png")
// Create the TbtQuadBackgroundComponent
def backgroundCustom = TbtQuadBackgroundComponent.create(
texture, // The texture to use
1, 1, 1, // Insets for the 9-patch behavior
126, 126, // The size of the texture
1f, // The scale factor
false // No tiling
)
return backgroundCustom
}
selector("pp") {
font = font("Interface/Fonts/Metropolis/Metropolis-Regular-32.fnt")
}
@@ -84,16 +64,6 @@ selector("label-Bold", "pp") {
textHAlignment = HAlignment.Center
textVAlignment = VAlignment.Center
}
selector("label-toolbar", "pp") {
insets = new Insets3f(2, 2, 2, 2)
font = font("Interface/Fonts/Metropolis/Metropolis-Bold-32.fnt")
fontSize = 25
color = new ColorRGBA(ColorRGBA.White)
textHAlignment = HAlignment.Center
textVAlignment = VAlignment.Center
}
selector("label-Text", "pp") {
insets = new Insets3f(2, 2, 2, 2)
@@ -101,26 +71,6 @@ selector("label-Text", "pp") {
color = buttonEnabledColor
}
selector("label-player", "pp") {
insets = new Insets3f(2, 2, 2, 2)
font = font("Interface/Fonts/Metropolis/Metropolis-Bold-32.fnt")
fontSize = 20
color = buttonEnabledColor
}
selector("label-account", "pp") {
insets = new Insets3f(2, 2, 2, 2)
fontSize = 25
color = new ColorRGBA(ColorRGBA.White)
textHAlignment = HAlignment.Center
textVAlignment = VAlignment.Center
}
selector("card-label", "pp") {
insets = new Insets3f(2, 2, 2, 2)
color = ColorRGBA.Black
}
selector("header", "pp") {
font = font("Interface/Fonts/Metropolis/Metropolis-Bold-42.fnt")
insets = new Insets3f(2, 2, 2, 2)
@@ -225,6 +175,7 @@ selector("button", "pp") {
insets = new Insets3f(3, 3, 3, 3) // Adjust the border thickness
textHAlignment = HAlignment.Center
textVAlignment = VAlignment.Center
buttonCommands = stdButtonCommands
}
selector("slider", "pp") {
@@ -306,16 +257,6 @@ selector("settings-title", "pp") {
textHAlignment = HAlignment.Center
textVAlignment = VAlignment.Center
}
selector("warning-title", "pp") {
def outerBackground = new QuadBackgroundComponent(color(1, 0.5, 0, 1)) // Grey inner border
def innerBackground = new QuadBackgroundComponent(buttonBgColor) // White outer border background
font = font("Interface/Fonts/Metropolis/Metropolis-Bold-42.fnt")
background = outerBackground
fontSize = 40
insets = new Insets3f(3, 3, 3, 3)
textHAlignment = HAlignment.Center
textVAlignment = VAlignment.Center
}
selector("menu-button", "pp") {
fontSize = 40 // Set font size
@@ -351,98 +292,3 @@ selector("selector.item.label", "hover") {
background = new QuadBackgroundComponent(new ColorRGBA(0.2f, 0.6f, 1.0f, 0.9f)) // Highlighted background
}
def enabledCommandToolbar = new Command<Button>() {
MonopolyApp app // Pass the app instance to access player details
void execute(Button source) {
// Get the current player's color
Player currentPlayer = app.getGameLogic().getPlayerHandler().getPlayerById(app.getId());
ColorRGBA playerColor = Player.getColor(currentPlayer.getId()).getColor();
if (source.isEnabled()) {
source.setColor(ColorRGBA.White);
def playerBackground = new QuadBackgroundComponent(playerColor); // Use player's color
source.setBackground(playerBackground);
} else {
source.setColor(ColorRGBA.White);
def grayBackground = new QuadBackgroundComponent(ColorRGBA.Gray); // Use gray when disabled
source.setBackground(grayBackground);
}
}
}
def stdButtonCommandsToolbar = [
(ButtonAction.Down) : [pressedCommand],
(ButtonAction.Up) : [pressedCommand],
(ButtonAction.Enabled) : [enabledCommandToolbar],
(ButtonAction.Disabled): [enabledCommandToolbar]
]
selector("button-toolbar", "pp") {
def outerBackground = new QuadBackgroundComponent(color(1, 0.5, 0, 1)) // Orange border
def innerBackground = new QuadBackgroundComponent(buttonBgColor) // Inner button background
// Apply the outer border as the main background
background = outerBackground
// Use insets to create a margin/padding effect for the inner background
insets = new Insets3f(3, 3, 3, 3) // Adjust the border thickness
textHAlignment = HAlignment.Center
textVAlignment = VAlignment.Center
buttonCommands = stdButtonCommandsToolbar
}
selector("button-clear", "pp") { playerColor ->
def validColor = playerColor ?: new ColorRGBA(0, 0, 0, 0) // Vollständig transparent
def playerGradientBackground = new QuadBackgroundComponent(validColor)
// Kein Hintergrundbild, komplett transparent
playerGradientBackground.setColor(new ColorRGBA(0, 0, 0, 0)) // RGBA (Rot, Grün, Blau, Alpha)
background = playerGradientBackground.clone() // Setze den Hintergrund
insets = new Insets3f(-3, -3, -3, -3) // Optional: Ränder
textHAlignment = HAlignment.Center // Text-Zentrierung
textVAlignment = VAlignment.Center // Text-Zentrierung
}
def enabledCommandToolbar2= new Command<Button>() {
void execute(Button source) {
if (source.isEnabled()){
source.setColor(ColorRGBA.White)
def orangeBackground = new QuadBackgroundComponent(color(1, 0.5, 0, 1)); // Orange background
source.setBackground(orangeBackground);
} else{
source.setColor(ColorRGBA.White)
def grayBackground = new QuadBackgroundComponent(ColorRGBA.Gray); // Gray background
source.setBackground(grayBackground);
}
}
}
def stdButtonCommandsToolbar2 =[
(ButtonAction.Down) : [pressedCommand],
(ButtonAction.Up) : [pressedCommand],
(ButtonAction.Enabled) : [enabledCommandToolbar2],
(ButtonAction.Disabled): [enabledCommandToolbar2]
]
selector("button-toolbar2", "pp") {
def outerBackground = new QuadBackgroundComponent(color(1, 0.5, 0, 1)) // Orange border
def innerBackground = new QuadBackgroundComponent(buttonBgColor) // Inner button background
// Apply the outer border as the main background
background = outerBackground
// Use insets to create a margin/padding effect for the inner background
insets = new Insets3f(3, 3, 3, 3) // Adjust the border thickness
textHAlignment = HAlignment.Center
textVAlignment = VAlignment.Center
buttonCommands = stdButtonCommandsToolbar2
}

View File

@@ -1,6 +1,5 @@
plugins {
id 'buildlogic.jme-application-conventions'
id 'com.github.johnrengelman.shadow' version '8.1.1'
}
description = 'Monopoly Client'
@@ -27,12 +26,3 @@ application {
mainClass = 'pp.monopoly.client.MonopolyApp'
applicationName = 'monopoly'
}
shadowJar {
manifest {
attributes(
'Main-Class': 'pp.monopoly.client.MonopolyApp'
)
}
}

View File

@@ -1,354 +0,0 @@
package pp.monopoly.client;
import com.jme3.app.Application;
import com.jme3.app.state.AppStateManager;
import com.jme3.asset.AssetManager;
import com.jme3.effect.ParticleEmitter;
import com.jme3.effect.ParticleMesh;
import com.jme3.effect.shapes.EmitterSphereShape;
import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.material.RenderState.FaceCullMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.renderer.queue.RenderQueue;
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Box;
import com.jme3.scene.shape.Cylinder;
import com.jme3.shadow.DirectionalLightShadowRenderer;
import com.jme3.shadow.EdgeFilteringMode;
import com.jme3.texture.Texture;
import com.jme3.util.TangentBinormalGenerator;
import pp.monopoly.client.gui.BobTheBuilder;
import pp.monopoly.client.gui.CameraController;
import pp.monopoly.client.gui.CameraInputHandler;
import pp.monopoly.client.gui.Toolbar;
import pp.monopoly.model.Board;
/**
* Manages the rendering and visual aspects of the sea and sky in the Battleship game.
* This state is responsible for setting up and updating the sea, sky, and lighting
* conditions, and controls the camera to create a dynamic view of the game environment.
*/
public class BoardAppState extends MonopolyAppState {
/**
* The path to the unshaded texture material.
*/
private static final String UNSHADED = "Common/MatDefs/Misc/Unshaded.j3md"; //NON-NLS
private static final String LIGHTING = "Common/MatDefs/Light/Lighting.j3md";
/**
* The path to the sea texture material.
*/
private static final String BoardTexture = "Pictures/board2.png"; //NON-NLS
/**
* The root node for all visual elements in this state.
*/
private final Node viewNode = new Node("view"); //NON-NLS
/**
* The node containing the scene elements, such as the sea surface.
*/
private final Node sceneNode = new Node("scene"); //NON-NLS
/**
* Synchronizes the buildings's visual representation with the game logic.
*/
private BobTheBuilder bobTheBuilder;
/**
* The pop-up manager for displaying messages and notifications.
*/
private PopUpManager popUpManager;
private CameraController cameraController;
private CameraInputHandler cameraInputHandler;
/**
* Initializes the state by setting up the sky, lights, and other visual components.
* This method is called when the state is first attached to the state manager.
*
* @param stateManager the state manager
* @param application the application
*/
@Override
public void initialize(AppStateManager stateManager, Application application) {
super.initialize(stateManager, application);
// Initialisiere den CameraController zuerst
cameraController = new CameraController(getApp().getCamera(), getApp());
// Danach den CameraInputHandler mit dem initialisierten CameraController
cameraInputHandler = new CameraInputHandler(cameraController, getApp().getInputManager());
popUpManager = new PopUpManager(getApp());
viewNode.attachChild(sceneNode);
setupLights();
// setupSky();
getApp().getViewPort().setBackgroundColor(new com.jme3.math.ColorRGBA(0.5f, 0.7f, 1.0f, 1.0f));
}
/**
* Enables the sea and sky state, setting up the scene and registering any necessary listeners.
* This method is called when the state is set to active.
*/
@Override
protected void enableState() {
getApp().getRootNode().detachAllChildren();
getApp().getGuiNode().detachAllChildren();
getApp().getDialogManager().close(getApp().getDialogManager().getDialogStack().peek());
new Toolbar(getApp()).open();
sceneNode.detachAllChildren();
setupScene();
if (bobTheBuilder == null) {
bobTheBuilder = new BobTheBuilder(getApp(), sceneNode);
getGameLogic().addListener(bobTheBuilder);
}
getApp().getRootNode().attachChild(viewNode);
}
/**
* Disables the sea and sky state, removing visual elements from the scene and unregistering listeners.
* This method is called when the state is set to inactive.
*/
@Override
protected void disableState() {
getApp().getRootNode().detachChild(viewNode);
if (bobTheBuilder != null) {
getGameLogic().removeListener(bobTheBuilder);
bobTheBuilder = null;
}
}
/**
* Sets up the lighting for the scene, including directional and ambient lights.
* Also configures shadows to enhance the visual depth of the scene.
*/
private void setupLights() {
final AssetManager assetManager = getApp().getAssetManager();
final DirectionalLightShadowRenderer shRend = new DirectionalLightShadowRenderer(assetManager, 2048, 3);
shRend.setLambda(0.55f);
shRend.setShadowIntensity(0.6f);
shRend.setEdgeFilteringMode(EdgeFilteringMode.Bilinear);
getApp().getViewPort().addProcessor(shRend);
final DirectionalLight sun = new DirectionalLight();
sun.setDirection(new Vector3f(-1f, -0.7f, -1f).normalizeLocal());
viewNode.addLight(sun);
shRend.setLight(sun);
final AmbientLight ambientLight = new AmbientLight();
// ambientLight.setColor(ColorRGBA.White.mult(0.f)); // brightness
viewNode.addLight(ambientLight);
}
/**
* Sets up the sky in the scene using a skybox with textures for all six directions.
* This creates a realistic and immersive environment for the sea.
*/
private void setupSky() {
final AssetManager assetManager = getApp().getAssetManager();
// Create a cylinder for the sky
float radius = 500f; // Adjust radius as needed
float height = 200f; // Height of the cylinder
int radialSamples = 64; // Number of radial segments for smoothness
int axisSamples = 2; // No vertical divisions (flat vertical surface)
Cylinder skyCylinder = new Cylinder(axisSamples, radialSamples, radius, height, true);
// Create a geometry for the cylinder
Geometry skyGeometry = new Geometry("CylinderSky", skyCylinder);
// Load the cylindrical texture
Texture cylinderTexture = assetManager.loadTexture("Textures/CylinderMap.jpg");
// Create a material and apply the texture
Material skyMaterial = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
skyMaterial.setTexture("ColorMap", cylinderTexture);
skyMaterial.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Off); // Render inside of the cylinder
// Assign material to the geometry
skyGeometry.setMaterial(skyMaterial);
skyGeometry.rotate(-FastMath.HALF_PI, 0, 0); // Rotate 90° along the Y-axis
// Position and attach the cylinder to the scene
skyGeometry.setQueueBucket(RenderQueue.Bucket.Sky); // Ensure it's rendered in the background
skyGeometry.setCullHint(Spatial.CullHint.Never); // Always render the sky
viewNode.attachChild(skyGeometry);
addCylinderCaps();
}
/**
* Adds top and bottom caps to the cylinder sky.
*/
private void addCylinderCaps() {
final AssetManager assetManager = getApp().getAssetManager();
float radius = 500f; // Match the cylinder's radius
float height = 225f; // Match the cylinder's height
int radialSamples = 64; // Match the cylinder's radial samples
// Bottom Cap
Cylinder bottomCap = new Cylinder(2, radialSamples, radius, 0.01f, true, false); // Thin bottom cap
Geometry bottomGeometry = new Geometry("BottomCap", bottomCap);
bottomGeometry.setLocalTranslation(0, -height / 2, 0); // Position at the bottom
bottomGeometry.rotate(FastMath.HALF_PI, 0, 0); // Rotate to make it horizontal
Material bottomMaterial = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
bottomMaterial.setTexture("ColorMap", assetManager.loadTexture("Textures/grass.jpg")); // Bottom texture
bottomMaterial.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Off); // Render both sides
bottomGeometry.setMaterial(bottomMaterial);
bottomGeometry.setQueueBucket(RenderQueue.Bucket.Sky);
bottomGeometry.setCullHint(Spatial.CullHint.Never);
// Top Cap
Cylinder topCap = new Cylinder(2, radialSamples, radius, 0.01f, true, false); // Thin top cap
Geometry topGeometry = new Geometry("TopCap", topCap);
topGeometry.setLocalTranslation(0, height / 2, 0); // Position at the top
topGeometry.rotate(FastMath.HALF_PI, 0, 0); // Rotate to make it horizontal
Material topMaterial = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
topMaterial.setTexture("ColorMap", assetManager.loadTexture("Textures/Top.png")); // Top texture
topMaterial.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Off); // Render both sides
topGeometry.setMaterial(topMaterial);
topGeometry.setQueueBucket(RenderQueue.Bucket.Sky);
topGeometry.setCullHint(Spatial.CullHint.Never);
// Attach caps to the view node
viewNode.attachChild(bottomGeometry);
viewNode.attachChild(topGeometry);
}
/**
* Sets up the sea surface in the scene. This includes creating the sea mesh,
* applying textures, and enabling shadows.
*/
private void setupScene() {
final Board board = getGameLogic().getBoard();
final float x = board.getWidth();
final float y = board.getHeight();
final Box seaMesh = new Box(y, 0.1f, x);
final Geometry seaGeo = new Geometry("sea", seaMesh); //NON-NLS
seaGeo.setLocalTranslation(new Vector3f(0, -0.1f, 0));
Quaternion rotation = new Quaternion();
rotation.fromAngleAxis(FastMath.HALF_PI, Vector3f.UNIT_Y);
seaGeo.setLocalRotation(rotation);
final Material seaMat = new Material(getApp().getAssetManager(), "Common/MatDefs/Light/Lighting.j3md");
Texture texture = getApp().getAssetManager().loadTexture("Pictures/board2.png");
texture.setMagFilter(Texture.MagFilter.Bilinear);
texture.setMinFilter(Texture.MinFilter.Trilinear);
seaMat.setTexture("DiffuseMap", texture);
// Add specular highlights
// seaMat.setBoolean("UseMaterialColors", true);
seaMat.setColor("Diffuse", ColorRGBA.White);
seaMat.setColor("Specular", ColorRGBA.White);
// seaMat.setFloat("Shininess", 16f);
seaGeo.setMaterial(seaMat);
seaGeo.setShadowMode(ShadowMode.CastAndReceive);
TangentBinormalGenerator.generate(seaGeo);
sceneNode.attachChild(createCardDeck());
sceneNode.attachChild(seaGeo);
// Schneefall hinzufügen
// addSnowEffect(sceneNode);
}
private Node createCardDeck() {
Node cardDeck = new Node("cardDeck");
// Ereigniskarten
Vector3f basePosition1 = new Vector3f(3.1f, 0.4f, 3.8f); // Basisposition für Ereigniskarten
float baseRotation1 = -60; // Basisrotation in Grad
for (int i = 0; i < 6; i++) {
Box box = new Box(1.2f, 0.05f, 1.8f); // Sehr flaches Rechteck
Geometry flatCard = new Geometry("Ereigniskarten_" + i, box);
Material mat = new Material(getApp().getAssetManager(), UNSHADED);
mat.setTexture("ColorMap", getApp().getAssetManager().loadTexture("Textures/Ereigniskarten.png"));
flatCard.setMaterial(mat);
// Position und Rotation für die Karte
flatCard.setLocalTranslation(basePosition1.x, basePosition1.y - (i * 0.08f), basePosition1.z);
flatCard.setLocalRotation(new Quaternion().fromAngleAxis(FastMath.DEG_TO_RAD * (baseRotation1 - (i * 5)), Vector3f.UNIT_Y));
cardDeck.attachChild(flatCard);
}
// Gemeinschaftskarten
Vector3f basePosition2 = new Vector3f(-3.3f, 0.4f, -3.8f); // Basisposition für Gemeinschaftskarten
float baseRotation2 = -220; // Basisrotation in Grad
for (int i = 0; i < 6; i++) {
Box box = new Box(1.2f, 0.04f, 1.8f); // Sehr flaches Rechteck
Geometry flatCard = new Geometry("Gemeinschaftskarten_" + i, box);
Material mat = new Material(getApp().getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
mat.setTexture("ColorMap", getApp().getAssetManager().loadTexture("Textures/Gemeinschaftskarten.png"));
flatCard.setMaterial(mat);
// Position und Rotation für die Karte
flatCard.setLocalTranslation(basePosition2.x, basePosition2.y - (i * 0.08f), basePosition2.z);
flatCard.setLocalRotation(new Quaternion().fromAngleAxis(FastMath.DEG_TO_RAD * (baseRotation2 - (i * 5)), Vector3f.UNIT_Y));
cardDeck.attachChild(flatCard);
}
return cardDeck;
}
private void addSnowEffect(Node parentNode) {
// ParticleEmitter für Schnee
ParticleEmitter snowEmitter = new ParticleEmitter("Snow", ParticleMesh.Type.Triangle, 5000);
Material snowMat = new Material(getApp().getAssetManager(), "Common/MatDefs/Misc/Particle.j3md");
snowMat.setTexture("Texture", getApp().getAssetManager().loadTexture("Textures/snowflake.png")); // Schneeflocken-Textur
snowEmitter.setMaterial(snowMat);
// Eigenschaften für Schneepartikel
snowEmitter.setImagesX(1);
snowEmitter.setImagesY(1);
snowEmitter.setEndColor(new ColorRGBA(1f, 1f, 1f, 0.5f)); // Weiß, halbtransparent
snowEmitter.setStartColor(new ColorRGBA(1f, 1f, 1f, 1f)); // Vollweiß
snowEmitter.setStartSize(0.1f);
snowEmitter.setEndSize(0.2f);
snowEmitter.setGravity(0, 0.5f, 0); // Langsames Fallen
snowEmitter.setLowLife(3f);
snowEmitter.setHighLife(15f);
snowEmitter.getParticleInfluencer().setInitialVelocity(new Vector3f(0, -1, 0));
snowEmitter.getParticleInfluencer().setVelocityVariation(0.3f);
// Spawn-Bereich für Schneeflocken definieren
snowEmitter.setParticlesPerSec(200);
snowEmitter.setLocalTranslation(0, 10, 0);
snowEmitter.setShape(new EmitterSphereShape(new Vector3f(0, 0, 0), 15)); // Bereich von -15 bis 15
// Emitter zur Szene hinzufügen
parentNode.attachChild(snowEmitter);
}
@Override
public void update(float tpf) {
super.update(tpf);
cameraController.update(tpf);
}
}

View File

@@ -13,35 +13,51 @@ import com.jme3.asset.AssetLoadException;
import com.jme3.asset.AssetNotFoundException;
import com.jme3.audio.AudioData;
import com.jme3.audio.AudioNode;
/**
* Handles the background and secondary music in the game.
* Allows playing, stopping, and toggling between background music and a secondary track.
*/
public class GameMusic extends AbstractAppState {
private static final Logger LOGGER = System.getLogger(pp.monopoly.client.GameMusic.class.getName());
private static final Preferences PREFERENCES = getPreferences(pp.monopoly.client.GameMusic.class);
private static final String ENABLED_PREF = "enabled"; // NON-NLS
private static final String VOLUME_PREF = "volume"; // NON-NLS
private AudioNode mainMusic;
private AudioNode secondaryMusic;
private boolean isMainMusicPlaying = false;
private boolean isSecondaryMusicPlaying = false;
/**
* Handles the background music beeing played. Is able to start and stop the music. Set the Volume of the Audio.
*/
public class GameMusic extends AbstractAppState{
private static final Logger LOGGER = System.getLogger(GameMusic.class.getName());
private static final Preferences PREFERENCES = getPreferences(GameMusic.class);
private static final String ENABLED_PREF = "enabled"; //NON-NLS
private static final String VOLUME_PREF = "volume"; //NON-NLS
private AudioNode music;
/**
* Initializes the GameMusic app state and loads the background music.
* Checks if sound is enabled in the preferences.
*
* @return {@code true} if sound is enabled, {@code false} otherwise.
*/
public static boolean enabledInPreferences() {
return PREFERENCES.getBoolean(ENABLED_PREF, true);
}
/**
* Checks if sound is enabled in the preferences.
*
* @return float to which the volume is set
*/
public static float volumeInPreferences() {
return PREFERENCES.getFloat(VOLUME_PREF, 0.5f);
}
/**
* Initializes the sound effects for the game.
* Overrides {@link AbstractAppState#initialize(AppStateManager, Application)}
*
* @param stateManager The state manager
* @param app The application instance
* @param app The application
*/
@Override
public void initialize(AppStateManager stateManager, Application app) {
super.initialize(stateManager, app);
mainMusic = loadSound(app, "Sound/background.ogg");
secondaryMusic = loadSound(app, "Sound/ChooseYourCharakter.ogg");
music = loadSound(app, "Sound/background.ogg");
setVolume(volumeInPreferences());
if (isEnabled()) {
playMainMusic();
music.setLooping(true);
if (isEnabled() && music != null) {
music.play();
}
}
@@ -55,7 +71,7 @@ public class GameMusic extends AbstractAppState {
private AudioNode loadSound(Application app, String name) {
try {
final AudioNode sound = new AudioNode(app.getAssetManager(), name, AudioData.DataType.Buffer);
sound.setLooping(true);
sound.setLooping(false);
sound.setPositional(false);
return sound;
}
@@ -66,138 +82,41 @@ public class GameMusic extends AbstractAppState {
}
/**
* Plays the main music.
*/
public void playMainMusic() {
if (!isEnabled()) {
return; // Sound is disabled
}
if (mainMusic != null && !isMainMusicPlaying) {
mainMusic.play();
isMainMusicPlaying = true;
}
}
/**
* Stops the main music.
*/
private void stopMainMusic() {
if (mainMusic != null && isMainMusicPlaying) {
mainMusic.stop();
isMainMusicPlaying = false;
}
}
/**
* Plays the secondary music and stops the main music.
* Sets the enabled state of this AppState.
* Overrides {@link com.jme3.app.state.AbstractAppState#setEnabled(boolean)}
*
*/
public void playSecondaryMusic() {
if (!isEnabled()) {
stopAllMusic();
return;
}
if (isSecondaryMusicPlaying) {
return; // Secondary music is already playing
}
stopMainMusic();
if (secondaryMusic != null) {
secondaryMusic.setVolume(volumeInPreferences());
secondaryMusic.play();
isSecondaryMusicPlaying = true;
}
}
/**
* Stops the secondary music.
*/
public void stopSecondaryMusic() {
if (secondaryMusic != null && isSecondaryMusicPlaying) {
secondaryMusic.stop();
isSecondaryMusicPlaying = false;
}
}
/**
* Toggles between the background music and the secondary track.
* If the secondary track is playing, it stops and resumes the background music.
* If the background music is playing, it pauses and plays the secondary track.
*
*/
public void toggleMusic() {
if (!isEnabled()) {
stopAllMusic();
return;
}
if (isSecondaryMusicPlaying) {
stopSecondaryMusic();
playMainMusic();
} else {
stopMainMusic();
playSecondaryMusic();
}
}
/**
* Sets the audio volume for both the main and secondary tracks.
*
* @param vol The volume level (0.0f to 1.0f)
*/
public void setVolume(float vol) {
if (mainMusic != null) mainMusic.setVolume(vol);
if (secondaryMusic != null) secondaryMusic.setVolume(vol);
PREFERENCES.putFloat(VOLUME_PREF, vol);
}
/**
* Stops all music (both main and secondary).
*/
public void stopAllMusic() {
stopMainMusic();
stopSecondaryMusic();
}
/**
* Enables or disables the sound system.
* When disabled, all music stops.
*
* @param enabled {@code true} to enable, {@code false} to disable
* @param enabled {@code true} to enable the AppState, {@code false} to disable it.
*/
@Override
public void setEnabled(boolean enabled) {
if (isEnabled() == enabled) return; // Avoid redundant operations
if (isEnabled() == enabled) return;
PREFERENCES.putBoolean(ENABLED_PREF, enabled);
if (enabled) {
playMainMusic();
} else {
stopAllMusic();
if (music != null) {
if (enabled) {
music.play();
} else {
music.stop();
}
}
super.setEnabled(enabled);
LOGGER.log(Level.INFO, "Sound enabled: {0}", enabled); // NON-NLS
LOGGER.log(Level.INFO, "Sound enabled: {0}", enabled); //NON-NLS
PREFERENCES.putBoolean(ENABLED_PREF, enabled);
}
/**
* Retrieves the current sound volume preference.
*
* @return The volume level (0.0f to 1.0f)
* Toggles the game sound on or off.
*/
public static float volumeInPreferences() {
return PREFERENCES.getFloat(VOLUME_PREF, 0.5f);
public void toggleSound() {
setEnabled(!isEnabled());
}
/**
* Checks if sound is enabled in the preferences.
*
* @return {@code true} if sound is enabled, {@code false} otherwise
* Sets the volume of music
* @param vol the volume to which the music should be set
*/
public static boolean enabledInPreferences() {
return PREFERENCES.getBoolean(ENABLED_PREF, true);
public void setVolume(float vol){
music.setVolume(vol);
PREFERENCES.putFloat(VOLUME_PREF, vol);
}
}

View File

@@ -27,25 +27,9 @@ import static pp.util.PreferencesUtils.getPreferences;
* An application state that plays sounds.
*/
public class GameSound extends AbstractAppState implements GameEventListener {
/**
* Logger instance for logging messages related to GameSound.
*/
private static final Logger LOGGER = System.getLogger(GameSound.class.getName());
/**
* Preferences instance for managing GameSound-related settings.
*/
private static final Preferences PREFERENCES = getPreferences(GameSound.class);
/**
* Preference key for enabling or disabling GameSound.
*/
private static final String ENABLED_PREF = "enabled"; //NON-NLS
/**
* Preference key for storing the volume level of GameSound.
*/
private static final String VOLUME_PREF = "volume"; //NON-NLS
private AudioNode passStartSound;
@@ -120,7 +104,6 @@ public class GameSound extends AbstractAppState implements GameEventListener {
winnerSound = loadSound(app, "Sound/Effects/winner.ogg");
looserSound = loadSound(app, "Sound/Effects/loser.ogg");
buttonSound = loadSound(app, "Sound/Effects/button.ogg");
setVolume(volumeInPreferences());
}
/**
@@ -240,11 +223,6 @@ public class GameSound extends AbstractAppState implements GameEventListener {
PREFERENCES.putFloat(VOLUME_PREF, vol);
}
/**
* Overrides {@link SoundEvent#notifyListener(GameEventListener)}
* @param event the received event
*/
@Override
public void receivedEvent(SoundEvent event) {
switch (event.sound()) {

View File

@@ -7,18 +7,6 @@
package pp.monopoly.client;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.LogManager;
import java.awt.Image;
import javax.imageio.ImageIO;
import com.jme3.app.DebugKeysAppState;
import com.jme3.app.SimpleApplication;
import com.jme3.app.StatsAppState;
@@ -32,24 +20,32 @@ import com.jme3.input.controls.MouseButtonTrigger;
import com.jme3.system.AppSettings;
import com.simsilica.lemur.GuiGlobals;
import com.simsilica.lemur.style.BaseStyles;
import pp.dialog.DialogBuilder;
import pp.dialog.DialogManager;
import pp.graphics.Draw;
import static pp.monopoly.Resources.lookup;
import pp.monopoly.game.client.MonopolyClient;
import pp.monopoly.client.gui.SettingsMenu;
import pp.monopoly.client.gui.StartMenu;
import pp.monopoly.game.client.ClientGameLogic;
import pp.monopoly.game.client.MonopolyClient;
import pp.monopoly.game.client.ServerConnection;
import pp.monopoly.message.client.NotificationAnswer;
import pp.monopoly.notification.ClientStateEvent;
import pp.monopoly.notification.GameEventListener;
import pp.monopoly.notification.InfoTextEvent;
import pp.monopoly.notification.Sound;
import pp.dialog.DialogBuilder;
import pp.dialog.DialogManager;
import pp.graphics.Draw;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.LogManager;
import static pp.monopoly.Resources.lookup;
/**
* The main class for the Monopoly client application.
* The main class for the Battleship client application.
* It manages the initialization, input setup, GUI setup, and game states for the client.
*/
public class MonopolyApp extends SimpleApplication implements MonopolyClient, GameEventListener {
@@ -124,11 +120,6 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga
*/
private final ActionListener escapeListener = (name, isPressed, tpf) -> escape(isPressed);
/**
* Listener for handeling Demo Mode (Minas mode)
*/
private final ActionListener f8Listener = (name, isPressed, tpf) -> handleF8(isPressed);
static {
// Configure logging
LogManager manager = LogManager.getLogManager();
@@ -142,7 +133,7 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga
}
/**
* Starts the Monopoly application.
* Starts the Battleship application.
*
* @param args Command-line arguments for launching the application.
*/
@@ -154,7 +145,7 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga
* Constructs a new {@code MonopolyApp} instance.
* Initializes the configuration, server connection, and game logic listeners.
*/
public MonopolyApp() {
private MonopolyApp() {
config = new MonopolyAppConfig();
config.readFromIfExists(CONFIG_FILE);
serverConnection = makeServerConnection();
@@ -172,16 +163,6 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga
private AppSettings makeSettings() {
final AppSettings settings = new AppSettings(true);
settings.setTitle(lookup("monopoly.name"));
try {
// Prüfen, ob das Betriebssystem ein Mac-System ist
if (!System.getProperty("os.name").toLowerCase().contains("mac")) {
settings.setIcons(new Image[]{ImageIO.read(new File("src/main/resources/icons/Uniman.png"))});
} else {
LOGGER.log(Level.INFO, "Icon setting skipped on macOS due to system restrictions.");
}
} catch (IOException e) {
LOGGER.log(Level.ERROR, e.getMessage());
}
settings.setResolution(config.getResolutionWidth(), config.getResolutionHeight());
settings.setFullscreen(config.fullScreen());
settings.setUseRetinaFrameBuffer(config.useRetinaFrameBuffer());
@@ -219,9 +200,9 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga
}
/**
* Returns the current configuration settings for the Monopoly client.
* Returns the current configuration settings for the Battleship client.
*
* @return The {@link pp.monopoly.game.client.MonopolyClientConfig} instance.
* @return The {@link BattleshipClientConfig} instance.
*/
@Override
public MonopolyAppConfig getConfig() {
@@ -266,21 +247,7 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga
inputManager.setCursorVisible(false);
inputManager.addMapping(ESC, new KeyTrigger(KeyInput.KEY_ESCAPE));
inputManager.addMapping(CLICK, new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
inputManager.addMapping("F8", new KeyTrigger(KeyInput.KEY_F8));
inputManager.addListener(f8Listener, "F8");
inputManager.addListener(escapeListener, ESC);
}
/**
* Handles the action on alt m for demo mode
* @param isPressed {@code true} is alt + m is pressed, {@code false} otherwise
*/
private void handleF8(boolean isPressed) {
if (isPressed) {
LOGGER.log(Level.INFO, "F detected."); // Debug logging
getGameLogic().send(new NotificationAnswer("hack"));
}
}
/**
@@ -293,14 +260,11 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga
stateManager.attach(stats);
}
flyCam.setEnabled(false);
flyCam.setMoveSpeed(4f); // Setzt die Bewegungsgeschwindigkeit der Kamera (Standardwert ist 1f)
stateManager.detach(stateManager.getState(StatsAppState.class));
stateManager.detach(stateManager.getState(DebugKeysAppState.class));
attachGameSound();
attachGameMusic();
stateManager.attach(new BoardAppState());
}
/**
@@ -333,7 +297,6 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga
super.simpleUpdate(tpf);
dialogManager.update(tpf);
logic.update(tpf);
stateManager.update(tpf);
}
/**
@@ -420,7 +383,6 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga
*/
@Override
public void receivedEvent(ClientStateEvent event) {
stateManager.getState(BoardAppState.class).setEnabled(logic.isTurn());
}
/**
@@ -478,26 +440,7 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga
.open();
}
/**
* Disconnects the current server connection.
*
* This method delegates the disconnection operation to the `disconnect` method of the
* `serverConnection` object.
*
*/
public void disconnect() {
serverConnection.disconnect();
}
/**
* Retrieves the unique identifier associated with the server connection.
*
* Checks if a Server is connected and returns 0 if there is no connection
*
* @return the ID of the connected Server instance.
*/
public int getId() {
if (serverConnection != null && serverConnection instanceof NetworkSupport) return ((NetworkSupport) serverConnection).getId();
return 0;
}
}

View File

@@ -106,26 +106,6 @@ public class MonopolyAppConfig extends MonopolyClientConfig {
@Property("overlay.top.color") //NON-NLS
private ColorRGBA topColor = ColorRGBA.White;
private ColorRGBA applyGammaCorrection(ColorRGBA color) {
return new ColorRGBA(
correctGamma(color.r),
correctGamma(color.g),
correctGamma(color.b),
color.a // Alpha bleibt unverändert
);
}
private float correctGamma(float channel) {
// Formel: ((RGB / 255)^2.2) * 255
float normalized = channel / 255.0f; // RGB normalisieren (0-1)
float gammaCorrected = (float) Math.pow(normalized, 2.2); // ^2.2
return gammaCorrected * 255.0f; // Zurückskalieren auf 0-255
}
private float correctGamma(float channel, float gamma) {
return (float) Math.pow(channel, gamma);
}
/**
* Creates a default {@code MonopolyAppConfig} with predefined values.
*/

View File

@@ -25,7 +25,7 @@ import java.lang.System.Logger.Level;
import static pp.monopoly.Resources.lookup;
/**
* Manages the network connection for the Monopoly application.
* Manages the network connection for the Battleship application.
* Handles connecting to and disconnecting from the server, and sending messages.
*/
public class NetworkSupport implements MessageListener<Client>, ClientStateListener, ServerConnection {
@@ -34,9 +34,9 @@ public class NetworkSupport implements MessageListener<Client>, ClientStateListe
private Client client;
/**
* Constructs a NetworkSupport instance for the given Monopoly application.
* Constructs a NetworkSupport instance for the given Battleship application.
*
* @param app The Monopoly application instance.
* @param app The Battleship application instance.
*/
public NetworkSupport(MonopolyApp app) {
this.app = app;
@@ -44,7 +44,6 @@ public class NetworkSupport implements MessageListener<Client>, ClientStateListe
/**
* Return the client connections Id
*
* @return the client id
*/
public int getId() {
@@ -53,9 +52,9 @@ public class NetworkSupport implements MessageListener<Client>, ClientStateListe
}
/**
* Returns the Monopoly application instance.
* Returns the Battleship application instance.
*
* @return Monopoly application instance
* @return Battleship application instance
*/
public MonopolyApp getApp() {
return app;

View File

@@ -1,97 +0,0 @@
package pp.monopoly.client;
import java.util.Timer;
import java.util.TimerTask;
import pp.monopoly.client.gui.popups.AcceptTrade;
import pp.monopoly.client.gui.popups.BuildingPropertyCard;
import pp.monopoly.client.gui.popups.ConfirmTrade;
import pp.monopoly.client.gui.popups.EventCardPopup;
import pp.monopoly.client.gui.popups.FoodFieldCard;
import pp.monopoly.client.gui.popups.GateFieldCard;
import pp.monopoly.client.gui.popups.Gulag;
import pp.monopoly.client.gui.popups.GulagInfo;
import pp.monopoly.client.gui.popups.LooserPopUp;
import pp.monopoly.client.gui.popups.NoMoneyWarning;
import pp.monopoly.client.gui.popups.ReceivedRent;
import pp.monopoly.client.gui.popups.RejectTrade;
import pp.monopoly.client.gui.popups.Rent;
import pp.monopoly.client.gui.popups.TimeOut;
import pp.monopoly.client.gui.popups.WinnerPopUp;
import pp.monopoly.message.server.NotificationMessage;
import pp.monopoly.message.server.TradeReply;
import pp.monopoly.model.fields.BuildingProperty;
import pp.monopoly.model.fields.FoodField;
import pp.monopoly.model.fields.GateField;
import pp.monopoly.notification.EventCardEvent;
import pp.monopoly.notification.GameEventListener;
import pp.monopoly.notification.PopUpEvent;
public class PopUpManager implements GameEventListener {
private final MonopolyApp app;
public PopUpManager(MonopolyApp app) {
this.app = app;
app.getGameLogic().addListener(this);
}
@Override
public void receivedEvent(PopUpEvent event) {
if (event.msg().equals("Buy")) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
app.enqueue(() -> {
int field = app.getGameLogic().getPlayerHandler().getPlayerById(app.getId()).getFieldID();
Object fieldObject = app.getGameLogic().getBoardManager().getFieldAtIndex(field);
if (fieldObject instanceof BuildingProperty) {
new BuildingPropertyCard(app).open();
} else if (fieldObject instanceof GateField) {
new GateFieldCard(app).open();
} else if (fieldObject instanceof FoodField) {
new FoodFieldCard(app).open();
}
});
}
}, 8000);
} else if (event.msg().equals("Winner")) {
new WinnerPopUp(app).open();
} else if (event.msg().equals("Looser")) {
new LooserPopUp(app).open();
} else if (event.msg().equals("timeout")) {
new TimeOut(app).open();
} else if (event.msg().equals("tradeRequest")) {
new ConfirmTrade(app).open();
} else if (event.msg().equals("goingToJail")) {
new Gulag(app).open();
} else if (event.msg().equals("NoMoneyWarning")) {
new NoMoneyWarning(app).open();
} else if(event.msg().equals("rent")) {
new Rent(app, ( (NotificationMessage) event.message()).getRentOwner(), ( (NotificationMessage) event.message()).getRentAmount() ).open();
} else if (event.msg().equals("jailtryagain")) {
new GulagInfo(app, 1).open();
} else if (event.msg().equals("jailpay")) {
new GulagInfo(app, 3).open();
} else if (event.msg().equals("tradepos")) {
new AcceptTrade(app, (TradeReply) event.message()).open();
} else if (event.msg().equals("tradeneg")) {
new RejectTrade(app, (TradeReply) event.message()).open();
} else if (event.msg().equals("ReceivedRent")) {
new ReceivedRent(app, ( (NotificationMessage) event.message()).getRentOwner(), ( (NotificationMessage) event.message()).getRentAmount() ).open();
}
}
@Override
public void receivedEvent(EventCardEvent event) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
app.enqueue(() -> new EventCardPopup(app, event.description()).open());
}
}, 2500);
}
}

View File

@@ -0,0 +1,74 @@
package pp.monopoly.client.gui;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import pp.monopoly.model.Board;
import pp.monopoly.model.Item;
import pp.monopoly.model.Visitor;
import pp.monopoly.notification.GameEventListener;
import pp.monopoly.notification.ItemAddedEvent;
import pp.monopoly.notification.ItemRemovedEvent;
import pp.view.ModelViewSynchronizer;
/**
* Abstract base class for synchronizing the visual representation of a {@link Board} with its model state.
* This class handles the addition and removal of items from the map, ensuring that changes in the model
* are accurately reflected in the view.
*/
abstract class BoardSynchronizer extends ModelViewSynchronizer<Item> implements Visitor<Spatial>, GameEventListener {
protected final Board board;
/**
* Constructs a new BoardSynchronizer.
*
* @param board the game board to synchronize
* @param root the root node to which the view representations of the board items are attached
*/
protected BoardSynchronizer(Board board, Node root) {
super(root);
this.board = board;
}
/**
* Translates a model item into its corresponding visual representation.
*
* @param item the item from the model to be translated
* @return the visual representation of the item as a {@link Spatial}
*/
@Override
protected Spatial translate(Item item) {
return item.accept(this);
}
/**
* Adds the existing items from the board to the view during initialization.
*/
protected void addExisting() {
board.getItems().forEach(this::add);
}
/**
* Handles the event when an item is removed from the board.
*
* @param event the event indicating that an item has been removed from the board
*/
@Override
public void receivedEvent(ItemRemovedEvent event) {
if (board == event.getBoard()) {
delete(event.getItem());
}
}
/**
* Handles the event when an item is added to the board.
*
* @param event the event indicating that an item has been added to the board
*/
@Override
public void receivedEvent(ItemAddedEvent event) {
if (board == event.getBoard()) {
add(event.getItem());
}
}
}

View File

@@ -1,147 +0,0 @@
package pp.monopoly.client.gui;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Box;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.model.Figure;
import pp.monopoly.model.Hotel;
import pp.monopoly.model.House;
import pp.monopoly.model.Item;
import pp.monopoly.notification.UpdatePlayerView;
public class BobTheBuilder extends GameBoardSynchronizer {
private static final String UNSHADED = "Common/MatDefs/Misc/Unshaded.j3md"; //NON-NLS
private static final String COLOR = "Color"; //NON-NLS
private static final String FIGURE = "figure"; //NON-NLS
private static final String HOUSE = "house"; //NON-NLS
private static final String HOTEL = "hotel"; //NON-NLS
private final MonopolyApp app;
public BobTheBuilder(MonopolyApp app, Node root) {
super(app.getGameLogic().getBoard(), root);
this.app = app;
addExisting();
}
@Override
public Spatial visit(Figure figure) {
final Node node = new Node(FIGURE);
Spatial spatial = createFigure(figure);
node.attachChild(spatial);
// Setze die Position basierend auf der Feld-ID
node.setLocalTranslation(figure.getPos());
// Setze die Anfangsrotation auf 90 Grad nach links
Quaternion initialRotation = new Quaternion().fromAngleAxis(FastMath.HALF_PI, Vector3f.UNIT_Y);
node.setLocalRotation(initialRotation);
node.addControl(new FigureControl(node, figure, app));
return node;
}
@Override
public Spatial visit(Hotel hotel) {
final Node node = new Node(HOTEL);
node.attachChild(createHotel(hotel));
// Setze die Position basierend auf der Feld-ID
node.setLocalTranslation(hotel.getPos());
// Setze die Rotation basierend auf der Feld-ID
node.setLocalRotation(hotel.getRot().toQuaternion());
return node;
}
@Override
public Spatial visit(House house) {
final Node node = new Node(HOUSE);
node.attachChild(createHouse(house));
// Setze die Position basierend auf der Feld-ID
node.setLocalTranslation(house.getPos());
// Setze die Rotation basierend auf der Feld-ID
node.setLocalRotation(house.getAlignment());
return node;
}
private Spatial createFigure(Figure figure) {
// Lade das Modell
Spatial model = app.getAssetManager().loadModel("models/" + "Spielfiguren/" + figure.getType() + "/" + figure.getType() + ".j3o");
// Skaliere und positioniere das Modell
model.scale(0.5f);
return model;
}
private Spatial createHotel(Hotel hotel) {
Spatial model = app.getAssetManager().loadModel("models/Hotel/Hotel.j3o");
model.scale(0.2f);
model.setShadowMode(ShadowMode.CastAndReceive);
return model;
}
private Spatial createHouse(House house) {
Spatial model = app.getAssetManager().loadModel("models/Haus/"+house.getStage()+"Haus.j3o");
model.scale(0.5f);
model.setShadowMode(ShadowMode.CastAndReceive);
return model;
}
/**
* Creates a simple box to represent a battleship that is not of the "King George V" type.
*
* @param ship the battleship to be represented
* @return the geometry representing the battleship as a box
*/
private Spatial createBox(Item item) {
final Box box = new Box(3,
3f,
3);
final Geometry geometry = new Geometry(FIGURE, box);
geometry.setMaterial(createColoredMaterial(ColorRGBA.Blue));
geometry.setShadowMode(ShadowMode.CastAndReceive);
geometry.setLocalTranslation(0, 2, 0);
return geometry;
}
/**
* Creates a new {@link Material} with the specified color.
* If the color includes transparency (i.e., alpha value less than 1),
* the material's render state is set to use alpha blending, allowing for
* semi-transparent rendering.
*
* @param color the {@link ColorRGBA} to be applied to the material. If the alpha value
* of the color is less than 1, the material will support transparency.
* @return a {@link Material} instance configured with the specified color and,
* if necessary, alpha blending enabled.
*/
private Material createColoredMaterial(ColorRGBA color) {
final Material material = new Material(app.getAssetManager(), UNSHADED);
if (color.getAlpha() < 1f)
material.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
material.setColor(COLOR, color);
return material;
}
}

View File

@@ -1,221 +0,0 @@
package pp.monopoly.client.gui;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Quad;
import com.jme3.texture.Texture;
import com.simsilica.lemur.*;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.component.SpringGridLayout;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.client.gui.popups.BuyHouse;
import pp.monopoly.client.gui.popups.RepayMortage;
import pp.monopoly.client.gui.popups.SellHouse;
import pp.monopoly.client.gui.popups.TakeMortage;
import pp.monopoly.notification.Sound;
/**
* Represents the building administration menu in the Monopoly application.
* <p>
* Provides options to manage properties, including building houses, demolishing houses,
* taking mortgages, repaying mortgages, and viewing an overview of owned properties.
* </p>
*/
public class BuildingAdminMenu extends Dialog {
/** Reference to the Monopoly application instance. */
private final MonopolyApp app;
/** Main container for the menu's UI components. */
private final Container mainContainer;
/** Background geometry for the menu. */
private Geometry background;
/** Button to navigate back to the previous menu. */
private final Button backButton = new Button("Zurück");
/** Button to build houses on properties. */
private final Button buildButton = new Button("Bauen");
/** Button to demolish houses on properties. */
private final Button demolishButton = new Button("Abriss");
/** Button to take out a mortgage on properties. */
private final Button takeMortgageButton = new Button("Hypothek aufnehmen");
/** Button to repay a mortgage on properties. */
private final Button payMortgageButton = new Button("Hypothek bezahlen");
/** Button to open the property overview menu. */
private final Button overviewButton = new Button("Übersicht");
/**
* Constructs the building administration menu.
*
* @param app the Monopoly application instance
*/
public BuildingAdminMenu(MonopolyApp app) {
super(app.getDialogManager());
this.app = app;
// Background Image
addBackgroundImage();
// Main container for the UI components
mainContainer = new Container(new SpringGridLayout(Axis.Y, Axis.X));
mainContainer.setPreferredSize(new Vector3f(800, 600, 0));
mainContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(1, 1, 1, 0.7f))); // Translucent white background
// Add header
mainContainer.addChild(createHeaderContainer());
// Add content
mainContainer.addChild(createContent());
// Attach main container to GUI node
app.getGuiNode().attachChild(mainContainer);
mainContainer.setLocalTranslation(
(app.getCamera().getWidth() - mainContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + mainContainer.getPreferredSize().y) / 2,
7
);
}
/**
* Creates the header container.
*
* @return The header container.
*/
private Container createHeaderContainer() {
Container headerContainer = new Container(new SpringGridLayout(Axis.X, Axis.Y));
headerContainer.setPreferredSize(new Vector3f(800, 100, 0));
Label headerLabel = headerContainer.addChild(new Label("Grundstücke Verwalten", new ElementId("header")));
headerLabel.setFontSize(45);
headerLabel.setInsets(new Insets3f(10, 10, 10, 10));
return headerContainer;
}
/**
* Creates the main content container with columns for Overview, Build, and Mortgage.
*
* @return The content container.
*/
private Container createContent() {
Container contentContainer = new Container(new SpringGridLayout(Axis.X, Axis.Y));
contentContainer.setPreferredSize(new Vector3f(800, 500, 0));
// Overview Column
Container overviewColumn = new Container(new SpringGridLayout(Axis.Y, Axis.X));
overviewColumn.addChild(new Label("Übersicht:")).setFontSize(30);
//Building Overview Button
overviewButton.setPreferredSize(new Vector3f(200, 50, 0));
overviewButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
new PropertyOverviewMenu(app).open();
}));
overviewColumn.addChild(overviewButton);
// Back Button
backButton.setPreferredSize(new Vector3f(200, 50, 0));
backButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
close();
}));
overviewColumn.addChild(backButton);
contentContainer.addChild(overviewColumn);
// Build Column
Container buildColumn = new Container(new SpringGridLayout(Axis.Y, Axis.X));
buildColumn.addChild(new Label("Bauen:")).setFontSize(30);
// Build Houses Button
buildButton.setPreferredSize(new Vector3f(200, 50, 0));
buildButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
new BuyHouse(app).open();
}));
buildColumn.addChild(buildButton);
//Demolish Houses Button
demolishButton.setPreferredSize(new Vector3f(200, 50, 0));
demolishButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
new SellHouse(app).open();
}));
buildColumn.addChild(demolishButton);
contentContainer.addChild(buildColumn);
// Mortgage Column
Container mortgageColumn = new Container(new SpringGridLayout(Axis.Y, Axis.X));
mortgageColumn.addChild(new Label("Hypotheken:")).setFontSize(30);
// Lend Mortgage Button
takeMortgageButton.setPreferredSize(new Vector3f(200, 50, 0));
takeMortgageButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
new TakeMortage(app).open();
}));
mortgageColumn.addChild(takeMortgageButton);
//Repay Mortgage Button
payMortgageButton.setPreferredSize(new Vector3f(200, 50, 0));
payMortgageButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
new RepayMortage(app).open();
}));
mortgageColumn.addChild(payMortgageButton);
contentContainer.addChild(mortgageColumn);
return contentContainer;
}
/**
* Adds a background image to the dialog.
*/
private void addBackgroundImage() {
Texture backgroundImage = app.getAssetManager().loadTexture("Pictures/unibw-Bib2.png");
Quad quad = new Quad(app.getCamera().getWidth(), app.getCamera().getHeight());
background = new Geometry("Background", quad);
Material backgroundMaterial = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
backgroundMaterial.setTexture("ColorMap", backgroundImage);
background.setMaterial(backgroundMaterial);
background.setLocalTranslation(0, 0, 6); // Position behind other GUI elements
app.getGuiNode().attachChild(background);
}
/**
* Closes the building administration menu and detaches its elements from the GUI.
*/
@Override
public void close() {
app.getGuiNode().detachChild(mainContainer);
app.getGuiNode().detachChild(background);
super.close();
}
/**
* Opens the settings menu when the escape key is pressed.
*/
@Override
public void escape() {
new SettingsMenu(app).open();
}
/**
* Periodic updates for the menu, if required.
*
* @param delta Time since the last update in seconds.
*/
@Override
public void update(float delta) {
// Periodic updates if necessary
}
}

View File

@@ -1,108 +1,60 @@
package pp.monopoly.client.gui;
import com.jme3.math.FastMath;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import pp.monopoly.client.MonopolyApp; // Import MonopolyApp
import pp.monopoly.game.server.PlayerHandler;
import pp.monopoly.notification.GameEventListener;
import pp.monopoly.notification.UpdatePlayerView;
public class CameraController implements GameEventListener{
public enum CameraMode {
FOCUS_CURRENT_PLAYER,
FOCUS_SELF,
FREECAM
}
/**
* Steuert die Kamerabewegung in der Szene.
*/
public class CameraController {
private final Camera camera;
private CameraMode currentMode;
private final Vector3f center; // Fokuspunkt der Kamera
private final float radius; // Radius der Kreisbewegung
private final float height; // Höhe der Kamera über dem Spielfeld
private final float speed; // Geschwindigkeit der Kamerabewegung
private float angle; // Aktueller Winkel in der Kreisbewegung
private PlayerHandler playerHandler; // Reference to PlayerHandler for player data
private final MonopolyApp app; // Reference to MonopolyApp for self ID
public CameraController(Camera camera, MonopolyApp app) {
/**
* Konstruktor für den CameraController.
*
* @param camera Die Kamera, die gesteuert werden soll
* @param center Der Mittelpunkt der Kreisbewegung (Fokuspunkt)
* @param radius Der Radius der Kreisbewegung
* @param height Die Höhe der Kamera über dem Fokuspunkt
* @param speed Die Geschwindigkeit der Kamerabewegung
*/
public CameraController(Camera camera, Vector3f center, float radius, float height, float speed) {
this.camera = camera;
this.playerHandler = app.getGameLogic().getPlayerHandler();
this.app = app;
app.getGameLogic().addListener(this);
setMode(CameraMode.FOCUS_SELF); // Initialize the camera mode
}
public void setMode(CameraMode mode) {
this.currentMode = mode;
this.center = center;
this.radius = radius;
this.height = height;
this.speed = speed;
this.angle = 0; // Starte bei Winkel 0
}
/**
* Aktualisiert die Kameraposition und -ausrichtung.
*
* @param tpf Zeit pro Frame
*/
public void update(float tpf) {
switch (currentMode) {
case FOCUS_CURRENT_PLAYER:
updatePosition();
break;
case FOCUS_SELF:
updatePosition();
break;
case FREECAM:
break;
default:
break;
}
camera.lookAt(center, Vector3f.UNIT_Y);
}
public void updatePosition() {
Vector3f newPosition = getPos();
camera.setLocation(newPosition);
camera.lookAt(app.getGameLogic().getBoard().getFigure(app.getId()).getPos(), Vector3f.UNIT_Y);
camera.update();
public void setPosition(int fieldID) {
camera.setLocation(fieldIdToVector(fieldID));
}
private Vector3f getPos() {
Vector3f pos = new Vector3f();
switch (currentMode) {
case FOCUS_CURRENT_PLAYER:
pos = app.getGameLogic().getBoard().getFigure(playerHandler.getPlayerById(0).getId()).getPos();
case FOCUS_SELF:
pos = app.getGameLogic().getBoard().getFigure(app.getId()).getPos();
case FREECAM:
break;
default:
break;
}
Vector3f offset = getOffset();
pos = new Vector3f(pos.getX() + offset.getX(), pos.getY() + offset.getY(), pos.getZ() + offset.getZ());
return pos;
public void setPosition(float x, float y) {
camera.setLocation(new Vector3f(x,height,y));
}
private Vector3f getOffset() {
Vector3f offset = new Vector3f();
int fieldId = playerHandler.getPlayerById( (currentMode == CameraMode.FOCUS_SELF ? app.getId() : playerHandler.getPlayerAtIndex(0).getId()) ).getFieldID();
// System.out.println();
if(fieldId < 10) {
offset = new Vector3f(0, 10, -15);
} else if(fieldId < 20) {
offset = new Vector3f(15 , 10, 0);
} else if(fieldId < 30) {
offset = new Vector3f(0, 10, 15 );
} else {
offset = new Vector3f(-15, 10, 0);
}
return offset;
}
@Override
public void receivedEvent(UpdatePlayerView event) {
playerHandler = app.getGameLogic().getPlayerHandler();
private Vector3f fieldIdToVector(int fieldID) {
if (fieldID <= 10) return new Vector3f(30,height,0);
if (fieldID <= 20) return new Vector3f(0, height, 30);
if (fieldID <= 30) return new Vector3f(-30, height, 0);
if (fieldID <= 40) return new Vector3f(0, height, -30);
else throw new IllegalArgumentException();
}
}

View File

@@ -1,31 +0,0 @@
package pp.monopoly.client.gui;
import com.jme3.input.InputManager;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
public class CameraInputHandler {
private CameraController cameraController;
public CameraInputHandler(CameraController cameraController, InputManager inputManager) {
this.cameraController = cameraController;
// Tasten für die verschiedenen Kameramodi registrieren
inputManager.addMapping("FocusCurrentPlayer", new KeyTrigger(KeyInput.KEY_1));
inputManager.addMapping("FocusSelf", new KeyTrigger(KeyInput.KEY_2));
inputManager.addMapping("FreeCam", new KeyTrigger(KeyInput.KEY_3));
inputManager.addListener(actionListener, "FocusCurrentPlayer", "FocusSelf", "FreeCam");
}
private final ActionListener actionListener = (name, isPressed, tpf) -> {
if (!isPressed) return;
switch (name) {
case "FocusCurrentPlayer" -> cameraController.setMode(CameraController.CameraMode.FOCUS_CURRENT_PLAYER);
case "FocusSelf" -> cameraController.setMode(CameraController.CameraMode.FOCUS_SELF);
case "FreeCam" -> cameraController.setMode(CameraController.CameraMode.FREECAM);
}
};
}

View File

@@ -1,224 +0,0 @@
package pp.monopoly.client.gui;
import java.util.Set;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Quad;
import com.jme3.texture.Texture;
import com.simsilica.lemur.*;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.component.SpringGridLayout;
import com.simsilica.lemur.core.VersionedList;
import com.simsilica.lemur.core.VersionedReference;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.game.server.Player;
import pp.monopoly.message.client.ViewAssetsRequest;
import pp.monopoly.model.TradeHandler;
import pp.monopoly.notification.Sound;
public class ChoosePartner extends Dialog {
private final MonopolyApp app;
private Selector<String> playerSelector;
private final Button cancelButton = new Button("Abbrechen");
private final Button confirmButton = new Button("Bestätigen");
private final Container mainContainer;
private Container lowerLeftMenu;
private Container lowerRightMenu;
private Geometry background;
private TradeHandler tradeHandler;
private VersionedReference<Set<Integer>> selectionRef; // Reference to track selector changes
private String lastSelected = ""; // To keep track of the last selected value
QuadBackgroundComponent translucentWhiteBackground =
new QuadBackgroundComponent(new ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f));
/**
* Constructs the ChoosePartner dialog.
*
* @param app The Monopoly application instance.
*/
public ChoosePartner(MonopolyApp app) {
super(app.getDialogManager());
this.app = app;
tradeHandler = new TradeHandler(app.getGameLogic().getPlayerHandler().getPlayerById(app.getId()));
app.getGameLogic().send(new ViewAssetsRequest());
// Background Image
addBackgroundImage();
// Main container for the UI components
mainContainer = new Container(new SpringGridLayout(Axis.Y, Axis.X));
mainContainer.setPreferredSize(new Vector3f(1000, 600, 0));
mainContainer.setBackground(translucentWhiteBackground);
// Add title with background
Label headerLabel = mainContainer.addChild(new Label("Wähle deinen Handelspartner:", new ElementId("label-Bold")));
headerLabel.setFontSize(40);
headerLabel.setBackground(new QuadBackgroundComponent(new ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f)));
// Dropdown for player selection
mainContainer.addChild(createDropdown());
// Add buttons
mainContainer.addChild(createButtonContainer());
// Attach main container to GUI node
app.getGuiNode().attachChild(mainContainer);
mainContainer.setLocalTranslation(
(app.getCamera().getWidth() - mainContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + mainContainer.getPreferredSize().y) / 2,
4
);
// Initialize selection reference for tracking changes
selectionRef = playerSelector.getSelectionModel().createReference();
}
/**
* Creates the dropdown menu for selecting a partner.
*
* @return The dropdown container.
*/
private Container createDropdown() {
Container dropdownContainer = new Container(new SpringGridLayout(Axis.Y, Axis.X));
dropdownContainer.setPreferredSize(new Vector3f(100, 80, 0));
dropdownContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(ColorRGBA.Black)));
VersionedList<String> playerOptions = new VersionedList<>();
for (Player player : app.getGameLogic().getPlayerHandler().getPlayers()) {
if (player.getId() != app.getId()) {
playerOptions.add(player.getName() + " (ID: " + player.getId() + ")");
}
}
playerSelector = new Selector<>(playerOptions, "glass");
dropdownContainer.addChild(playerSelector);
Vector3f dimens = dropdownContainer.getPreferredSize();
Vector3f dimens2 = playerSelector.getPopupContainer().getPreferredSize();
dimens2.setX(dimens.getX());
playerSelector.getPopupContainer().setPreferredSize(new Vector3f(200, 200, 3));
playerSelector.setLocalTranslation(0, 0, 5);
// Set initial selection
if (!playerOptions.isEmpty()) {
onDropdownSelectionChanged(playerOptions.get(0));
}
return dropdownContainer;
}
/**
* Creates the button container with cancel and confirm buttons.
*
* @return The button container.
*/
private Container createButtonContainer() {
Container buttonContainer = new Container(new SpringGridLayout(Axis.X, Axis.Y));
buttonContainer.setBackground(translucentWhiteBackground);
// "Abbrechen" button
lowerLeftMenu = new Container();
cancelButton.setPreferredSize(new Vector3f(200, 60, 0));
cancelButton.setFontSize(30);
cancelButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
close();
}));
lowerLeftMenu.addChild(cancelButton);
// Position the container near the bottom-left corner
lowerLeftMenu.setLocalTranslation(new Vector3f(120, 170, 5)); // Adjust X and Y to align with the bottom-left corner
app.getGuiNode().attachChild(lowerLeftMenu);
// "Bestätigen" button
lowerRightMenu = new Container();
confirmButton.setPreferredSize(new Vector3f(200, 60, 0));
confirmButton.setFontSize(30);
confirmButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
close();
new TradeMenu(app, tradeHandler).open();
}));
lowerRightMenu.addChild(confirmButton);
// Position the container near the bottom-right corner
lowerRightMenu.setLocalTranslation(new Vector3f(app.getCamera().getWidth() - 320, 170, 5)); // X: 220px from the right, Y: 50px above the bottom
app.getGuiNode().attachChild(lowerRightMenu);
return buttonContainer;
}
/**
* Adds a background image to the dialog.
*/
private void addBackgroundImage() {
Texture backgroundImage = app.getAssetManager().loadTexture("Pictures/unibw-Bib2.png");
Quad quad = new Quad(app.getCamera().getWidth(), app.getCamera().getHeight());
background = new Geometry("Background", quad);
Material backgroundMaterial = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
backgroundMaterial.setTexture("ColorMap", backgroundImage);
background.setMaterial(backgroundMaterial);
background.setLocalTranslation(0, 0, 3); // Position behind other GUI elements
app.getGuiNode().attachChild(background);
}
/**
* Handles the escape action for the dialog.
*/
@Override
public void escape() {
new SettingsMenu(app).open();
}
/**
* Updates the dialog periodically, called by the dialog manager.
*
* @param delta The time elapsed since the last update.
*/
@Override
public void update(float delta) {
// Check if the selection has changed
if (selectionRef.update()) {
String selected = playerSelector.getSelectedItem();
if (!selected.equals(lastSelected)) {
lastSelected = selected;
onDropdownSelectionChanged(selected);
}
}
}
@Override
public void close() {
app.getGuiNode().detachChild(playerSelector);
app.getGuiNode().detachChild(lowerLeftMenu);
app.getGuiNode().detachChild(lowerRightMenu);
app.getGuiNode().detachChild(mainContainer);
app.getGuiNode().detachChild(background);
super.close();
}
/**
* Callback for when the dropdown selection changes.
*/
private void onDropdownSelectionChanged(String selected) {
app.getGameLogic().playSound(Sound.BUTTON);
int idStart = selected.indexOf("(ID: ") + 5; // Find start of the ID
int idEnd = selected.indexOf(")", idStart); // Find end of the ID
String idStr = selected.substring(idStart, idEnd); // Extract the ID as a string
int playerId = Integer.parseInt(idStr); // Convert the ID to an integer
// Find the player by ID
Player selectedPlayer = app.getGameLogic().getPlayerHandler().getPlayerById(playerId);
if (selectedPlayer != null) {
tradeHandler.setReceiver(selectedPlayer); // Set the receiver in TradeHandler
}
}
}

View File

@@ -66,7 +66,7 @@ public class CreateGameMenu extends Dialog {
final MonopolyApp app = network.getApp();
int screenWidth = app.getContext().getSettings().getWidth();
int screenWidth = app.getContext().getSettings().getWidth();
int screenHeight = app.getContext().getSettings().getHeight();
// Set up the background image

View File

@@ -1,158 +0,0 @@
package pp.monopoly.client.gui;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Node;
import com.jme3.scene.control.AbstractControl;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.game.client.ClientGameLogic;
import pp.monopoly.model.Figure;
import pp.monopoly.notification.GameEventListener;
import pp.monopoly.notification.UpdatePlayerView;
// import java.lang.System.Logger;
// import java.lang.System.Logger.Level;
import java.util.LinkedList;
import java.util.Queue;
public class FigureControl extends AbstractControl implements GameEventListener {
// // // private static final Logger LOGGER = System.getLogger(FigureControl.class.getName());
private final Figure figure;
private final Node spatial;
private final MonopolyApp app;
private Queue<Vector3f> path; // Path to follow
private Vector3f currentTarget;
private float animationTime = 0f; // Time elapsed for the current movement
private final float durationPerField = 0.5f; // Time to move between fields
private float delayTime = 3f; // Verzögerung in Sekunden
private float delayElapsed = 0f; // Zeit, die seit dem Start der Verzögerung vergangen ist
public FigureControl(Node spatial, Figure figure, MonopolyApp app) {
super();
this.figure = figure;
this.spatial = spatial;
this.app = app;
this.path = new LinkedList<>();
app.getGameLogic().addListener(this);
}
@Override
protected void controlUpdate(float tpf) {
if (delayTime > 0) {
delayElapsed += tpf;
if (delayElapsed < delayTime) {
return; // Warte, bis die Verzögerung abgeschlossen ist
}
delayTime = 0; // Verzögerung abgeschlossen
}
if (currentTarget == null && !path.isEmpty()) {
// Hole das nächste Ziel aus dem Pfad
currentTarget = path.poll();
animationTime = 0f;
// Prüfe, ob eine Drehung erforderlich ist (Felder 0, 10, 20, 30)
int currentField = figure.getCurrentFieldID();
int nextField = nextField(currentField);
if ((nextField(currentField) == 10) ||
(nextField(currentField) == 20) ||
(nextField(currentField) == 30) ||
(nextField(currentField) == 0)) {
Quaternion rotation = spatial.getLocalRotation();
Quaternion turnRight = new Quaternion().fromAngleAxis(-FastMath.HALF_PI, Vector3f.UNIT_Y);
spatial.setLocalRotation(rotation.mult(turnRight));
}
}
if (currentTarget != null) {
animationTime += tpf;
Vector3f startPosition = spatial.getLocalTranslation();
Vector3f interpolatedPosition = startPosition.interpolateLocal(
currentTarget,
animationTime / durationPerField
);
// Hüpfeffekt hinzufügen
float hopHeight = 0.5f * FastMath.sin(FastMath.PI * (animationTime / durationPerField));
interpolatedPosition.setY(hopHeight );
spatial.setLocalTranslation(interpolatedPosition);
// Ziel erreicht
if (animationTime >= durationPerField) {
spatial.setLocalTranslation(currentTarget);
figure.moveTo(currentTarget); // Synchronisiere die interne Position
currentTarget = null; // Setze Ziel zurück
}
}
}
private int nextField(int currentField) {
return (currentField + 1) % 40;
}
@Override
protected void controlRender(RenderManager rm, ViewPort vp) {
// No rendering logic required
}
public void setPath(int startField, int endField) {
// LOGGER.log(Level.TRACE, "setPath called with startField: {0} to endField {1}", startField, endField);
path.clear();
for (int fieldId = startField; fieldId != endField; fieldId = (fieldId + 1) % 40) {
Vector3f position = figure.calculateFieldPosition(fieldId);
// LOGGER.log(Level.DEBUG, "Adding postition to path: {0}", position);
path.add(position);
}
Vector3f finalPosition = figure.calculateFieldPosition(endField);
path.add(finalPosition);
// LOGGER.log(Level.DEBUG, "Final position added to path: {0}", finalPosition);
// LOGGER.log(Level.TRACE, "Path size: {0}", path.size());
}
@Override
public void receivedEvent(UpdatePlayerView event) {
// LOGGER.log(Level.TRACE, "receivedEvent called with event: {0}", event);
int newPos = app.getGameLogic().getPlayerHandler().getPlayerById(figure.getId()).getFieldID();
int currentField = figure.getCurrentFieldID();
if (currentField == newPos) {
// LOGGER.log(Level.DEBUG, "No movement required. Current field: {0}, New field: {1}", currentField, newPos);
return;
}
// LOGGER.log(Level.DEBUG, "Movement required. Current field: {0}, New field: {1}", currentField, newPos);
setPath(currentField, newPos);
delayTime = 3f; // Verzögerung zurücksetzen
delayElapsed = 0f; // Timer zurücksetzen
}
}

View File

@@ -1,87 +1,124 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package pp.monopoly.client.gui;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import pp.monopoly.model.Item;
import pp.monopoly.model.Visitor;
import pp.monopoly.notification.DiceRollEvent;
import pp.monopoly.notification.GameEventListener;
import pp.monopoly.notification.ItemAddedEvent;
import pp.monopoly.notification.ItemRemovedEvent;
import pp.monopoly.notification.UpdatePlayerView;
import com.jme3.scene.shape.Box;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.game.server.PlayerColor;
import pp.monopoly.model.Board;
import pp.monopoly.model.Figure;
import pp.view.ModelViewSynchronizer;
import pp.monopoly.model.Rotation;
import static pp.util.FloatMath.HALF_PI;
import static pp.util.FloatMath.PI;
/**
* Abstract base class for synchronizing the visual representation of a {@link Board} with its model state.
* This class handles the addition and removal of items from the board, ensuring that changes in the model
* are accurately reflected in the view.
* <p>
* Subclasses are responsible for providing the specific implementation of how each item in the map
* is represented visually by implementing the {@link Visitor} interface.
* </p>
* The {@code GameBoardSynchronizer} class is responsible for synchronizing the graphical
* representation of the ships and shots on the sea map with the underlying data model.
* It extends the {@link BoardSynchronizer} to provide specific synchronization
* logic for the sea map.
*/
abstract class GameBoardSynchronizer extends ModelViewSynchronizer<Item> implements Visitor<Spatial>, GameEventListener {
// The board that this synchronizer is responsible for
protected final Board board;
class GameBoardSynchronizer extends BoardSynchronizer {
private static final String UNSHADED = "Common/MatDefs/Misc/Unshaded.j3md"; //NON-NLS
private static final String LIGHTING = "Common/MatDefs/Light/Lighting.j3md";
private static final String COLOR = "Color"; //NON-NLS
private static final String FIGURE = "figure"; //NON-NLS
private final MonopolyApp app;
private final ParticleEffectFactory particleFactory;
/**
* Constructs a new GameBoardSynchronizer.
* Initializes the synchronizer with the provided board and the root node for attaching view representations.
* Constructs a {@code GameBoardSynchronizer} object with the specified application, root node, and ship map.
*
* @param map the board to be synchronized
* @param root the root node to which the view representations of the board items are attached
* @param app the Battleship application
* @param root the root node to which graphical elements will be attached
* @param map the ship map containing the ships and shots
*/
protected GameBoardSynchronizer(Board board, Node root) {
super(root);
this.board = board;
public GameBoardSynchronizer(MonopolyApp app, Node root, Board board) {
super(board, root);
this.app = app;
this.particleFactory = new ParticleEffectFactory(app);
addExisting();
}
/**
* Translates a model item into its corresponding visual representation.
* The specific visual representation is determined by the concrete implementation of the {@link Visitor} interface.
* Visits a {@link Battleship} and creates a graphical representation of it.
* The representation is either a 3D model or a simple box depending on the
* type of battleship.
*
* @param item the item from the model to be translated
* @return the visual representation of the item as a {@link Spatial}
* @param ship the battleship to be represented
* @return the node containing the graphical representation of the battleship
*/
@Override
protected Spatial translate(Item item) {
return item.accept(this);
public Spatial visit(Figure figure) {
final Node node = new Node(FIGURE);
node.attachChild(createBox(figure));
// compute the center of the ship in world coordinates
final float x = 1;
final float z = 1;
node.setLocalTranslation(x, 0f, z);
return node;
}
/**
* Adds the existing items from the board to the view.
* This method should be called during initialization to ensure that all current items in the board
* are visually represented.
*/
protected void addExisting() {
board.getItems().forEach(this::add);
}
/**
* Handles the event when an item is removed from the ship map.
* Removes the visual representation of the item from the view if it belongs to the synchronized ship map.
* Creates a simple box to represent a battleship that is not of the "King George V" type.
*
* @param event the event indicating that an item has been removed from the ship map
* @param ship the battleship to be represented
* @return the geometry representing the battleship as a box
*/
@Override
public void receivedEvent(ItemRemovedEvent event) {
if (board == event.board())
delete(event.item());
private Spatial createBox(Figure figure) {
final Box box = new Box(0.5f * (figure.getMaxY() - figure.getMinY()) + 0.3f,
0.3f,
0.5f * (figure.getMaxX() - figure.getMinX()) + 0.3f);
final Geometry geometry = new Geometry(FIGURE, box);
geometry.setMaterial(createColoredMaterial(PlayerColor.PINK.getColor()));
geometry.setShadowMode(ShadowMode.CastAndReceive);
return geometry;
}
/**
* Handles the event when an item is added to the ship map.
* Adds the visual representation of the new item to the view if it belongs to the synchronized ship map.
* Creates a new {@link Material} with the specified color.
* If the color includes transparency (i.e., alpha value less than 1),
* the material's render state is set to use alpha blending, allowing for
* semi-transparent rendering.
*
* @param event the event indicating that an item has been added to the ship map
* @param color the {@link ColorRGBA} to be applied to the material. If the alpha value
* of the color is less than 1, the material will support transparency.
* @return a {@link Material} instance configured with the specified color and,
* if necessary, alpha blending enabled.
*/
@Override
public void receivedEvent(ItemAddedEvent event) {
if (board == event.board()){
add(event.item());
}
private Material createColoredMaterial(ColorRGBA color) {
final Material material = new Material(app.getAssetManager(), UNSHADED);
if (color.getAlpha() < 1f)
material.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
material.setColor(COLOR, color);
return material;
}
/**
* Calculates the rotation angle for the specified rotation.
*
* @param rot the rotation of the battleship
* @return the rotation angle in radians
*/
private static float calculateRotationAngle(Rotation rot) {
return switch (rot) {
case RIGHT -> HALF_PI;
case DOWN -> 0f;
case LEFT -> -HALF_PI;
case UP -> PI;
};
}
}

View File

@@ -1,93 +0,0 @@
package pp.monopoly.client.gui;
import com.jme3.texture.Texture;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Command;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.game.server.Player;
import pp.monopoly.game.server.PlayerColor;
import pp.monopoly.notification.Sound;
public class ImageButton extends Button {
private final MonopolyApp app;
private final String functionality;
private final PlayerColor playerColor;
public ImageButton(String functionality, MonopolyApp app) {
super("", "button-clear");
this.app = app;
this.functionality = functionality;
this.playerColor = Player.getColor(app.getId());
updateButtonAppearance(ButtonState.ENABLED);
addButtonCommands();
}
/**
* Updates the button's appearance based on its state.
*
* @param state the current button state
*/
private void updateButtonAppearance(ButtonState state) {
setBackgroundTexture(state.name().toLowerCase());
}
/**
* Adds button commands for state-specific actions like hover, press, enable, and disable.
*/
private void addButtonCommands() {
addCommands(ButtonAction.Enabled, source -> updateButtonAppearance(ButtonState.ENABLED));
addCommands(ButtonAction.Disabled, source -> updateButtonAppearance(ButtonState.DISABLED));
addCommands(ButtonAction.Hover, source -> {
if (isEnabled()) {
updateButtonAppearance(ButtonState.HOVER);
}
});
addCommands(ButtonAction.HighlightOff, source -> updateButtonAppearance(isEnabled() ? ButtonState.ENABLED : ButtonState.DISABLED));
addCommands(ButtonAction.Up, source -> updateButtonAppearance(isEnabled() ? ButtonState.ENABLED : ButtonState.DISABLED));
addCommands(ButtonAction.Down, source -> {
if (isEnabled()) {
app.getGameLogic().playSound(Sound.BUTTON);
}
});
}
/**
* Sets the background texture for the button based on the given state.
*
* @param state the button state (e.g., "enabled", "disabled", "hover")
*/
private void setBackgroundTexture(String state) {
String texturePath = buildTexturePath(state);
Texture texture = app.getAssetManager().loadTexture(texturePath);
setBackground(new QuadBackgroundComponent(texture));
}
/**
* Builds the file path for the button texture.
*
* @param state the button state (e.g., "enabled", "disabled", "hover")
* @return the full file path to the texture
*/
private String buildTexturePath(String state) {
return String.format("Pictures/Buttons/Button_%s_%s_%s.png", functionality, playerColor.getColorName(), state);
}
/**
* Button states for handling appearance transitions.
*/
private enum ButtonState {
ENABLED, DISABLED, HOVER
}
public void addClickCommands( Command<? super Button> command ) {
super.addCommands(ButtonAction.Down, command);
}
@SuppressWarnings("unchecked") // because Java doesn't like var-arg generics
public void addClickCommands( Command<? super Button>... commands ) {
super.addCommands(ButtonAction.Down, commands);
}
}

View File

@@ -1,5 +1,7 @@
package pp.monopoly.client.gui;
import com.jme3.app.Application;
import com.jme3.app.state.BaseAppState;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
@@ -22,80 +24,50 @@ import com.simsilica.lemur.core.VersionedReference;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.monopoly.client.GameMusic;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.game.server.Player;
import pp.monopoly.message.client.PlayerReady;
import pp.monopoly.notification.Sound;
import java.util.Set;
/**
* Represents the lobby menu in the Monopoly application.
* <p>
* Provides functionality for player configuration, including input for starting capital,
* player name, and figure selection, as well as options to ready up or exit the game.
* </p>
*/
public class LobbyMenu extends Dialog {
/** Reference to the Monopoly application instance. */
private final MonopolyApp app;
/** Main container for the lobby menu UI. */
private final Container menuContainer;
/** Background geometry for the menu. */
private Geometry background;
/** Colored circle displayed between input fields and dropdown menus. */
private Geometry circle;
/** Container for the lower-left section of the menu. */
private Container lowerLeftMenu;
/** Container for the lower-right section of the menu. */
private Container lowerRightMenu;
private ColorRGBA playerColor= ColorRGBA.Gray;
/** Text field for entering the player's name. */
private PlayerHandler playerHandler;
private TextField startingCapital;
private TextField playerInputField;
/** Text field for entering the starting capital. */
private TextField startingCapital = new TextField("15000");
/** Selected player figure. */
private String figure;
private VersionedReference<Set<Integer>> selectionRef;
private Selector<String> figureDropdown;
/**
* Constructs the lobby menu for player configuration.
*
* @param app the Monopoly application instance
*/
private TextField playerInputField = new TextField("Spieler 1");
private TextField startingCapital = new TextField("15000");
private String figure;
public LobbyMenu(MonopolyApp app) {
super(app.getDialogManager());
this.app = app;
GameMusic music = app.getStateManager().getState(GameMusic.class);
if (music != null && music.isEnabled()) {
music.playSecondaryMusic();
}
playerInputField = new TextField("Spieler "+(app.getId()+1));
// Hintergrundbild laden und hinzufügen
addBackgroundImage();
app.getGuiNode().detachAllChildren(); // Entfernt das CreateGameMenu (inklusive Hintergrund)
addBackgroundImage();// Hintergrundbild laden und hinzufügen
QuadBackgroundComponent translucentWhiteBackground =
new QuadBackgroundComponent(new ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f));
menuContainer = new Container(new SpringGridLayout(Axis.Y, Axis.X));
menuContainer.setPreferredSize(new Vector3f(1000, 600, 0)); // Fixed size of the container
menuContainer.setPreferredSize(new Vector3f(1000, 600, 0));
menuContainer.setBackground(translucentWhiteBackground);
// Create a smaller horizontal container for the label, input field, and spacers
Container horizontalContainer = menuContainer.addChild(new Container(new SpringGridLayout(Axis.X, Axis.Y)));
horizontalContainer.setPreferredSize(new Vector3f(600, 40, 0)); // Adjust container size
horizontalContainer.setPreferredSize(new Vector3f(600, 40, 0));
horizontalContainer.setBackground(null);
Label title = horizontalContainer.addChild(new Label("Startkapital:", new ElementId("label-Bold")));
@@ -124,7 +96,6 @@ public class LobbyMenu extends Dialog {
// Dropdowns and Labels
Container dropdownContainer = menuContainer.addChild(new Container(new SpringGridLayout(Axis.X, Axis.Y)));
dropdownContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(ColorRGBA.Black)));
dropdownContainer.setPreferredSize(new Vector3f(800, 200, 0));
dropdownContainer.setBackground(null);
dropdownContainer.setInsets(new Insets3f(10, 0, 0, 0));
@@ -135,42 +106,37 @@ public class LobbyMenu extends Dialog {
playerInputField.setPreferredSize(new Vector3f(100, 20, 0));
playerInputField.setInsets(new Insets3f(5, 10, 5, 10)); // Add padding for the text inside the field
playerInputField.setInsets(new Insets3f(5, 10, 5, 10));
playerInputField.setBackground(new QuadBackgroundComponent(ColorRGBA.Black));
playerInputContainer.addChild(playerInputField);
// Spacer (Center Circle Area)
Label spacer = dropdownContainer.addChild(new Label(""));
spacer.setPreferredSize(new Vector3f(200, 200, 0)); // Adjust this to fit the center graphic
spacer.setPreferredSize(new Vector3f(200, 200, 0));
// Figur Dropdown
Container figureDropdownContainer = dropdownContainer.addChild(new Container(new SpringGridLayout(Axis.Y, Axis.X)));
figureDropdownContainer.setPreferredSize(new Vector3f(150, 80, 0));
figureDropdownContainer.addChild(new Label("Figur:"));
figureDropdownContainer.setBackground(null);
VersionedList<String> figures = new VersionedList<>();
figures.add("Computer");
figures.add("Laptop");
figures.add("Flugzeug");
figures.add("Jägermeister");
figures.add("Katze");
figures.add("OOP");
figures.add("Handyholster");
figures.add("Panzer");
figureDropdown = new Selector<>(figures, "glass");
Selector<String> figureDropdown = new Selector<>(figures, "glass");
figureDropdown.setBackground(new QuadBackgroundComponent(ColorRGBA.DarkGray));
figureDropdown.setPreferredSize(new Vector3f(100, 20, 0));
figureDropdownContainer.addChild(figureDropdown);
Vector3f dimens = dropdownContainer.getPreferredSize();
figureDropdown.setPreferredSize(new Vector3f(150, 140, 0));
Vector3f dimens = figureDropdownContainer.getPreferredSize();
Vector3f dimens2 = figureDropdown.getPopupContainer().getPreferredSize();
dimens2.setX( dimens.getX() );
figureDropdown.getPopupContainer().setPreferredSize(new Vector3f(200,200,5));
figureDropdown.getPopupContainer().setPreferredSize( dimens2 );
figureDropdownContainer.addChild(figureDropdown);
// Create selection ref for updating
selectionRef = figureDropdown.getSelectionModel().createReference();
// Set default
figureDropdown.getSelectionModel().setSelection(0);
onDropdownSelectionChanged(figureDropdown);
addSelectionActionListener(figureDropdown, this::onDropdownSelectionChanged);
Container buttonContainer = menuContainer.addChild(new Container(new SpringGridLayout(Axis.X, Axis.Y)));
buttonContainer.setPreferredSize(new Vector3f(100, 40, 0));
@@ -198,12 +164,11 @@ public class LobbyMenu extends Dialog {
readyButton.setFontSize(18); // Adjust font size
readyButton.setBackground(new QuadBackgroundComponent(ColorRGBA.Green)); // Add color to match the style
readyButton.addClickCommands(s -> ifTopDialog(() -> {
music.toggleMusic();
toggleReady();
app.getGameLogic().playSound(Sound.BUTTON);
readyButton.setBackground(new QuadBackgroundComponent(ColorRGBA.DarkGray));
}));
lowerRightMenu.addChild(readyButton);
//TODO aktivieren des Spielers in den ready Status und Sprung in den nächsten Menüzustand
// Position the container near the bottom-right corner
lowerRightMenu.setLocalTranslation(new Vector3f(app.getCamera().getWidth() - 320, 170, 3)); // X: 220px from the right, Y: 50px above the bottom
@@ -225,13 +190,64 @@ public class LobbyMenu extends Dialog {
1 // Höhere Z-Ebene für den Vordergrund
);
app.getGuiNode().attachChild(menuContainer);
}
/**
* Apply the starting capital only if the current player is the host.
*/
private void applyStartingCapital(int playerID) {
Player currentPlayer = playerHandler.getPlayerById(playerID);
// Check if the current player is the host
if (currentPlayer.equals(playerHandler.getHostPlayer())) {
try {
// Parse and validate starting capital
int startBalance = Integer.parseInt(startingCapital.getText().replaceAll("[^\\d]", ""));
if (startBalance < 0) throw new NumberFormatException("Starting capital must be positive.");
// Apply the starting balance to all players
playerHandler.setStartBalance(startBalance);
System.out.println("Starting balance set to: " + startBalance);
} catch (NumberFormatException e) {
System.err.println("Invalid starting capital: " + e.getMessage());
}
} else {
System.out.println("Only the host can set the starting balance.");
}
}
/**
* Adds a background image to the lobby menu.
* Apply the player name from the input field.
*/
private void applyPlayerName(int playerID) {
Player currentPlayer = playerHandler.getPlayerById(playerID);
String playerName = playerInputField.getText().trim();
if (!playerName.isEmpty()) {
currentPlayer.setName(playerName);
System.out.println("Player name set to: " + playerName);
} else {
System.err.println("Invalid player name: Name cannot be empty.");
}
}
/**
* Apply the selected figure to the player.
*/
private void applyFigure(int playerID) {
Player currentPlayer = playerHandler.getPlayerById(playerID);
String selectedFigure = figureDropdown.getSelectedItem();
if (selectedFigure != null && !selectedFigure.isEmpty()) {
currentPlayer.setFigure(new Figure(0, 0, 0, Rotation.RIGHT, "selectedFigure"));
System.out.println("Player figure set to: " + selectedFigure);
} else {
System.err.println("Invalid figure selection.");
}
}
/**
* Lädt das Hintergrundbild und fügt es als geometrische Ebene hinzu.
*/
private void addBackgroundImage() {
Texture backgroundImage = app.getAssetManager().loadTexture("Pictures/lobby.png");
@@ -245,11 +261,6 @@ public class LobbyMenu extends Dialog {
app.getGuiNode().attachChild(background);
}
/**
* Creates a circle graphic element for the menu.
*
* @return the created circle geometry
*/
private Geometry createCircle() {
Sphere sphere = new Sphere(90,90,60.0f);
@@ -257,89 +268,106 @@ public class LobbyMenu extends Dialog {
// Create a material with a solid color
Material material = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
material.setColor("Color", Player.getColor(app.getId()).getColor()); // Set the desired color
material.setColor("Color", playerColor); // Set the desired color
circleGeometry.setMaterial(material);
return circleGeometry;
}
public void setPlayerColor(ColorRGBA newColor) {
this.playerColor = newColor;
// Update the circle's color
if (circle != null) {
Material material = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
material.setColor("Color", playerColor);
circle.setMaterial(material);
}
}
/**
* Toggles the player's ready state and sends the configuration to the server.
* Assigns a color to the player based on their ID.
*
* @param playerID the player's ID
*/
private void toggleReady() {
app.getGameLogic().send(new PlayerReady(true, playerInputField.getText(), figure, Integer.parseInt(startingCapital.getText())));
}
/**
* Opens the settings menu when the escape key is pressed.
*/
@Override
public void escape() {
new SettingsMenu(app).open();
}
/**
* Updates the menu at regular intervals.
* Checks if the dropdown selection has been updated and invokes the selection change handler.
*
* @param tpf Time per frame, in seconds, since the last update.
* Adds a custom action listener to the Selector.
*/
@Override
public void update(float tpf) {
if (selectionRef.update()) {
onDropdownSelectionChanged(figureDropdown);
}
}
private void addSelectionActionListener(Selector<String> selector, SelectionActionListener<String> listener) {
VersionedReference<Set<Integer>> selectionRef = selector.getSelectionModel().createReference();
/**
* Closes the current menu and transitions music playback.
* Stops the secondary music (if playing) and resumes the main background music
* if music is enabled in the preferences. Ensures smooth transitions in audio.
*/
@Override
public void close() {
GameMusic music = app.getStateManager().getState(GameMusic.class);
if (music != null) {
music.stopSecondaryMusic();
if (music.isEnabled()) {
music.playMainMusic();
app.getStateManager().attach(new BaseAppState() {
@Override
public void update(float tpf) {
if (selectionRef.update()) {
String selected = selectionRef.get().toString();
System.out.println(selected);
listener.onSelectionChanged(selected);
}
}
}
super.close();
@Override
protected void initialize(Application app) {
}
@Override
protected void cleanup(Application app) {
}
@Override
protected void onEnable() {
}
@Override
protected void onDisable() {
}
});
}
/**
* Updates the selected figure based on the dropdown menu selection.
*
* @param selector the selected figure
* Callback for when the dropdown selection changes.
*/
private void onDropdownSelectionChanged(Selector<String> selector) {
private void onDropdownSelectionChanged(String selected) {
System.out.println("Selected: " + selected);
app.getGameLogic().playSound(Sound.BUTTON);
switch (selector.getSelectedItem()) {
case "Jägermeister":
figure = "Jaegermeister";
switch (selected) {
case "[0]":
figure = "Laptop";
break;
case "Handyholster":
figure = "Holster";
case "[1]":
figure = "Flugzeug";
break;
case "[2]":
figure = "Jägermeister";
break;
case "[3]":
figure = "Katze";
break;
case "[4]":
figure = "OOP";
break;
case "[5]":
figure = "Handyholster";
break;
default:
figure = selector.getSelectedItem();
break;
}
}
/**
* Functional interface for handling selection changes in dropdown menus.
*
* @param <T> the type of the selection
* Functional interface for a selection action listener.
*/
@FunctionalInterface
private interface SelectionActionListener<T> {
/**
* Triggered when the selection changes.
*
* @param selection the new selection
*/
void onSelectionChanged(T selection);
}
}

View File

@@ -0,0 +1,22 @@
package pp.monopoly.client.gui;
import com.jme3.effect.ParticleMesh.Type;
import pp.monopoly.client.MonopolyApp;
/**
* Factory class responsible for creating particle effects used in the game.
* This centralizes the creation of various types of particle emitters.
*/
public class ParticleEffectFactory {
private static final int COUNT_FACTOR = 1;
private static final float COUNT_FACTOR_F = 1f;
private static final boolean POINT_SPRITE = true;
private static final Type EMITTER_TYPE = POINT_SPRITE ? Type.Point : Type.Triangle;
private final MonopolyApp app;
ParticleEffectFactory(MonopolyApp app) {
this.app = app;
}
}

View File

@@ -1,271 +0,0 @@
package pp.monopoly.client.gui;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.control.AbstractControl;
import com.simsilica.lemur.*;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.component.SpringGridLayout;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.game.server.Player;
import pp.monopoly.model.fields.BuildingProperty;
import pp.monopoly.model.fields.FoodField;
import pp.monopoly.model.fields.GateField;
import pp.monopoly.model.fields.PropertyField;
import pp.monopoly.notification.Sound;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
/**
* PropertyOverviewMenu is a dialog for displaying the player's properties in the game.
*/
public class PropertyOverviewMenu extends Dialog {
private final MonopolyApp app;
private final Container mainContainer;
private final Container displayContainer;
private final Slider horizontalSlider;
private final List<Container> cards;
/**
* Constructs the PropertyOverviewMenu dialog.
*
* @param app The Monopoly application instance.
*/
public PropertyOverviewMenu(MonopolyApp app) {
super(app.getDialogManager());
this.app = app;
// Make the menu fullscreen
Vector3f screenSize = new Vector3f(app.getCamera().getWidth(), app.getCamera().getHeight(), 0);
// Main container for the menu layout
mainContainer = new Container();
mainContainer.setPreferredSize(screenSize); // Make fullscreen
mainContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(1.0f, 1.0f, 1.0f, 0.8f))); // Semi-transparent background
// Header label
Label headerLabel = mainContainer.addChild(new Label("Meine Grundstücke", new ElementId("header")));
headerLabel.setFontSize(40);
// Central display container (to hold the "Gebäude" cards)
displayContainer = mainContainer.addChild(new Container(new SpringGridLayout(Axis.X, Axis.Y, FillMode.Even, FillMode.None))); // Horizontal layout
displayContainer.setPreferredSize(new Vector3f(screenSize.x - 300, 550, 0)); // Take up the remaining width
displayContainer.setBackground(new QuadBackgroundComponent(ColorRGBA.White));
displayContainer.setLocalTranslation(0, 0, 11);
// Add some placeholder "Gebäude" cards to the display container
cards = new ArrayList<>();
populatePlayerProperties();
// Initially add only visible cards to the displayContainer
refreshVisibleCards(0);
// Horizontal slider for scrolling through cards
horizontalSlider = mainContainer.addChild(new Slider(Axis.X));
horizontalSlider.setPreferredSize(new Vector3f(screenSize.x - 300, 20, 5));
horizontalSlider.setModel(new DefaultRangedValueModel(0, Math.max(0, cards.size() - 5), 0));
horizontalSlider.addControl(new SliderValueChangeListener());
// Add the "Zurück" button at the bottom
Button backButton = mainContainer.addChild(new Button("Zurück", new ElementId("button")));
backButton.setPreferredSize(new Vector3f(200, 60, 0));
backButton.addClickCommands(source -> ifTopDialog( () -> {
app.getGameLogic().playSound(Sound.BUTTON);
close();
}));
// Attach the main container to the GUI node
app.getGuiNode().attachChild(mainContainer);
mainContainer.setLocalTranslation(
0,
app.getCamera().getHeight(), // Align to the top
10
);
}
/**
* Fetches the player's properties and populates them into the cards list.
*/
private void populatePlayerProperties() {
// Fetch the current player
Player currentPlayer = app.getGameLogic().getPlayerHandler().getPlayerById(app.getId());
// Fetch the player's properties using their indices
List<PropertyField> fields = new ArrayList<>();
for (Integer i : currentPlayer.getProperties()) {
fields.add((PropertyField) app.getGameLogic().getBoardManager().getFieldAtIndex(i));
}
// Iterate through the fetched properties
for (PropertyField property : fields.stream().sorted(Comparator.comparingInt(PropertyField::getId)).collect(Collectors.toList())) {
if (property instanceof BuildingProperty) {
BuildingProperty building = (BuildingProperty) property;
cards.add(createBuildingCard(building));
} else if (property instanceof FoodField) {
FoodField foodField = (FoodField) property;
cards.add(createFoodFieldCard(foodField));
} else if (property instanceof GateField) {
GateField gateField = (GateField) property;
cards.add(createGateFieldCard(gateField));
}
}
}
/**
* Creates a card for BuildingProperty with detailed rent and cost information.
*/
private Container createBuildingCard(BuildingProperty field) {
Container card = new Container();
card.setPreferredSize(new Vector3f(200, 300, 2)); // Match the size of the BuildingPropertyCard
card.setBackground(new QuadBackgroundComponent(field.getColor().getColor()));
card.setInsets(new Insets3f(5, 5, 5, 5)); // Add 5-pixel inset
card.addChild(new Label(field.getName(), new ElementId("label-Bold"))).setFontSize(25);
// Add property details
Container propertyValuesContainer = card.addChild(new Container());
propertyValuesContainer.addChild(new Label("Grundstückswert: " + field.getPrice()+ " EUR", new ElementId("label-Text"))).setFontSize(14);
propertyValuesContainer.addChild(new Label("", new ElementId("label-Text"))).setFontSize(14); // Leerzeile
propertyValuesContainer.addChild(new Label("Miete allein: " + field.getAllRent().get(0)+ " EUR", new ElementId("label-Text"))).setFontSize(14);
propertyValuesContainer.addChild(new Label("- mit 1 Haus: " + field.getAllRent().get(1)+ " EUR", new ElementId("label-Text"))).setFontSize(14);
propertyValuesContainer.addChild(new Label("- mit 2 Häuser: " + field.getAllRent().get(2)+ " EUR", new ElementId("label-Text"))).setFontSize(14);
propertyValuesContainer.addChild(new Label("- mit 3 Häuser: " + field.getAllRent().get(3)+ " EUR", new ElementId("label-Text"))).setFontSize(14);
propertyValuesContainer.addChild(new Label("- mit 4 Häuser: " + field.getAllRent().get(4)+ " EUR", new ElementId("label-Text"))).setFontSize(14);
propertyValuesContainer.addChild(new Label("- mit 1 Hotel: " + field.getAllRent().get(5)+ " EUR", new ElementId("label-Text"))).setFontSize(14);
propertyValuesContainer.addChild(new Label("- 1 Haus kostet: " + field.getHousePrice()+ " EUR", new ElementId("label-Text"))).setFontSize(14);
propertyValuesContainer.addChild(new Label("", new ElementId("label-Text"))).setFontSize(14); // Leerzeile
Label hypo = new Label("Hypothek: " + field.getHypo()+ " EUR", new ElementId("label-Text"));
hypo.setFontSize(14);
if (field.isMortgaged()) hypo.setColor(ColorRGBA.Red);
propertyValuesContainer.addChild(hypo);
propertyValuesContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
return card;
}
/**
* Creates a card for FoodField with dynamic pricing and rent details.
*/
private Container createFoodFieldCard(FoodField field) {
Container card = new Container();
card.setPreferredSize(new Vector3f(200, 300, 2)); // Adjust card size
card.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.1f, 0.1f, 0.1f, 0.9f))); // Dark background for card
card.setInsets(new Insets3f(5, 5, 5, 5)); // Add 5-pixel inset
// Title Section
Label title = card.addChild(new Label(field.getName(), new ElementId("label-Bold")));
title.setFontSize(30);
title.setColor(ColorRGBA.White); // Ensure readability on dark background
// Property Values Section
Container propertyValuesContainer = card.addChild(new Container());
propertyValuesContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f))); // Grey background
propertyValuesContainer.addChild(new Label("Preis: " + field.getPrice()+ " EUR", new ElementId("label-Text"))).setFontSize(14);
propertyValuesContainer.addChild(new Label("", new ElementId("label-Text"))).setFontSize(14); // Leerzeile
propertyValuesContainer.addChild(new Label("Wenn man Besitzer der", new ElementId("label-Text"))).setFontSize(14);
propertyValuesContainer.addChild(new Label(field.getName() + " ist, so ist", new ElementId("label-Text"))).setFontSize(14);
propertyValuesContainer.addChild(new Label("die Miete 40x Würfelwert.", new ElementId("label-Text"))).setFontSize(14);
propertyValuesContainer.addChild(new Label("", new ElementId("label-Text"))).setFontSize(14); // Leerzeile
propertyValuesContainer.addChild(new Label("Besitzer beider", new ElementId("label-Text"))).setFontSize(14);
propertyValuesContainer.addChild(new Label("Restaurants zahlt", new ElementId("label-Text"))).setFontSize(14);
propertyValuesContainer.addChild(new Label("100x Würfelwert.", new ElementId("label-Text"))).setFontSize(14);
propertyValuesContainer.addChild(new Label("", new ElementId("label-Text"))).setFontSize(14); // Leerzeile
propertyValuesContainer.addChild(new Label("Hypothek: " + field.getHypo()+ " EUR", new ElementId("label-Text"))).setFontSize(14);
return card;
}
/**
* Creates a card for GateField with rent details for owning multiple gates.
*/
private Container createGateFieldCard(GateField field) {
Container card = new Container();
card.setPreferredSize(new Vector3f(200, 300, 2)); // Adjust card size
card.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f))); // Light grey background
card.setInsets(new Insets3f(5, 5, 5, 5)); // Add 5-pixel inset
// Title Section
Label title = card.addChild(new Label(field.getName(), new ElementId("label-Bold")));
title.setFontSize(30);
title.setColor(ColorRGBA.Black);
// Property Values Section
Container propertyValuesContainer = card.addChild(new Container());
propertyValuesContainer.addChild(new Label("Preis: " + field.getPrice()+ " EUR", new ElementId("label-Text"))).setFontSize(14);
propertyValuesContainer.addChild(new Label("", new ElementId("label-Text"))).setFontSize(14);
propertyValuesContainer.addChild(new Label("Miete: 250 EUR", new ElementId("label-Text"))).setFontSize(14);
propertyValuesContainer.addChild(new Label("Wenn man", new ElementId("label-Text"))).setFontSize(14);
propertyValuesContainer.addChild(new Label("2 Bahnhof besitzt: 500 EUR", new ElementId("label-Text"))).setFontSize(14);
propertyValuesContainer.addChild(new Label("Wenn man", new ElementId("label-Text"))).setFontSize(14);
propertyValuesContainer.addChild(new Label("3 Bahnhof besitzt: 1000 EUR", new ElementId("label-Text"))).setFontSize(14);
propertyValuesContainer.addChild(new Label("Wenn man", new ElementId("label-Text"))).setFontSize(14);
propertyValuesContainer.addChild(new Label("4 Bahnhof besitzt: 2000 EUR", new ElementId("label-Text"))).setFontSize(14);
propertyValuesContainer.addChild(new Label("", new ElementId("label-Text"))).setFontSize(14);
propertyValuesContainer.addChild(new Label("„Hypothek: " + field.getHypo() + " EUR", new ElementId("label-Text"))).setFontSize(14);
propertyValuesContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f))); // Dark grey background
return card;
}
/**
* Updates the visible cards in the displayContainer based on the slider value.
*
* @param startIndex The starting index of the visible cards.
*/
private void refreshVisibleCards(int startIndex) {
displayContainer.clearChildren(); // Remove all current children
int maxVisible = 5; // Number of cards to display at once
for (int i = startIndex; i < startIndex + maxVisible && i < cards.size(); i++) {
displayContainer.addChild(cards.get(i));
}
}
/**
* Custom listener for slider value changes.
* Extends {@link AbstractControl} to respond to updates in the slider's value and refresh
* the visible cards accordingly.
*/
private class SliderValueChangeListener extends AbstractControl {
@Override
protected void controlUpdate(float tpf) {
// Get the slider's current value and refresh visible cards
int sliderValue = (int) ((Slider) getSpatial()).getModel().getValue();
refreshVisibleCards(sliderValue);
}
/**
* Overrides the rendering logic for the control.
* <p>
* This implementation does not require any rendering operations, so the method is left empty.
*
* @param renderManager the {@link RenderManager} handling the rendering process.
* @param viewPort the {@link ViewPort} associated with the rendering context.
*/
@Override
protected void controlRender(RenderManager renderManager, ViewPort viewPort) {
// No rendering logic needed
}
}
/**
* Closes the dialog and detaches it from the GUI node.
*/
@Override
public void close() {
app.getGuiNode().detachChild(mainContainer);
super.close();
}
}

View File

@@ -14,6 +14,7 @@ import com.simsilica.lemur.Checkbox;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.style.ElementId;
import static pp.monopoly.Resources.lookup;
import pp.monopoly.client.GameMusic;
import pp.monopoly.client.GameSound;
import pp.monopoly.client.MonopolyApp;
@@ -24,44 +25,19 @@ import pp.monopoly.notification.Sound;
import static pp.util.PreferencesUtils.getPreferences;
/**
* The Menu class represents the main menu in the Monopoly game application.
* It extends the Dialog class and provides functionalities for Volume adjustment, Sound adjustment,
* The Menu class represents the main menu in the Battleship game application.
* It extends the Dialog class and provides functionalities for loading, saving,
* returning to the game, and quitting the application.
*/
public class SettingsMenu extends Dialog {
/**
* Preferences instance for storing and retrieving settings specific to the SettingsMenu.
*/
private static final Preferences PREFERENCES = getPreferences(SettingsMenu.class);
/**
* Reference to the main Monopoly application instance.
*/
private static final String LAST_PATH = "last.file.path";
private final MonopolyApp app;
/**
* Slider control for adjusting the music volume.
*/
private final VolumeSlider musicSlider;
/**
* Slider control for adjusting the sound effects volume.
*/
private final SoundSlider soundSlider;
/**
* Checkbox for toggling sound effects.
*/
private final Checkbox soundCheckbox;
/**
* Checkbox for toggling background music.
*/
private final Checkbox musicCheckbox;
/**
* Constructs the Menu dialog for the Monopoly application.
* Constructs the Menu dialog for the Battleship application.
*
* @param app the MonopolyApp instance
*/
@@ -75,14 +51,10 @@ public class SettingsMenu extends Dialog {
addChild(soundSlider);
soundCheckbox = new Checkbox("Soundeffekte an / aus", new StateCheckboxModel(app, GameSound.class));
addChild(soundCheckbox);
addChild(new Checkbox("Soundeffekte an / aus", new StateCheckboxModel(app, GameSound.class)));
addChild(new Label("Hintergrund Musik", new ElementId("label"))); //NON-NLS
musicCheckbox = new Checkbox("Musik an / aus", new StateCheckboxModel(app, GameMusic.class));
musicCheckbox.addClickCommands(s -> toggleMusicPreference());
addChild(musicCheckbox);
addChild(new Checkbox("Musik an / aus", new StateCheckboxModel(app, GameMusic.class)));
addChild(musicSlider);
@@ -98,42 +70,16 @@ public class SettingsMenu extends Dialog {
}
/**
* Toggles the music preference based on the state of the musicCheckbox.
* Enables or disables background music and starts playback if enabled.
*/
private void toggleMusicPreference() {
boolean enabled = musicCheckbox.isChecked();
GameMusic gameMusic = app.getStateManager().getState(GameMusic.class);
if (gameMusic != null) {
gameMusic.setEnabled(enabled);
if (enabled) {
gameMusic.playMainMusic();
}
}
}
/**
* Updates the state of the music checkbox to match the current preferences.
* This ensures the checkbox reflects the actual enabled/disabled state of the music.
* Updates the state of the load and save buttons based on the game logic.
*/
@Override
public void update() {
GameMusic gameMusic = app.getStateManager().getState(GameMusic.class);
if (gameMusic != null) {
musicCheckbox.setChecked(gameMusic.isEnabled());
}
}
/**
* Updates UI elements such as sliders and synchronizes the state of the settings menu.
*
* @param delta the time in seconds since the last update
*/
@Override
public void update(float delta) {
musicSlider.update();
soundSlider.update();
update();
}
/**

View File

@@ -5,14 +5,7 @@ import pp.monopoly.client.GameSound;
public class SoundSlider extends Slider {
/**
* Manages sound effects for the game.
*/
private final pp.monopoly.client.GameSound sound;
/**
* Volume level for the game sounds.
*/
private double vol;
/**
@@ -27,7 +20,7 @@ public class SoundSlider extends Slider {
}
/**
* When triggered it updates the volume to the value set with the slider
* when triggered it updates the volume to the value set with the slider
*/
public void update() {
if (vol != getModel().getPercent()) {

View File

@@ -18,6 +18,7 @@ import pp.monopoly.notification.Sound;
/**
* Constructs the startup menu dialog for the Monopoly application.
import pp.monopoly.client.gui.GameMenu;
*/
public class StartMenu extends Dialog {
private final MonopolyApp app;
@@ -41,63 +42,70 @@ public class StartMenu extends Dialog {
Material backgroundMaterial = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
backgroundMaterial.setTexture("ColorMap", backgroundImage);
background.setMaterial(backgroundMaterial);
background.setLocalTranslation(0, 0, -1);
background.setLocalTranslation(0, 0, -1); // Ensure it is behind other GUI elements
app.getGuiNode().attachChild(background);
// Center container for title and play button
Container centerMenu = new Container(new SpringGridLayout(Axis.Y, Axis.X));
Button startButton = new Button("Spielen");
startButton.setPreferredSize(new Vector3f(190, 60, 0));
startButton.setFontSize(40);
startButton.setTextHAlignment(HAlignment.Center);
startButton.setPreferredSize(new Vector3f(190, 60, 0)); // Increase button size (width, height)
startButton.setFontSize(40); // Set the font size for the button text
startButton.setTextHAlignment(HAlignment.Center); // Center the text horizontally
startButton.addClickCommands(s -> ifTopDialog(() -> {
close();
this.close(); // Close the StartMenu dialog
app.connect(); // Perform the connection logic
app.getGameLogic().playSound(Sound.BUTTON);
app.connect();
}));
centerMenu.addChild(startButton);
// Position the center container in the middle of the screen
centerMenu.setLocalTranslation(new Vector3f(screenWidth / 2f - centerMenu.getPreferredSize().x / 2f,
screenHeight / 2f - 280 + centerMenu.getPreferredSize().y / 2f,
0));
app.getGuiNode().attachChild(centerMenu);
// Load the Monopoly logo as a texture
Texture logoTexture = app.getAssetManager().loadTexture("Pictures/logo-monopolyw.png");
Texture logoTexture = app.getAssetManager().loadTexture("Pictures/logo-monopoly.png");
// Create a container for the logo
Container logoContainer = new Container();
QuadBackgroundComponent logoBackground = new QuadBackgroundComponent(logoTexture);
logoContainer.setBackground(logoBackground);
float logoWidth = 512;
float logoHeight = 128;
// Set the size of the container to fit the logo
float logoWidth = 512; // Adjust these values based on the logo dimensions
float logoHeight = 128; // Adjust these values based on the logo dimensions
logoContainer.setPreferredSize(new Vector3f(logoWidth, logoHeight, 0));
// Position the container at the center of the screen
logoContainer.setLocalTranslation(new Vector3f(
screenWidth / 2f - logoWidth / 2f,
screenHeight / 2f + 200,
screenHeight / 2f + 200, // Adjust this value for vertical position
0
));
// Attach the container to the GUI node
app.getGuiNode().attachChild(logoContainer);
// Load the Unibw logo as a texture
Texture unibwTexture = app.getAssetManager().loadTexture("Pictures/logo-unibw.png");
// Create a container for the Unibw logo
Container unibwContainer = new Container();
QuadBackgroundComponent unibwBackground = new QuadBackgroundComponent(unibwTexture);
unibwContainer.setBackground(unibwBackground);
float unibwWidth = 662;
float unibwHeight = 180;
// Set the size of the container to fit the Unibw logo
float unibwWidth = 512; // Adjust these values based on the logo dimensions
float unibwHeight = 128; // Adjust these values based on the logo dimensions
unibwContainer.setPreferredSize(new Vector3f(unibwWidth, unibwHeight, 0));
// Position the container slightly below the Monopoly logo
unibwContainer.setLocalTranslation(new Vector3f(
screenWidth / 2f - unibwWidth / 2f,
screenHeight / 2f + 100,
screenHeight / 2f + 100, // Adjust this value for vertical position
0
));
@@ -105,17 +113,11 @@ public class StartMenu extends Dialog {
app.getGuiNode().attachChild(unibwContainer);
}
/**
* Opens the settings menu when the escape key is pressed.
*/
@Override
public void escape() {
new SettingsMenu(app).open();
}
/**
* Closes the startup menu and detaches all GUI elements.
*/
@Override
public void close() {
app.getGuiNode().detachAllChildren();

View File

@@ -0,0 +1,114 @@
package pp.monopoly.client.gui;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;
import com.jme3.texture.Texture;
import pp.monopoly.client.MonopolyApp;
/**
* TestWorld zeigt eine einfache Szene mit einem texturierten Quadrat.
* Die Kamera wird durch den CameraController gesteuert.
*/
public class TestWorld {
private final MonopolyApp app;
private CameraController cameraController; // Steuert die Kamera
private Geometry cube; // Spielfigur
/**
* Konstruktor für TestWorld.
*
* @param app Die Hauptanwendung (MonopolyApp)
*/
public TestWorld(MonopolyApp app) {
this.app = app;
}
/**
* Initialisiert die Szene und startet die Kamerabewegung.
*/
public void initializeScene() {
app.getGuiNode().detachAllChildren(); // Entferne GUI
app.getRootNode().detachAllChildren(); // Entferne andere Szenenobjekte
setSkyColor(); // Setze den Himmel auf hellblau
createBoard(); // Erstelle das Spielfeld
createCube(); // Füge den Würfel hinzu
// Erstelle den CameraController
cameraController = new CameraController(
app.getCamera(), // Die Kamera der App
Vector3f.ZERO, // Fokus auf die Mitte des Spielfelds
4, // Radius des Kreises
15, // Höhe der Kamera
0 // Geschwindigkeit der Bewegung
);
// Füge die Toolbar hinzu
new Toolbar(app, cube);
cameraController.setPosition(0);
}
/**
* Aktualisiert die Kameraposition.
*
* @param tpf Zeit pro Frame
*/
public void update(float tpf) {
if (cameraController != null) {
cameraController.update(tpf);
}
}
/**
* Setzt die Hintergrundfarbe der Szene auf hellblau.
*/
private void setSkyColor() {
app.getViewPort().setBackgroundColor(new ColorRGBA(0.5f, 0.7f, 1.0f, 1.0f)); // Hellblauer Himmel
}
/**
* Erstelle das Spielfeld.
*/
private void createBoard() {
// Erstelle ein Quadrat
Box box = new Box(10, 0.1f, 10); // Dünnes Quadrat für die Textur
Geometry geom = new Geometry("Board", box);
// Setze das Material mit Textur
Material mat = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
Texture texture = app.getAssetManager().loadTexture("Pictures/board2.png");
mat.setTexture("ColorMap", texture);
geom.setMaterial(mat);
app.getRootNode().attachChild(geom);
}
/**
* Erstellt den Würfel (Spielfigur) in der Szene.
*/
private void createCube() {
Box box = new Box(0.05f, 0.05f, 0.05f); // Kleinere Größe für Spielfigur
cube = new Geometry("Cube", box);
// Setze das Material für den Würfel
Material mat = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("Color", ColorRGBA.Blue); // Blau gefärbter Würfel
cube.setMaterial(mat);
// Setze den Startpunkt des Würfels
cube.setLocalTranslation(0.8999999f, 0.1f, -0.9f);
app.getRootNode().attachChild(cube);
}
}

View File

@@ -1,553 +1,250 @@
package pp.monopoly.client.gui;
import com.jme3.input.event.MouseButtonEvent;
import com.jme3.input.event.MouseMotionEvent;
import java.util.Random;
import com.jme3.font.BitmapText;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.scene.Spatial;
import com.jme3.texture.Texture;
import com.simsilica.lemur.Axis;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.HAlignment;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.VAlignment;
import com.simsilica.lemur.component.IconComponent;
import com.jme3.scene.Geometry;
import com.simsilica.lemur.*;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.component.SpringGridLayout;
import com.simsilica.lemur.event.MouseEventControl;
import com.simsilica.lemur.event.MouseListener;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.client.gui.popups.Bankrupt;
import pp.monopoly.game.server.Player;
import pp.monopoly.game.server.PlayerHandler;
import pp.monopoly.message.client.EndTurn;
import pp.monopoly.message.client.RollDice;
import pp.monopoly.notification.ButtonStatusEvent;
import pp.monopoly.notification.DiceRollEvent;
import pp.monopoly.notification.GameEventListener;
import pp.monopoly.notification.Sound;
import pp.monopoly.notification.UpdatePlayerView;
/**
* Represents the toolbar interface in the Monopoly application.
* Provides game controls, player information, and event handling.
* Toolbar Klasse, die am unteren Rand der Szene angezeigt wird.
* Die Buttons bewegen den Würfel auf dem Spielfeld.
*/
public class Toolbar extends Dialog implements GameEventListener {
public class Toolbar extends Dialog {
/** The Monopoly application instance*/
private final MonopolyApp app;
/** The container representing the toolbar interface */
private final Container toolbarContainer;
/** The container representing the player overview information */
private Container overviewContainer;
/** The container representing the player account information */
private Container accountContainer;
/** The player handler instance */
private PlayerHandler playerHandler;
/** The label representing the left dice */
private Label imageLabel;
/** The label representing the right dice */
private Label imageLabel2;
/** The flag to check if the dice can be rolled */
private boolean canRollDice = false;
/** The trade button */
private Button tradeButton;
/** The property menu button */
private Button propertyMenuButton;
/** The end turn button */
private Button endTurnButton;
/** The latest incoming Dice Roll Event */
private DiceRollEvent latestDiceRollEvent = null;
/** The flag to check if the bankrupt pop up is already shown */
private boolean bankruptPopUp = false;
private final Geometry cube; // Referenz auf den Würfel
private final BitmapText positionText; // Anzeige für die aktuelle Position
private final float boardLimit = 0.95f; // Grenzen des Bretts
private final float stepSize = 0.18f; // Schrittgröße pro Bewegung
private int currentPosition = 0; // Aktuelle Position auf dem Spielfeld
private final int positionsPerSide = 10; // Anzahl der Positionen pro Seite
private final Random random = new Random(); // Zufallsgenerator für den Würfelwurf
/**
* Constructs a new {@code Toolbar} for the given {@code MonopolyApp}.
* Konstruktor für die Toolbar.
*
* @param app The {@code MonopolyApp} instance to create the toolbar for.
* @param app Die Hauptanwendung (MonopolyApp)
* @param cube Der Würfel, der bewegt werden soll
*/
public Toolbar(MonopolyApp app) {
public Toolbar(MonopolyApp app, Geometry cube) {
super(app.getDialogManager());
this.app = app;
this.cube = cube;
app.getGameLogic().addListener(this);
this.playerHandler = app.getGameLogic().getPlayerHandler();
// Erstelle die Toolbar
toolbarContainer = new Container(new SpringGridLayout(Axis.X, Axis.Y), "toolbar");
toolbarContainer = setupToolbar();
// Setze die Position am unteren Rand und die Breite
toolbarContainer.setLocalTranslation(
0, // Links bündig
200, // Höhe über dem unteren Rand
0 // Z-Ebene
);
toolbarContainer.setPreferredSize(new Vector3f(app.getCamera().getWidth(), 200, 0)); // Volle Breite
// Füge Buttons zur Toolbar hinzu
//initializeButtons();
// Menü-Container: Ein Nested-Container für Kontostand und "Meine Gulag Frei Karten"
Container accountContainer = toolbarContainer.addChild(new Container());
accountContainer.addChild(new Label("Kontostand", new ElementId("label-Bold")));
accountContainer.addChild(new Label("6666€", new ElementId("label-Text"))); //TODO Variable hier einsetzen
accountContainer.addChild(new Label("Gulag Frei Karten", new ElementId("label-Bold")));
accountContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
// Add a spacer between accountContainer and overviewContainer
Panel spacer = new Panel(); // Create an empty panel as a spacer
spacer.setPreferredSize(new Vector3f(5, 0, 0)); // Adjust the width as needed
spacer.setBackground(null);
toolbarContainer.addChild(spacer);
// Menü-Container: Ein Container für Übersicht
Container overviewContainer = toolbarContainer.addChild(new Container());
overviewContainer.addChild(new Label("Übersicht", new ElementId("label-Bold")));
overviewContainer.addChild(new Label("„Spieler 1“: 1244€", new ElementId("label-Text")));//TODO Variable hier einsetzen
overviewContainer.addChild(new Label("„Spieler 2“: 1244€", new ElementId("label-Text")));//TODO Variable hier einsetzen
overviewContainer.addChild(new Label("„Spieler 3“: 1244€", new ElementId("label-Text")));//TODO Variable hier einsetzen
overviewContainer.addChild(new Label("„Spieler 4“: 1244€", new ElementId("label-Text")));//TODO Variable hier einsetzen
overviewContainer.addChild(new Label("„Spieler 5“: 1244€", new ElementId("label-Text")));//TODO Variable hier einsetzen
overviewContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
// Menü-Container: Ein Container für Würfel
Container diceContainer = toolbarContainer.addChild(new Container());
diceContainer.setPreferredSize(new Vector3f(400, 150, 0));
diceContainer.addChild(new Label("Wo Würfel?", new ElementId("label")));
diceContainer.addChild(addDiceRollButton());
diceContainer.setBackground(null);
// Menü-Container: Ein Nested-Container für Handeln, Grundstücke und Zug beenden
Container menuContainer = toolbarContainer.addChild(new Container());
menuContainer.addChild(new Button("Handeln"));
menuContainer.addChild(new Button("Grundstücke"));
menuContainer.addChild(new Button("Zug beenden"));
menuContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
// Füge die Toolbar zur GUI hinzu
app.getGuiNode().attachChild(toolbarContainer);
endTurnButton.setEnabled(false);
// Erstelle die Position-Anzeige
positionText = createPositionDisplay();
updatePositionDisplay(); // Initialisiere die Anzeige mit der Startposition
}
/**
* Sets up the toolbar interface with the game controls, player information, and event handling.
* Initialisiert die Buttons in der Toolbar.
*/
private void initializeButtons() {
addTradeMenuButton(); // Bewegung nach vorne
addEndTurnButton(); // Bewegung nach hinten
addDiceRollButton(); // Würfel-Button
}
/**
* Fügt einen Button mit einer Bewegung hinzu.
*
* @return The container representing the toolbar interface.
* @param label Der Text des Buttons
* @param step Schrittweite (+1 für vorwärts, -1 für rückwärts)
*/
private Container setupToolbar() {
Container container = new Container(new SpringGridLayout(Axis.X, Axis.Y), "toolbar");
container.setLocalTranslation(0, 200, 0);
container.setPreferredSize(new Vector3f(app.getCamera().getWidth(), 200, 0));
Texture backgroundToolbar = app.getAssetManager().loadTexture("Pictures/toolbarbg.png");
QuadBackgroundComponent background = new QuadBackgroundComponent(backgroundToolbar);
background.setMargin(0, 0); // Removes any internal margin
container.setBackground(background);
setupBorders(container);
setupSpacer(container);
setupPlayerInfoSection(container);
setupSpacer(container);
setupDiceSection(container);
setupActionMenu(container);
return container;
}
/*private void addButton(String label, int step) {
Button button = new Button(label);
button.setPreferredSize(new Vector3f(150, 50, 0)); // Größe der Buttons
button.addClickCommands(source -> moveCube(step));
toolbarContainer.addChild(button);
}*/
/**
* Sets up the borders for the toolbar interface.
*
* @param container The container representing the toolbar interface.
* Fügt den Würfel-Button hinzu, der die Figur entsprechend der gewürfelten Zahl bewegt.
*/
private void setupBorders(Container container) {
addBorder(0, 205, app.getCamera().getWidth(), 5, ColorRGBA.DarkGray); // Top
addBorder(0, 5, app.getCamera().getWidth(), 10, ColorRGBA.DarkGray); // Bottom
addBorder(0, 200, 8, 210, ColorRGBA.DarkGray); // Left
addBorder(app.getCamera().getWidth() - 5, 200, 8, 210, ColorRGBA.DarkGray); // Right
}
/**
* Adds a border to the toolbar interface with the specified dimensions and color.
*
* @param x The x-coordinate of the border.
* @param y The y-coordinate of the border.
* @param width The width of the border.
* @param height The height of the border.
* @param color The color of the border.
*/
private void addBorder(float x, float y, float width, float height, ColorRGBA color) {
Container border = new Container();
border.setPreferredSize(new Vector3f(width, height, 0));
border.setBackground(new QuadBackgroundComponent(color));
border.setLocalTranslation(x, y, 3);
app.getGuiNode().attachChild(border);
}
/**
* Adds a spacer to the specified container.
*
* @param container the container to which the spacer is added
*/
private void setupSpacer(Container container) {
Container spacer = container.addChild(new Container());
spacer.setPreferredSize(new Vector3f(20, 10, 0));
spacer.setBackground(null);
}
/**
* Sets up the player information section of the toolbar interface.
*
* @param parentContainer The container representing the toolbar interface.
*/
private void setupPlayerInfoSection(Container parentContainer) {
Container playerInfoSection = parentContainer.addChild(new Container(new SpringGridLayout(Axis.X, Axis.Y)));
playerInfoSection.setPreferredSize(new Vector3f(600, 300, 0)); // Adjust size for both containers
Texture backgroundTexture = app.getAssetManager().loadTexture("Pictures/"+ Player.getColor(app.getId()).getColorName()+ "Background.png");
QuadBackgroundComponent background = new QuadBackgroundComponent(backgroundTexture);
playerInfoSection.setBackground(background);
accountContainer = playerInfoSection.addChild(new Container());
accountContainer.setPreferredSize(new Vector3f(300, 300, 0));
accountContainer.setBackground(null);
overviewContainer = playerInfoSection.addChild(new Container());
overviewContainer.setPreferredSize(new Vector3f(300, 300, 0));
overviewContainer.setBackground(null);
refreshPlayerView();
}
/**
* Sets up the dice section of the toolbar interface.
*
* @param container The container representing the toolbar interface.
*/
private void setupDiceSection(Container container) {
Container diceContainer = container.addChild(new Container(new SpringGridLayout(Axis.X, Axis.Y)));
diceContainer.addChild(createDiceDisplay());
diceContainer.setBackground(null);
}
/**
* Sets up the action menu of the toolbar interface.
*
* @param container The container representing the toolbar interface.
*/
private void setupActionMenu(Container container) {
Container menuContainer = container.addChild(new Container());
menuContainer.addChild(createTradeButton());
menuContainer.addChild(createPropertyMenuButton());
menuContainer.addChild(createEndTurnButton());
menuContainer.setBackground(null);
}
/**
* Creates the dice display section of the toolbar interface.
*
* @return The container representing the dice display section.
*/
private Container createDiceDisplay() {
Container horizontalContainer = new Container(new SpringGridLayout(Axis.X, Axis.Y));
horizontalContainer.setPreferredSize(new Vector3f(200, 150, 0));
imageLabel = createDiceLabel("Pictures/dice/one.png");
imageLabel2 = createDiceLabel("Pictures/dice/two.png");
horizontalContainer.setBackground(null);
horizontalContainer.addChild(createDiceContainer(imageLabel));
horizontalContainer.addChild(createDiceContainer(imageLabel2));
// Add mouse event control for click handling
MouseEventControl.addListenersToSpatial(horizontalContainer, new MouseListener() {
@Override
public void mouseButtonEvent(MouseButtonEvent event, Spatial target, Spatial capture) {
if (event.isPressed()) {
handleDiceRoll();
}
}
@Override
public void mouseEntered(MouseMotionEvent event, Spatial target, Spatial capture) {
// Do nothing
}
@Override
public void mouseExited(MouseMotionEvent event, Spatial target, Spatial capture) {
// Do nothing
}
@Override
public void mouseMoved(MouseMotionEvent event, Spatial target, Spatial capture) {
// Do nothing
}
});
return horizontalContainer;
}
/**
* Creates a dice label with the specified icon path.
*
* @param iconPath The path to the icon image.
* @return The label representing the dice.
*/
private Label createDiceLabel(String iconPath) {
Label label = new Label("");
IconComponent icon = new IconComponent(iconPath);
icon.setIconSize(new Vector2f(80, 80));
label.setIcon(icon);
return label;
}
/**
* Creates a dice container with the specified label.
*
* @param label The label representing the dice.
* @return The container representing the dice.
*/
private Container createDiceContainer(Label label) {
Container container = new Container();
container.setBackground(null);
container.setPreferredSize(new Vector3f(100, 150, 0));
container.addChild(label);
return container;
}
/**
* Handles the dice roll event.
*/
private void handleDiceRoll() {
ifTopDialog(() -> {
if (!canRollDice) return;
canRollDice = false;
if (endTurnButton != null) endTurnButton.setEnabled(true);
startDiceAnimation();
app.getGameLogic().send(new RollDice());
app.getGameLogic().playSound(Sound.BUTTON);
});
}
private Button createTradeButton() {
String iconPath = "icons/icon-handeln.png";
// createActionButton(playerColor, "icons/icon-handeln.png", 100, () -> new ChoosePartner(app).open());
tradeButton = new ImageButton("generic", app);
tradeButton.setPreferredSize(new Vector3f(150, 50, 0));
IconComponent icon = new IconComponent(iconPath);
icon.setHAlignment(HAlignment.Center);
icon.setVAlignment(VAlignment.Center);
icon.setIconSize(new Vector2f(75 , 75));
tradeButton.setIcon(icon);
tradeButton.addClickCommands(s -> ifTopDialog(() -> {
new ChoosePartner(app).open();
private Button addDiceRollButton() {
Button diceButton = new Button("Würfeln");
diceButton.setPreferredSize(new Vector3f(50, 20, 0));
diceButton.addClickCommands(s -> ifTopDialog(() -> {
rollDice();
app.getGameLogic().playSound(Sound.BUTTON);
}));
return tradeButton;
toolbarContainer.addChild(diceButton);
return diceButton;
}
private Button createPropertyMenuButton() {
String iconPath = "icons/icon-gebaude.png";
propertyMenuButton = new ImageButton("generic", app);
propertyMenuButton.setPreferredSize(new Vector3f(150, 50, 0));
IconComponent icon = new IconComponent(iconPath);
icon.setHAlignment(HAlignment.Center);
icon.setVAlignment(VAlignment.Center);
icon.setIconSize(new Vector2f(50 , 50));
propertyMenuButton.setIcon(icon);
propertyMenuButton.addClickCommands(s -> ifTopDialog(() -> {
new BuildingAdminMenu(app).open();
private void addTradeMenuButton() {
Button diceButton = new Button("Handeln");
diceButton.setPreferredSize(new Vector3f(150, 50, 0)); // Größe des Buttons
diceButton.addClickCommands(s -> ifTopDialog(() -> {
rollDice();
app.getGameLogic().playSound(Sound.BUTTON);
}));
return propertyMenuButton;
toolbarContainer.addChild(diceButton);
}
private Button createEndTurnButton() {
// return createActionButton(playerColor, "icons/icon-zugbeenden.png", 75, () -> handleEndTurn());
String iconPath = "icons/icon-zugbeenden.png";
endTurnButton = new ImageButton("generic", app);
endTurnButton.setPreferredSize(new Vector3f(150, 50, 0));
IconComponent icon = new IconComponent(iconPath);
icon.setHAlignment(HAlignment.Center);
icon.setVAlignment(VAlignment.Center);
icon.setIconSize(new Vector2f(50 , 50));
endTurnButton.setIcon(icon);
endTurnButton.addClickCommands(s -> ifTopDialog(() -> {
handleEndTurn();
private void addEndTurnButton() {
Button diceButton = new Button("Grundstücke");
diceButton.setPreferredSize(new Vector3f(150, 50, 0)); // Größe des Buttons
diceButton.addClickCommands(s -> ifTopDialog(() -> {
rollDice();
app.getGameLogic().playSound(Sound.BUTTON);
}));
return endTurnButton;
toolbarContainer.addChild(diceButton);
}
private void addPropertyMenuButton() {
Button diceButton = new Button("Zug beenden");
diceButton.setPreferredSize(new Vector3f(150, 50, 0)); // Größe des Buttons
diceButton.addClickCommands(s -> ifTopDialog(() -> {
rollDice();
app.getGameLogic().playSound(Sound.BUTTON);
}));
toolbarContainer.addChild(diceButton);
}
/**
* Handles the end turn event.
* Simuliert einen Würfelwurf und bewegt die Figur entsprechend.
*/
private void handleEndTurn() {
Player currentPlayer = playerHandler.getPlayerById(app.getId());
if (currentPlayer.getAccountBalance() < 0 && !bankruptPopUp) {
new Bankrupt(app).open();
bankruptPopUp = true;
} else {
bankruptPopUp = false;
app.getGameLogic().send(new EndTurn());
receivedEvent(new ButtonStatusEvent(false));
private void rollDice() {
int diceRoll = random.nextInt(6) + 1; // Zahl zwischen 1 und 6
System.out.println("Gewürfelt: " + diceRoll);
moveCube(diceRoll); // Bewege die Figur um die gewürfelte Zahl
}
/**
* Bewegt den Würfel basierend auf der aktuellen Position auf dem Brett.
*
* @param step Schrittweite (+1 für vorwärts, -1 für rückwärts oder andere Werte)
*/
private void moveCube(int step) {
currentPosition = (currentPosition + step + 4 * positionsPerSide) % (4 * positionsPerSide);
Vector3f newPosition = calculatePosition(currentPosition);
cube.setLocalTranslation(newPosition);
updatePositionDisplay(); // Aktualisiere die Positionsanzeige
System.out.println("Würfelposition: " + newPosition + " (Feld-ID: " + currentPosition + ")");
}
/**
* Berechnet die neue Position des Würfels basierend auf der aktuellen Brettseite und Position.
*
* @param position Aktuelle Position auf dem Spielfeld
* @return Die berechnete Position als Vector3f
*/
private Vector3f calculatePosition(int position) {
int side = position / positionsPerSide; // Seite des Bretts (0 = unten, 1 = rechts, 2 = oben, 3 = links)
int offset = position % positionsPerSide; // Position auf der aktuellen Seite
switch (side) {
case 0: // Unten (positive x-Achse)
return new Vector3f(-boardLimit + offset * stepSize, 0.1f, -boardLimit + 0.05f);
case 1: // Rechts (positive z-Achse)
return new Vector3f(boardLimit - 0.05f, 0.1f, -boardLimit + offset * stepSize);
case 2: // Oben (negative x-Achse)
return new Vector3f(boardLimit - offset * stepSize, 0.1f, boardLimit - 0.05f);
case 3: // Links (negative z-Achse)
return new Vector3f(-boardLimit + 0.05f, 0.1f, boardLimit - offset * stepSize);
default:
throw new IllegalArgumentException("Ungültige Position: " + position);
}
}
/**
* Starts the dice animation.
*/
private void startDiceAnimation() {
long startTime = System.currentTimeMillis();
new Thread(() -> {
try {
animateDice(startTime);
if (latestDiceRollEvent != null) {
showFinalDiceResult(latestDiceRollEvent);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
/**
* Animates the dice roll.
* Erstellt die Anzeige für die aktuelle Position.
*
* @param startTime The start time of the animation.
* @throws InterruptedException If the animation is interrupted.
* @return Das BitmapText-Objekt für die Anzeige
*/
private void animateDice(long startTime) throws InterruptedException {
int[] currentFace = {1};
while (System.currentTimeMillis() - startTime < 2000) {
currentFace[0] = (currentFace[0] % 6) + 1;
updateDiceIcons(currentFace[0]);
Thread.sleep(100);
}
private BitmapText createPositionDisplay() {
BitmapText text = new BitmapText(app.getAssetManager().loadFont("Interface/Fonts/Default.fnt"), false);
text.setSize(20); // Schriftgröße
text.setLocalTranslation(10, app.getCamera().getHeight() - 10, 0); // Oben links
app.getGuiNode().attachChild(text);
return text;
}
/**
* Updates the dice icons with the specified face.
*
* @param face The face of the dice.
* Aktualisiert die Anzeige für die aktuelle Position.
*/
private void updateDiceIcons(int face) {
app.enqueue(() -> {
setDiceIcon(imageLabel, diceToString(face));
setDiceIcon(imageLabel2, diceToString((face % 6) + 1));
});
private void updatePositionDisplay() {
positionText.setText("Feld-ID: " + currentPosition);
}
/**
* Shows the final dice result.
*
* @param event The dice roll event.
* Entfernt die Toolbar.
*/
private void showFinalDiceResult(DiceRollEvent event) {
app.enqueue(() -> {
setDiceIcon(imageLabel, diceToString(event.a()));
setDiceIcon(imageLabel2, diceToString(event.b()));
});
}
/**
* Sets the dice icon with the specified image path.
*
* @param label The label representing the dice.
* @param imagePath The path to the icon image.
*/
private void setDiceIcon(Label label, String imagePath) {
IconComponent icon = new IconComponent(imagePath);
icon.setIconSize(new Vector2f(80, 80));
label.setIcon(icon);
}
/**
* Converts the dice number to a string representation.
*
* @param i The dice number.
* @return The string representation of the dice number.
*/
private String diceToString(int i) {
return "Pictures/dice/" + switch (i) {
case 1 -> "one";
case 2 -> "two";
case 3 -> "three";
case 4 -> "four";
case 5 -> "five";
case 6 -> "six";
default -> throw new IllegalArgumentException("Invalid dice number: " + i);
} + ".png";
}
/**
* Handles dice roll events and updates the dice display.
*
* @param event the dice roll event containing dice values
*/
@Override
public void receivedEvent(DiceRollEvent event) {
latestDiceRollEvent = event;
}
/**
* Updates the player view by refreshing the player information displayed on the toolbar.
*
* @param event the update player view event
*/
@Override
public void receivedEvent(UpdatePlayerView event) {
playerHandler = app.getGameLogic().getPlayerHandler();
refreshPlayerView();
}
/**
* Refreshes the player view.
*/
private void refreshPlayerView() {
accountContainer.clearChildren();
overviewContainer.clearChildren();
addAccountDetails();
addOverviewDetails();
accountContainer.setBackground(null);
overviewContainer.setBackground(null);
}
/**
* Adds the account details to the player view.
*/
private void addAccountDetails() {
Player currentPlayer = playerHandler.getPlayerById(app.getId());
accountContainer.addChild(new Label("Kontostand", new ElementId("label-toolbar")));
accountContainer.addChild(new Label(currentPlayer.getAccountBalance() + " EUR", new ElementId("label-account")));
accountContainer.addChild(new Label("Gulag Karten", new ElementId("label-toolbar")));
accountContainer.addChild(new Label(String.valueOf(currentPlayer.getNumJailCard()), new ElementId("label-account")));
}
/**
* Adds the overview details to the player view.
*/
private void addOverviewDetails() {
overviewContainer.addChild(new Label("Übersicht", new ElementId("label-toolbar")));
for (Player player : playerHandler.getPlayers()) {
if (player.getId() != app.getId()) {
Label playerLabel = new Label(
player.getName() + ": " + player.getAccountBalance() + " EUR",
new ElementId("label-player")
);
playerLabel.setColor(Player.getColor(player.getId()).getColor());
overviewContainer.addChild(playerLabel);
}
}
}
/**
* Updates the status of toolbar buttons based on the provided button status event.
* Disables or enables buttons such as trade, property menu, and end turn based on the player's turn status.
*
* @param event the button status event indicating whether the buttons should be enabled
*/
@Override
public void receivedEvent(ButtonStatusEvent event) {
boolean enabled = event.buttonsEnabled();
canRollDice = enabled;
tradeButton.setEnabled(enabled);
propertyMenuButton.setEnabled(enabled);
endTurnButton.setEnabled(false);
}
/**
* Closes the toolbar, detaching it from the GUI.
*/
@Override
public void close() {
public void remove() {
app.getGuiNode().detachChild(toolbarContainer);
super.close();
}
/**
* Opens the settings menu when the escape key is pressed.
*/
@Override
public void escape() {
new SettingsMenu(app).open();
}
/**
* Updates the toolbar by refreshing player information.
*/
@Override
public void update() {
refreshPlayerView();
super.update();
app.getGuiNode().detachChild(positionText);
}
}

View File

@@ -0,0 +1,168 @@
package pp.monopoly.client.gui;
import java.util.Random;
import com.jme3.font.BitmapText;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.simsilica.lemur.Axis;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.component.SpringGridLayout;
import pp.monopoly.client.MonopolyApp;
/**
* Toolbar Klasse, die am unteren Rand der Szene angezeigt wird.
* Die Buttons bewegen den Würfel auf dem Spielfeld.
*/
public class Toolbar2 {
private final MonopolyApp app;
private final Container toolbarContainer;
private final Geometry cube; // Referenz auf den Würfel
private final BitmapText positionText; // Anzeige für die aktuelle Position
private final float boardLimit = 0.95f; // Grenzen des Bretts
private final float stepSize = 0.18f; // Schrittgröße pro Bewegung
private int currentPosition = 0; // Aktuelle Position auf dem Spielfeld
private final int positionsPerSide = 10; // Anzahl der Positionen pro Seite
private final Random random = new Random(); // Zufallsgenerator für den Würfelwurf
/**
* Konstruktor für die Toolbar.
*
* @param app Die Hauptanwendung (MonopolyApp)
* @param cube Der Würfel, der bewegt werden soll
*/
public Toolbar2(MonopolyApp app, Geometry cube) {
this.app = app;
this.cube = cube;
// Erstelle die Toolbar
toolbarContainer = new Container(new SpringGridLayout(Axis.X, Axis.Y));
// Setze die Position am unteren Rand und die Breite
toolbarContainer.setLocalTranslation(
0, // Links bündig
100, // Höhe über dem unteren Rand
0 // Z-Ebene
);
toolbarContainer.setPreferredSize(new Vector3f(app.getCamera().getWidth(), 100, 0)); // Volle Breite
// Füge Buttons zur Toolbar hinzu
initializeButtons();
// Füge die Toolbar zur GUI hinzu
app.getGuiNode().attachChild(toolbarContainer);
// Erstelle die Position-Anzeige
positionText = createPositionDisplay();
updatePositionDisplay(); // Initialisiere die Anzeige mit der Startposition
}
/**
* Initialisiert die Buttons in der Toolbar.
*/
private void initializeButtons() {
addButton("Vorwärts", 1); // Bewegung nach vorne
addButton("Rückwärts", -1); // Bewegung nach hinten
addDiceRollButton(); // Würfel-Button
}
/**
* Fügt einen Button mit einer Bewegung hinzu.
*
* @param label Der Text des Buttons
* @param step Schrittweite (+1 für vorwärts, -1 für rückwärts)
*/
private void addButton(String label, int step) {
Button button = new Button(label);
button.setPreferredSize(new Vector3f(150, 50, 0)); // Größe der Buttons
button.addClickCommands(source -> moveCube(step));
toolbarContainer.addChild(button);
}
/**
* Fügt den Würfel-Button hinzu, der die Figur entsprechend der gewürfelten Zahl bewegt.
*/
private void addDiceRollButton() {
Button diceButton = new Button("Würfeln");
diceButton.setPreferredSize(new Vector3f(150, 50, 0)); // Größe des Buttons
diceButton.addClickCommands(source -> rollDice());
toolbarContainer.addChild(diceButton);
}
/**
* Simuliert einen Würfelwurf und bewegt die Figur entsprechend.
*/
private void rollDice() {
int diceRoll = random.nextInt(6) + 1; // Zahl zwischen 1 und 6
System.out.println("Gewürfelt: " + diceRoll);
moveCube(diceRoll); // Bewege die Figur um die gewürfelte Zahl
}
/**
* Bewegt den Würfel basierend auf der aktuellen Position auf dem Brett.
*
* @param step Schrittweite (+1 für vorwärts, -1 für rückwärts oder andere Werte)
*/
private void moveCube(int step) {
currentPosition = (currentPosition + step + 4 * positionsPerSide) % (4 * positionsPerSide);
Vector3f newPosition = calculatePosition(currentPosition);
cube.setLocalTranslation(newPosition);
updatePositionDisplay(); // Aktualisiere die Positionsanzeige
System.out.println("Würfelposition: " + newPosition + " (Feld-ID: " + currentPosition + ")");
}
/**
* Berechnet die neue Position des Würfels basierend auf der aktuellen Brettseite und Position.
*
* @param position Aktuelle Position auf dem Spielfeld
* @return Die berechnete Position als Vector3f
*/
private Vector3f calculatePosition(int position) {
int side = position / positionsPerSide; // Seite des Bretts (0 = unten, 1 = rechts, 2 = oben, 3 = links)
int offset = position % positionsPerSide; // Position auf der aktuellen Seite
switch (side) {
case 0: // Unten (positive x-Achse)
return new Vector3f(-boardLimit + offset * stepSize, 0.1f, -boardLimit + 0.05f);
case 1: // Rechts (positive z-Achse)
return new Vector3f(boardLimit - 0.05f, 0.1f, -boardLimit + offset * stepSize);
case 2: // Oben (negative x-Achse)
return new Vector3f(boardLimit - offset * stepSize, 0.1f, boardLimit - 0.05f);
case 3: // Links (negative z-Achse)
return new Vector3f(-boardLimit + 0.05f, 0.1f, boardLimit - offset * stepSize);
default:
throw new IllegalArgumentException("Ungültige Position: " + position);
}
}
/**
* Erstellt die Anzeige für die aktuelle Position.
*
* @return Das BitmapText-Objekt für die Anzeige
*/
private BitmapText createPositionDisplay() {
BitmapText text = new BitmapText(app.getAssetManager().loadFont("Interface/Fonts/Default.fnt"), false);
text.setSize(20); // Schriftgröße
text.setLocalTranslation(10, app.getCamera().getHeight() - 10, 0); // Oben links
app.getGuiNode().attachChild(text);
return text;
}
/**
* Aktualisiert die Anzeige für die aktuelle Position.
*/
private void updatePositionDisplay() {
positionText.setText("Feld-ID: " + currentPosition);
}
/**
* Entfernt die Toolbar.
*/
public void remove() {
app.getGuiNode().detachChild(toolbarContainer);
app.getGuiNode().detachChild(positionText);
}
}

View File

@@ -1,406 +0,0 @@
package pp.monopoly.client.gui;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Quad;
import com.jme3.texture.Texture;
import com.simsilica.lemur.*;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.component.SpringGridLayout;
import com.simsilica.lemur.core.VersionedList;
import com.simsilica.lemur.core.VersionedReference;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.message.client.TradeOffer;
import pp.monopoly.model.TradeHandler;
import pp.monopoly.model.fields.BuildingProperty;
import pp.monopoly.model.fields.PropertyField;
import pp.monopoly.notification.Sound;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* Represents the trade menu dialog in the Monopoly application.
* <p>
* Facilitates trade interactions between players, including selection of properties,
* currency, and special cards for offers and requests.
* </p>
*/
public class TradeMenu extends Dialog {
/** The Monopoly application instance. */
private final MonopolyApp app;
/** The trade handler managing trade logic. */
private final TradeHandler tradeHandler;
/** Main container for the trade menu UI. */
private final Container mainContainer;
/** Background geometry for the menu. */
private Geometry background;
private Selector<String> leftBuildingSelector, leftSpecialCardSelector;
private Selector<String> rightBuildingSelector, rightSpecialCardSelector;
private Label leftSelectionsLabel, rightSelectionsLabel;
private TextField leftCurrencyInput, rightCurrencyInput;
private VersionedReference<Set<Integer>> leftBuildingRef, rightBuildingRef;
private VersionedReference<Set<Integer>> leftCardRef, rightCardRef;
private Set<String> rightselBuildings = new HashSet<>();
private Set<String> leftselBuildings = new HashSet<>();
private static final ColorRGBA TRANSLUCENT_WHITE = new ColorRGBA(1, 1, 1, 0.5f);
/**
* Constructs the trade menu dialog.
*
* @param app the Monopoly application instance
* @param tradeHandler the handler managing trade interactions
*/
public TradeMenu(MonopolyApp app, TradeHandler tradeHandler) {
super(app.getDialogManager());
this.app = app;
this.tradeHandler = tradeHandler;
addBackgroundImage();
mainContainer = createMainContainer();
app.getGuiNode().attachChild(mainContainer);
positionMainContainer();
initializeReferences();
}
/** Creates the main container for the trade menu UI. */
private Container createMainContainer() {
Container container = new Container(new SpringGridLayout(Axis.Y, Axis.X));
container.setPreferredSize(new Vector3f(1200, 800, 0));
container.setBackground(new QuadBackgroundComponent(TRANSLUCENT_WHITE));
container.addChild(createHeader());
container.addChild(createMainContent());
return container;
}
/** Creates the header label for the trade menu. */
private Label createHeader() {
Label header = new Label("Handelsmenü", new ElementId("label-Bold"));
header.setFontSize(50);
header.setInsets(new Insets3f(10, 10, 10, 10));
header.setBackground(new QuadBackgroundComponent(TRANSLUCENT_WHITE));
return header;
}
/** Creates the main content section of the trade menu. */
private Container createMainContent() {
Container mainContent = new Container(new SpringGridLayout(Axis.X, Axis.Y));
mainContent.setPreferredSize(new Vector3f(1200, 700, 0));
mainContent.addChild(createTradeColumn("Wähle Handelsobjekt:", true));
mainContent.addChild(createMiddleSection());
mainContent.addChild(createTradeColumn("Wähle Zielobjekt:", false));
return mainContent;
}
/** Sets the trade data based on the current selections. */
private void setTrades() {
String leftCurreny = leftCurrencyInput.getText().equals("")? "0" : leftCurrencyInput.getText();
String rightCurreny = rightCurrencyInput.getText().equals("")? "0" : rightCurrencyInput.getText();
tradeHandler.setOfferedAmount(Integer.parseInt(leftCurreny));
tradeHandler.setRequestedAmount(Integer.parseInt(rightCurreny));
tradeHandler.setOfferedJailCards(Integer.parseInt(leftSpecialCardSelector.getSelectedItem()));
tradeHandler.setRequestedJailCards(Integer.parseInt(rightSpecialCardSelector.getSelectedItem()));
Set<PropertyField> offeredProperties = new HashSet<>();
for (String propertyString : leftselBuildings) {
offeredProperties.add( (PropertyField) app.getGameLogic().getBoardManager().getFieldByName(propertyString));
}
Set<PropertyField> requestedProperties = new HashSet<>();
for (String propertyString : rightselBuildings) {
requestedProperties.add( (PropertyField) app.getGameLogic().getBoardManager().getFieldByName(propertyString));
}
tradeHandler.setOfferedProperties(offeredProperties);
tradeHandler.setRequestedProperties(requestedProperties);
}
/**
* Creates a trade column for either the sender or receiver.
*
* @param label the label text for the column
* @param isLeft true if the column is for the sender; false otherwise
*/
private Container createTradeColumn(String label, boolean isLeft) {
Container column = new Container(new SpringGridLayout(Axis.Y, Axis.X));
column.setBackground(new QuadBackgroundComponent(ColorRGBA.White));
Label columnLabel = column.addChild(new Label(label));
columnLabel.setFontSize(24);
columnLabel.setBackground(new QuadBackgroundComponent(TRANSLUCENT_WHITE));
column.addChild(new Label("Gebäude:"));
Selector<String> buildingSelector = createPropertySelector(isLeft);
column.addChild(buildingSelector);
column.addChild(new Label("Währung:"));
TextField currencyInput = createCurrencyInput();
column.addChild(currencyInput);
column.addChild(new Label("Sonderkarten:"));
Selector<String> specialCardSelector = createSpecialCardSelector(isLeft);
styleSelector(specialCardSelector);
column.addChild(specialCardSelector);
assignSelectors(buildingSelector, specialCardSelector, currencyInput, isLeft);
return column;
}
/**
* Creates a property selector for buildings.
*
* @param isLeft true if the selector is for the sender; false otherwise
* @return the created property selector
*/
private Selector<String> createPropertySelector(boolean isLeft) {
VersionedList<String> properties = new VersionedList<>();
for (PropertyField field : getPropertyFields(isLeft)) {
properties.add(field.getName());
}
Selector<String> selector = new Selector<>(properties, "glass");
styleSelector(selector);
return selector;
}
/**
* Creates a selector for special cards.
*
* @param isLeft true if the selector is for the sender; false otherwise
* @return the created special card selector
*/
private Selector<String> createSpecialCardSelector(boolean isLeft) {
VersionedList<String> numbers = new VersionedList<>();
for (int i = 0; i <= app.getGameLogic().getPlayerHandler().getPlayerById(isLeft ? tradeHandler.getReceiver().getId() : tradeHandler.getSender().getId()).getNumJailCard(); i++) {
numbers.add(i + "");
}
Selector<String> selector = new Selector<>(numbers, "glass");
styleSelector(selector);
return selector;
}
/**
* Retrieves the property fields owned by the respective player.
*
* @param isLeft true if retrieving fields for the sender; false otherwise
* @return an iterable of property fields
*/
private Iterable<PropertyField> getPropertyFields(boolean isLeft) {
Set<PropertyField> building = app.getGameLogic()
.getBoardManager()
.getPropertyFields(app.getGameLogic()
.getPlayerHandler()
.getPlayerById(isLeft ? tradeHandler.getSender().getId() : tradeHandler.getReceiver().getId())
.getProperties())
.stream()
.filter(p -> p instanceof BuildingProperty)
.map(p -> (BuildingProperty) p)
.filter(p -> p.getHouses() == 0)
.collect(Collectors.toSet());
Set<PropertyField> rest = app.getGameLogic()
.getBoardManager()
.getPropertyFields(app.getGameLogic()
.getPlayerHandler()
.getPlayerById(isLeft ? tradeHandler.getSender().getId() : tradeHandler.getReceiver().getId())
.getProperties())
.stream()
.filter(p -> !(p instanceof BuildingProperty))
.collect(Collectors.toSet());
List<PropertyField> combinedProperties = new ArrayList<>();
combinedProperties.addAll(building);
combinedProperties.addAll(rest);
combinedProperties = combinedProperties.stream().sorted(Comparator.comparingInt(PropertyField::getId)).collect(Collectors.toList());
return combinedProperties;
}
/** Creates a text field for currency input. */
private TextField createCurrencyInput() {
TextField currencyInput = new TextField("0");
styleTextField(currencyInput);
return currencyInput;
}
/** Creates the middle section containing buttons and summary fields. */
private Container createMiddleSection() {
Container middleSection = new Container(new SpringGridLayout(Axis.Y, Axis.X));
middleSection.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8f, 0.8f, 0.8f, 1.0f)));
Label middleLabelTop = middleSection.addChild(new Label("Meine Gebäude:"));
middleLabelTop.setFontSize(24);
middleLabelTop.setTextVAlignment(VAlignment.Center);
middleLabelTop.setTextHAlignment(HAlignment.Center);
middleLabelTop.setInsets(new Insets3f(5, 5, 5, 5));
leftSelectionsLabel = middleSection.addChild(new Label(""));
leftSelectionsLabel.setPreferredSize(new Vector3f(600, 50, 0));
Container buttons = middleSection.addChild(new Container(new SpringGridLayout()));
Button cancel = new Button("Abbrechen");
cancel.addClickCommands(s -> ifTopDialog(() -> {
close();
app.getGameLogic().playSound(Sound.BUTTON);
}));
Button trade = new Button("Handeln");
trade.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
setTrades();
app.getGameLogic().send(new TradeOffer(tradeHandler));
close();
}));
buttons.addChild(cancel);
buttons.addChild(trade);
Label middleLabelBottom = middleSection.addChild(new Label("Gebäude des Gegenspielers:"));
middleLabelBottom.setFontSize(24);
middleLabelBottom.setTextVAlignment(VAlignment.Center);
middleLabelBottom.setTextHAlignment(HAlignment.Center);
middleLabelBottom.setInsets(new Insets3f(5, 5, 5, 5));
rightSelectionsLabel = middleSection.addChild(new Label(""));
rightSelectionsLabel.setPreferredSize(new Vector3f(600, 50, 0));
return middleSection;
}
/** Styles the given selector with insets and background color. */
private void styleSelector(Selector<String> selector) {
selector.setInsets(new Insets3f(5, 10, 5, 10));
selector.setBackground(new QuadBackgroundComponent(ColorRGBA.Black));
}
/** Styles the given text field with insets and background color. */
private void styleTextField(TextField textField) {
textField.setInsets(new Insets3f(5, 10, 5, 10));
textField.setBackground(new QuadBackgroundComponent(ColorRGBA.Black));
textField.setPreferredSize(new Vector3f(300, 30, 0));
}
/**
* Assigns selectors and input fields to either the left or right column.
*
* @param buildingSelector the building selector
* @param specialCardSelector the special card selector
* @param currencyInput the currency input field
* @param isLeft true if assigning to the left column; false otherwise
*/
private void assignSelectors(Selector<String> buildingSelector, Selector<String> specialCardSelector, TextField currencyInput, boolean isLeft) {
if (isLeft) {
leftBuildingSelector = buildingSelector;
leftSpecialCardSelector = specialCardSelector;
leftCurrencyInput = currencyInput;
} else {
rightBuildingSelector = buildingSelector;
rightSpecialCardSelector = specialCardSelector;
rightCurrencyInput = currencyInput;
}
}
/** Positions the main container at the center of the screen. */
private void positionMainContainer() {
mainContainer.setLocalTranslation(
(app.getCamera().getWidth() - mainContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + mainContainer.getPreferredSize().y) / 2,
7
);
}
/** Adds a background image to the trade menu. */
private void addBackgroundImage() {
Texture backgroundImage = app.getAssetManager().loadTexture("Pictures/unibw-Bib2.png");
Quad quad = new Quad(app.getCamera().getWidth(), app.getCamera().getHeight());
background = new Geometry("Background", quad);
Material backgroundMaterial = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
backgroundMaterial.setTexture("ColorMap", backgroundImage);
background.setMaterial(backgroundMaterial);
background.setLocalTranslation(0, 0, 6);
app.getGuiNode().attachChild(background);
}
/** Initializes references for tracking UI changes. */
private void initializeReferences() {
leftBuildingRef = leftBuildingSelector.getSelectionModel().createReference();
leftCardRef = leftSpecialCardSelector.getSelectionModel().createReference();
rightBuildingRef = rightBuildingSelector.getSelectionModel().createReference();
rightCardRef = rightSpecialCardSelector.getSelectionModel().createReference();
}
/**
* Updates the trade menu state, including selected properties and values.
*
* @param delta the time elapsed since the last update
*/
@Override
public void update(float delta) {
if (leftBuildingRef.update() || leftCardRef.update()) {
updateSelections(leftSelectionsLabel, leftBuildingSelector, true);
}
if (rightBuildingRef.update() || rightCardRef.update()) {
updateSelections(rightSelectionsLabel, rightBuildingSelector, false);
}
}
/**
* Updates the displayed selections for properties.
*
* @param target the target label to update
* @param building the building selector
* @param isLeft true if updating the left column; false otherwise
*/
private void updateSelections(Label target, Selector<String> building, boolean isLeft) {
StringBuilder buildingText = new StringBuilder();
if (isLeft) {
if (leftselBuildings.contains(building.getSelectedItem())) {
leftselBuildings.remove(building.getSelectedItem()); // Remove if already selected
} else {
leftselBuildings.add(building.getSelectedItem()); // Add if not already selected
}
for (String property : leftselBuildings) {
buildingText.append(property).append(", ");
}
} else {
if (rightselBuildings.contains(building.getSelectedItem())) {
rightselBuildings.remove(building.getSelectedItem()); // Remove if already selected
} else {
rightselBuildings.add(building.getSelectedItem()); // Add if not already selected
}
for (String property : rightselBuildings) {
buildingText.append(property).append(", ");
}
}
target.setText(buildingText.toString().replaceAll(", $", ""));
}
/** Opens the settings menu when the escape key is pressed. */
@Override
public void escape() {
new SettingsMenu(app).open();
}
/** Closes the trade menu and detaches UI elements. */
@Override
public void close() {
app.getGuiNode().detachChild(mainContainer);
app.getGuiNode().detachChild(background);
super.close();
}
}

View File

@@ -25,7 +25,7 @@ public class VolumeSlider extends Slider {
}
/**
* When triggered it updates the volume to the value set with the slider
* when triggered it updates the volume to the value set with the slider
*/
public void update() {
if (vol != getModel().getPercent()) {

View File

@@ -1,504 +0,0 @@
/*
* $Id$
*
* Copyright (c) 2014, Simsilica, LLC
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package pp.monopoly.client.gui.hslider;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.simsilica.lemur.Axis;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.FillMode;
import com.simsilica.lemur.GuiGlobals;
import com.simsilica.lemur.HAlignment;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.Panel;
import com.simsilica.lemur.TextField;
import com.simsilica.lemur.component.SpringGridLayout;
import com.simsilica.lemur.core.GuiControl;
import com.simsilica.lemur.core.VersionedReference;
import com.simsilica.lemur.grid.GridModel;
import com.simsilica.lemur.style.Attributes;
import com.simsilica.lemur.style.ElementId;
import com.simsilica.lemur.style.StyleDefaults;
import com.simsilica.lemur.style.Styles;
/**
*
* @author Paul Speed
*/
public class GridPanel extends Panel {
public static final String ELEMENT_ID = "grid";
private GridModel<Panel> model;
private VersionedReference<GridModel<Panel>> modelRef;
private SpringGridLayout layout;
private int visibleRows = 5;
private int visibleColumns = 5;
private int row = 0;
private int column = 0;
private Float alpha; // for setting to new children
private Float[] columnwidths = null;
private Float[] rowheight = null;
private boolean widthsupdate = false;
private HAlignment [] columnHalignement = null;
public GridPanel(GridModel<Panel> model ) {
this(true, model, new ElementId(ELEMENT_ID), null);
}
public GridPanel(GridModel<Panel> model, String style ) {
this(true, model, new ElementId(ELEMENT_ID), style);
}
public GridPanel(GridModel<Panel> model, ElementId elementId, String style ) {
this(true, model, elementId, style);
}
protected GridPanel(boolean applyStyles, GridModel<Panel> model,
ElementId elementId, String style ) {
super(false, elementId, style);
this.layout = new SpringGridLayout(Axis.Y, Axis.X,
FillMode.ForcedEven,
FillMode.ForcedEven);
getControl(GuiControl.class).setLayout(layout);
if( applyStyles ) {
Styles styles = GuiGlobals.getInstance().getStyles();
styles.applyStyles(this, elementId, style);
}
setModel(model);
}
// change the layout if necessary
public void setLayout(SpringGridLayout lay) {
this.layout = lay;
getControl(GuiControl.class).getLayout().clearChildren();
getControl(GuiControl.class).setLayout(layout);
this.modelRef = null;
if( this.model != null ) {
this.modelRef = model.createReference();
refreshGrid();
}
}
@StyleDefaults(ELEMENT_ID)
public static void initializeDefaultStyles( Attributes attrs ) {
}
public void setModel( GridModel<Panel> model ) {
if( this.model == model ) {
return;
}
if( this.model != null ) {
// Clear the old panel
getControl(GuiControl.class).getLayout().clearChildren();
this.modelRef = null;
}
this.model = model;
if( this.model != null ) {
this.modelRef = model.createReference();
refreshGrid();
}
}
public GridModel<Panel> getModel() {
return model;
}
public void setRow( int row ) {
setLocation(row, column);
}
public int getRow() {
return row;
}
public void setColumn( int column ) {
setLocation(row, column);
}
public int getColumn() {
return column;
}
public Panel getCell( int r, int c ) {
r = r - row;
c = c - column;
if( r < 0 || c < 0 || r >= visibleRows || c >= visibleColumns ) {
return null;
}
return (Panel)layout.getChild(r, c);
}
public void setLocation( int row, int column ) {
if( this.row == row && this.column == column ) {
return;
}
this.row = row;
this.column = column;
refreshGrid();
}
public void setVisibleSize( int rows, int columns ) {
this.visibleRows = rows;
this.visibleColumns = columns;
getControl(GuiControl.class).getLayout().clearChildren();
refreshGrid();
}
public void setVisibleRows( int rows ) {
setVisibleSize(rows, visibleColumns);
}
public int getVisibleRows() {
return visibleRows;
}
public void setVisibleColumns( int columns ) {
setVisibleSize(visibleRows, columns);
}
public int getVisibleColumns() {
return visibleColumns;
}
public void setAlpha( float alpha, boolean recursive ) {
this.alpha = alpha;
super.setAlpha(alpha, recursive);
}
protected void refreshGrid() {
widthsupdate = false;
if( model == null ) {
getControl(GuiControl.class).getLayout().clearChildren();
return;
}
for( int r = row; r < row + visibleRows; r++ ) {
for( int c = column; c < column + visibleColumns; c++ ) {
Node existing = layout.getChild(r-row, c-column);
if( r < 0 || r >= model.getRowCount() || c < 0 || c >= model.getColumnCount() ) {
// Out of bounds
layout.addChild(null, r-row, c-column);
} else {
Panel child = model.getCell(r, c, (Panel)existing);
// we check if there is a size for either rowheight or columnwidth stored
Float ytemp = null;
Float xtemp = null;
if (columnwidths !=null) {
if (columnwidths.length > c) {
if (columnwidths[c] != null) xtemp = columnwidths[c];
}
}
if (rowheight != null) {
if (rowheight.length > r) {
if (rowheight[r] !=null) ytemp = rowheight[r];
}
}
// and only if, we set the preferred size
if (ytemp !=null || xtemp != null) {
child.setPreferredSize(null);
if (xtemp != null) child.setPreferredSize(child.getPreferredSize().clone().setX(xtemp));
if (ytemp !=null) child.setPreferredSize(child.getPreferredSize().clone().setY(ytemp));
}
if (columnHalignement != null) {
if (columnHalignement.length > c) {
if (columnHalignement[c] != null) {
// we only set the alignement for "text" elements attached to the listbox
// for others e.g. progressbar etc. we should call the element and do the changes there
if (child instanceof Button) ((Button) child).setTextHAlignment(columnHalignement[c]);
if (child instanceof Label) ((Label) child).setTextHAlignment(columnHalignement[c]);
if (child instanceof TextField)
((TextField) child).setTextHAlignment(columnHalignement[c]);
} else if (child instanceof Button) ((Button) child).setTextHAlignment(HAlignment.Left);
} else if (child instanceof Button) ((Button) child).setTextHAlignment(HAlignment.Left);
} else if (child instanceof Button) ((Button) child).setTextHAlignment(HAlignment.Left);
if( child != existing ) {
// Make sure new children pick up the alpha of the container
if( alpha != null && alpha != 1 ) {
child.setAlpha(alpha);
}
layout.addChild(child, r-row, c-column);
}
}
}
}
}
@Override
public void updateLogicalState( float tpf ) {
super.updateLogicalState(tpf);
if( modelRef.update() ) {
refreshGrid();
}
if (widthsupdate) refreshGrid();
}
@Override
public String toString() {
return getClass().getName() + "[elementId=" + getElementId() + "]";
}
public Float[] getColumnwidths() {
return columnwidths;
}
public Float[] getRowheights() {
return rowheight;
}
public void setRowheight(Float rowheight, int rownumber_starting_with_0){
// adds or replaces a columnwidth
if (rownumber_starting_with_0 < 0) return;
int size = rownumber_starting_with_0+1;
if (this.rowheight != null) {
size = Math.max(size, this.rowheight.length);
}
preparegridsizes(size,false);
setcheckedsize(rowheight,rownumber_starting_with_0,true,true);
}
public void setColumnwidths(Float columnwidth, int columnnumber_starting_with_0) {
// adds or replaces a columnwidth
if (columnnumber_starting_with_0 <0) return;
int size = columnnumber_starting_with_0+1;
if (this.columnwidths != null) {
size = Math.max(size, this.columnwidths.length);
}
preparegridsizes(size,true);
setcheckedsize(columnwidth,columnnumber_starting_with_0,true,false);
}
public void setRowheight (Float[] rowheights_or_null) {
// replaces the given rowheights and only keep the number of rows given
setRowheight(rowheights_or_null,true);
}
public void setColumnwidths (Float[] columnwidths_or_null) {
// replaces the given columnwidths and only keep the number of columns given
setColumnwidths(columnwidths_or_null,true);
}
public void setRowheight(Float[] rowheights_or_null, boolean write_null_values) {
// replaces the given rowheights and only keep the number of rows given
// null values either overwrite or will be ignored
Integer tmp = null;
if (rowheights_or_null != null) tmp = rowheights_or_null.length;
if (preparegridsizes(tmp,false)) {
for (int i = 0; i <tmp;i++) {
setcheckedsize(rowheights_or_null[i],i,write_null_values,true);
}
}
}
public void setColumnwidths(Float[] columnwidths_or_null, boolean write_null_values) {
// replaces the given columnwidths_or_null and only keep the number of columns given
// null values either overwrite or will be ignored
Integer tmp = null;
if (columnwidths_or_null != null) tmp = columnwidths_or_null.length;
if (preparegridsizes(tmp,true)) {
for (int i = 0; i <tmp;i++) {
setcheckedsize(columnwidths_or_null[i],i,write_null_values,false);
}
}
}
private boolean preparegridsizes(Integer givenfieldsize, boolean width) {
// prepares and adjust the size of the field(s) that hold columnwidth or rowheights
if (givenfieldsize == null) {
if (width) { //either columns or rows will be set null
columnwidths =null;
} else {
rowheight = null;
}
for (Spatial p: this.getChildren()) {
Panel x = (Panel) p;
x.setPreferredSize(null); //we set all sizes to 0 as we will recalculate them with next update
}
widthsupdate = true;
return false; // no more activity needed
} else {
Float[] tmp;
tmp = new Float[givenfieldsize];
if (width) {
if (columnwidths == null) {
columnwidths = tmp;
return true;
}
int i = 0;
for (Float z:columnwidths) {
tmp[i] =z;
i++;
if (i>= givenfieldsize) break;
}
columnwidths = tmp; // we get what we have
} else {
if (rowheight == null) {
rowheight = tmp;
return true;
}
int i = 0;
for (Float z:rowheight) {
tmp[i] =z;
i++;
if (i>= givenfieldsize) break;
}
rowheight = tmp; // we get what we have
}
return true;
}
}
private void setcheckedsize(Float size, int row_or_column, boolean override, boolean i_am_a_row) {
if (override || (size !=null)) {
if (i_am_a_row) {
rowheight[row_or_column] = size;
} else {
columnwidths[row_or_column] = size;
}
widthsupdate = true;
}
}
// public void setRowheight(Float rowheight_or_null){
// if (rowheight_or_null<=0) return;
// this.rowheight = rowheight_or_null;
// widthsupdate = true;
// }
public void setHalignements(HAlignment[] hals) {
setHalignements(hals,false);
}
public void setHalignements(HAlignment[] hals, boolean overridestandard) {
if (checkexistinghal(hals)) {
int i =0;
for (HAlignment z:hals) {
setHalignementchecked(z,i,overridestandard);
i++;
if (i>=columnHalignement.length) return; // we ignore given HAlignement that is out of column bound
}
if (!overridestandard ) return;
for (int u = i; u<columnHalignement.length;u++) {
setHalignementchecked(null,u,overridestandard); // override existing HAlignements
}
}
}
public void setHalignements(HAlignment hal, int column) {
checkexistinghal(new HAlignment[]{HAlignment.Center});
if (column < columnHalignement.length) setHalignementchecked(hal,column,true);
}
private void setHalignementchecked(HAlignment hal, int column,boolean override) {
if (override || (hal !=null)) {
columnHalignement[column] = hal;
widthsupdate = true;
}
}
private boolean checkexistinghal(HAlignment[] givenfield) {
// delete the given Halignements
if (givenfield == null) {
columnHalignement =null;
for (Spatial p: this.getChildren()) {
Button x = (Button)((Panel) p);
x.setTextHAlignment(HAlignment.Left); //standard HAlignement
}
widthsupdate = true;
return false;
}
// or prepare if we have no columnHalignement yet
HAlignment[] tmp;
if (columnHalignement == null) {
tmp = new HAlignment[model.getColumnCount()];
columnHalignement = tmp;
} else {
if (!(columnHalignement.length ==model.getColumnCount() )) {
tmp = new HAlignment[model.getColumnCount()];
int i = 0;
for (HAlignment z:columnHalignement) {
tmp[i] =z;
i++;
if (i>=model.getColumnCount()) break;
}
columnHalignement = tmp;
}
}
return true;
}
public HAlignment[] getColumnHalignement() {
return columnHalignement;
}
}

View File

@@ -1,135 +0,0 @@
/*
* $Id$
*
* Copyright (c) 2014, Simsilica, LLC
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package pp.monopoly.client.gui.hslider;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.List;
import com.simsilica.lemur.core.VersionedObject;
import com.simsilica.lemur.core.VersionedReference;
/**
*
* @author Paul Speed
*/
public class VersionedList<T> extends AbstractList<T>
implements VersionedObject<List<T>> {
private long version = 0;
private List<T> list;
protected VersionedList(List<T> items, boolean copy ) {
if( copy ) {
list = new ArrayList<T>();
list.addAll(items);
} else {
this.list = items;
}
}
public VersionedList() {
this(new ArrayList<T>(), false);
}
public VersionedList(List<T> items ) {
this(items, true);
}
/**
* Wraps a list in a VersionedList instead of copying it.
* This is useful for cases where a VersionedList is required
* but strict versioning is not, for example, passing a static list
* to a ListBox. Changes to the wrapped list obviously don't
* trigger version changes in the wrapper. Only changes through
* the wrapper will increment the version.
*/
public static <T> VersionedList<T> wrap( List<T> list ) {
return new VersionedList<T>(list, false);
}
public void incrementVersion() { // changed this to public
version++;
}
@Override
public long getVersion() {
return version;
}
@Override
public List<T> getObject() {
return this;
}
@Override
public VersionedReference<List<T>> createReference() {
return new VersionedReference<List<T>>(this);
}
@Override
public T get( int i ) {
return list.get(i);
}
@Override
public int size() {
return list.size();
}
@Override
public T set( int i, T val ) {
T result = list.set(i, val);
incrementVersion();
return result;
}
@Override
public void add( int i, T val ) {
list.add(i, val);
incrementVersion();
}
@Override
public T remove( int i ) {
T result = list.remove(i);
incrementVersion();
return result;
}
}

View File

@@ -1,161 +0,0 @@
package pp.monopoly.client.gui.popups;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Quad;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.dialog.PopupDialog;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.client.gui.SettingsMenu;
import pp.monopoly.message.server.TradeReply;
import pp.monopoly.notification.Sound;
/**
* Represents a confirmation dialog that appears when a trade is accepted.
* Displays a message to the user informing them that the trade was accepted.
*/
public class AcceptTrade extends Dialog implements PopupDialog {
/** Reference to the Monopoly application instance. */
private final MonopolyApp app;
/** Semi-transparent overlay background for the dialog. */
private Geometry overlayBackground;
/** Container for the warning message content. */
private Container noMoneyWarningContainer;
/** Background container providing a border for the dialog. */
private Container backgroundContainer;
/**
* Constructs the AcceptTrade dialog.
*
* @param app the Monopoly application instance
* @param msg the trade reply message containing details about the trade
*/
public AcceptTrade(MonopolyApp app, TradeReply msg) {
super(app.getDialogManager());
this.app = app;
// Initialize GUI elements
createOverlayBackground();
createBackgroundContainer();
createWarningContainer(msg);
}
/**
* Creates a semi-transparent background overlay for the dialog.
*/
private void createOverlayBackground() {
Quad quad = new Quad(app.getCamera().getWidth(), app.getCamera().getHeight());
overlayBackground = new Geometry("Overlay", quad);
Material material = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
material.setColor("Color", new ColorRGBA(0, 0, 0, 0.5f)); // Semi-transparent
material.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
overlayBackground.setMaterial(material);
overlayBackground.setLocalTranslation(0, 0, 0);
}
/**
* Creates the background container for the dialog.
*/
private void createBackgroundContainer() {
backgroundContainer = new Container();
backgroundContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f))); // Light gray background
}
/**
* Creates the main warning container for the dialog.
*
* @param msg the trade reply message
*/
private void createWarningContainer(TradeReply msg) {
noMoneyWarningContainer = new Container();
noMoneyWarningContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f)));
noMoneyWarningContainer.setPreferredSize(new Vector3f(550, 250, 10));
float padding = 10;
backgroundContainer.setPreferredSize(noMoneyWarningContainer.getPreferredSize().addLocal(padding, padding, 0));
// Title
Label title = noMoneyWarningContainer.addChild(new Label("Handel angenommen!", new ElementId("warning-title")));
title.setFontSize(48);
title.setColor(ColorRGBA.Black);
// Message
Container textContainer = noMoneyWarningContainer.addChild(new Container());
textContainer.addChild(new Label("Du hast " + msg.getTradeHandler().getReceiver().getName() + " einen Handel vorgeschlagen.", new ElementId("label-Text")));
textContainer.addChild(new Label("", new ElementId("label-Text")));
textContainer.addChild(new Label("Der Handel wurde angenommen.", new ElementId("label-Text")));
textContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
textContainer.setPreferredSize(noMoneyWarningContainer.getPreferredSize().addLocal(-250, -200, 0));
// Confirmation button
Button confirmButton = noMoneyWarningContainer.addChild(new Button("Bestätigen", new ElementId("button")));
confirmButton.setFontSize(32);
confirmButton.addClickCommands(source -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
close();
}));
}
/**
* Centers the warning and background containers on the screen.
*/
private void centerContainers() {
float padding = 10;
// Center main container
noMoneyWarningContainer.setLocalTranslation(
(app.getCamera().getWidth() - noMoneyWarningContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + noMoneyWarningContainer.getPreferredSize().y) / 2,
8
);
// Center background container with padding
backgroundContainer.setPreferredSize(noMoneyWarningContainer.getPreferredSize().addLocal(padding, padding, 0));
backgroundContainer.setLocalTranslation(
(app.getCamera().getWidth() - backgroundContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + backgroundContainer.getPreferredSize().y) / 2,
7
);
}
/**
* Displays the dialog by attaching it to the GUI through the DialogManager.
*/
@Override
public void show() {
app.getGuiNode().attachChild(overlayBackground);
app.getGuiNode().attachChild(backgroundContainer);
app.getGuiNode().attachChild(noMoneyWarningContainer);
centerContainers();
}
/**
* Closes the dialog and removes the associated GUI elements.
*/
@Override
public void close() {
app.getGuiNode().detachChild(overlayBackground);
app.getGuiNode().detachChild(backgroundContainer);
app.getGuiNode().detachChild(noMoneyWarningContainer);
super.close();
}
/**
* Handles the escape key action by closing the dialog.
*/
@Override
public void escape() {
new SettingsMenu(app).open();
}
}

View File

@@ -1,149 +0,0 @@
package pp.monopoly.client.gui.popups;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Quad;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.dialog.PopupDialog;
import pp.monopoly.client.MonopolyApp;
/**
* Bankrupt is a Warning-Popup which appears when the balance is negative at the end of a player´s turn.
*/
public class Bankrupt extends Dialog implements PopupDialog {
/** Reference to the Monopoly application instance. */
private final MonopolyApp app;
/** Semi-transparent overlay background for the popup. */
private Geometry overlayBackground;
/** Main container for the bankruptcy warning content. */
private Container bankruptContainer;
/** Background container providing a border for the popup. */
private Container backgroundContainer;
/**
* Constructs the bankruptcy warning popup.
*
* @param app the Monopoly application instance
*/
public Bankrupt(MonopolyApp app) {
super(app.getDialogManager());
this.app = app;
// Initialize the components
createOverlayBackground();
createBackgroundContainer();
createBankruptContainer();
}
/**
* Creates a semi-transparent background overlay for the popup.
*/
private void createOverlayBackground() {
Quad quad = new Quad(app.getCamera().getWidth(), app.getCamera().getHeight());
overlayBackground = new Geometry("Overlay", quad);
Material material = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
material.setColor("Color", new ColorRGBA(0, 0, 0, 0.5f)); // Semi-transparent
material.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
overlayBackground.setMaterial(material);
overlayBackground.setLocalTranslation(0, 0, 0);
}
/**
* Creates the background container for the popup.
*/
private void createBackgroundContainer() {
backgroundContainer = new Container();
backgroundContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f))); // Light gray background
}
/**
* Creates the main container for the bankruptcy warning content.
*/
private void createBankruptContainer() {
bankruptContainer = new Container();
bankruptContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f)));
bankruptContainer.setPreferredSize(new Vector3f(550, 350, 10));
// Title
Label title = bankruptContainer.addChild(new Label("Vorsicht!", new ElementId("warning-title")));
title.setFontSize(48);
title.setColor(ColorRGBA.Black);
// Text content
Container textContainer = bankruptContainer.addChild(new Container());
textContainer.addChild(new Label(
"Du hast einen negativen Kontostand. Wenn du jetzt deinen Zug beendest, gehst du bankrott und verlierst das Spiel!\n"
+ "Dieses Pop-Up wird nicht erneut angezeigt!",
new ElementId("label-Text")));
textContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
textContainer.setPreferredSize(bankruptContainer.getPreferredSize().addLocal(-250, -200, 0));
// Confirmation button
Button confirmButton = bankruptContainer.addChild(new Button("Bestätigen", new ElementId("button")));
confirmButton.setFontSize(32);
confirmButton.addClickCommands(source -> ifTopDialog(this::close));
}
/**
* Centers the popup containers on the screen.
*/
private void centerContainers() {
float padding = 10;
// Center bankrupt container
bankruptContainer.setLocalTranslation(
(app.getCamera().getWidth() - bankruptContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + bankruptContainer.getPreferredSize().y) / 2,
8
);
// Center background container with padding
backgroundContainer.setPreferredSize(bankruptContainer.getPreferredSize().addLocal(padding, padding, 0));
backgroundContainer.setLocalTranslation(
(app.getCamera().getWidth() - backgroundContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + backgroundContainer.getPreferredSize().y) / 2,
7
);
}
/**
* Displays the popup by attaching it to the GUI.
*/
@Override
public void show() {
app.getGuiNode().attachChild(overlayBackground);
app.getGuiNode().attachChild(backgroundContainer);
app.getGuiNode().attachChild(bankruptContainer);
centerContainers();
}
/**
* Closes the popup and removes the associated GUI elements.
*/
@Override
public void close() {
app.getGuiNode().detachChild(overlayBackground);
app.getGuiNode().detachChild(backgroundContainer);
app.getGuiNode().detachChild(bankruptContainer);
super.close();
}
/**
* Handles the escape key action by closing the popup.
*/
@Override
public void escape() {
close();
}
}

View File

@@ -1,165 +1,133 @@
package pp.monopoly.client.gui.popups;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.simsilica.lemur.Button;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Quad;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.dialog.PopupDialog;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.client.gui.SettingsMenu;
import pp.monopoly.message.client.BuyPropertyResponse;
import pp.monopoly.model.fields.BoardManager;
import pp.monopoly.model.fields.BuildingProperty;
import pp.monopoly.notification.Sound;
/**
* BuildingPropertyCard creates a popup for displaying field information.
* TODO Kommentare fixen
* SettingsMenu ist ein Overlay-Menü, das durch ESC aufgerufen werden kann.
*/
public class BuildingPropertyCard extends Dialog implements PopupDialog {
public class BuildingPropertyCard extends Dialog {
private final MonopolyApp app;
private final Geometry overlayBackground;
private final Container buildingPropertyContainer;
private final Container backgroundContainer;
private int index = 37;
/**
* Constructs a property card popup displaying details about the building property.
*
* @param app the Monopoly application instance
*/
public BuildingPropertyCard(MonopolyApp app) {
super(app.getDialogManager());
this.app = app;
int index = app.getGameLogic().getPlayerHandler().getPlayerById(app.getId()).getFieldID();
BuildingProperty field = (BuildingProperty) new BoardManager().getFieldAtIndex(index);
//Generate the corresponfing field
BuildingProperty field = (BuildingProperty) app.getGameLogic().getBoardManager().getFieldAtIndex(index);
// Create the main container for the popup
buildingPropertyContainer = new Container();
buildingPropertyContainer.setBackground(new QuadBackgroundComponent(field.getColor().getColor()));
addContentToContainer(buildingPropertyContainer, field);
buildingPropertyContainer.setPreferredSize(new Vector3f(360,460,1));
System.out.println(buildingPropertyContainer.getPreferredSize());
// Halbtransparentes Overlay hinzufügen
overlayBackground = createOverlayBackground();
app.getGuiNode().attachChild(overlayBackground);
// Create the background container
backgroundContainer = new Container();
backgroundContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f))); // Light gray
backgroundContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f))); // Darker background
app.getGuiNode().attachChild(backgroundContainer);
// Add padding to the background
float padding = 10f;
// Hauptcontainer für die Gebäudekarte
buildingPropertyContainer = new Container();
buildingPropertyContainer.setBackground(new QuadBackgroundComponent(field.getColor().getColor()));
Label settingsTitle = buildingPropertyContainer.addChild(new Label( field.getName(), new ElementId("settings-title")));
settingsTitle.setFontSize(48);
// Text, der auf der Karte steht
// Die Preise werden dynamisch dem BoardManager entnommen
Container propertyValuesContainer = buildingPropertyContainer.addChild(new Container());
propertyValuesContainer.addChild(new Label("„Grundstückswert: " + field.getPrice() + " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("", new ElementId("label-Text")));// Leerzeile
propertyValuesContainer.addChild(new Label("„Miete allein: " + field.getAllRent().get(0)+ " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("„-mit 1 Haus: " + field.getAllRent().get(1) + " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("„-mit 2 Häuser: " + field.getAllRent().get(2) + " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("„-mit 3 Häuser: " + field.getAllRent().get(3) + " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("„-mit 4 Häuser: " + field.getAllRent().get(4) + " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("„-mit 1 Hotel: " + field.getAllRent().get(5) + " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("„-1 Haus kostet: " + field.getHousePrice()+ " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("", new ElementId("label-Text")));// Leerzeile
propertyValuesContainer.addChild(new Label("„Hypothek: " + field.getHypo() + " EUR", new ElementId("label-Text")));
propertyValuesContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
//TODO eventuell diese Stelle löschen, da nur die BuyCard Kaufen und beenden hat
/*
// Beenden-Button
Button quitButton = foodFieldContainer.addChild(new Button("Beenden", new ElementId("button")));
quitButton.setFontSize(32);
// Kaufen-Button
Button buyButton = foodFieldContainer.addChild(new Button("Kaufen", new ElementId("button")));
buyButton.setFontSize(32);
*/
float padding = 10; // Padding around the settingsContainer for the background
backgroundContainer.setPreferredSize(buildingPropertyContainer.getPreferredSize().addLocal(padding, padding, 0));
System.out.println(backgroundContainer.getPreferredSize());
// Position the containers
centerContainers(padding);
}
/**
* Adds the property details and buttons to the container.
*
* @param container the main container for the property card
* @param field the building property to display
*/
private void addContentToContainer(Container container, BuildingProperty field) {
// Title
Label title = container.addChild(new Label(field.getName(), new ElementId("label-Bold")));
title.setBackground(new QuadBackgroundComponent(field.getColor().getColor()));
title.setFontSize(38);
// Property details
Container propertyValuesContainer = container.addChild(new Container());
propertyValuesContainer.addChild(new Label("Grundstückswert: " + field.getPrice() + " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("Miete allein: " + field.getAllRent().get(0) + " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("- mit 1 Haus: " + field.getAllRent().get(1) + " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("- mit 2 Häusern: " + field.getAllRent().get(2) + " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("- mit 3 Häusern: " + field.getAllRent().get(3) + " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("- mit 4 Häusern: " + field.getAllRent().get(4) + " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("- mit 1 Hotel: " + field.getAllRent().get(5) + " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("1 Haus kostet: " + field.getHousePrice() + " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("Hypothek: " + field.getHypo() + " EUR", new ElementId("label-Text")));
propertyValuesContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
// Add buttons
addButtons(container);
}
/**
* Adds the buttons for closing or buying the property.
*
* @param container the main container
*/
private void addButtons(Container container) {
// Quit button
Button quitButton = container.addChild(new Button("Beenden", new ElementId("button")));
quitButton.setFontSize(32);
quitButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
close();
}));
// Buy button
Button buyButton = container.addChild(new Button("Kaufen", new ElementId("button")));
buyButton.setFontSize(32);
buyButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
close();
app.getGameLogic().send(new BuyPropertyResponse());
}));
}
/**
* Centers the containers on the screen.
*
* @param padding the padding size
*/
private void centerContainers(float padding) {
// Center main container
// Zentriere das Menü
buildingPropertyContainer.setLocalTranslation(
(app.getCamera().getWidth() - buildingPropertyContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + buildingPropertyContainer.getPreferredSize().y) / 2,
8
);
// Center background container with padding
backgroundContainer.setLocalTranslation(
(app.getCamera().getWidth() - buildingPropertyContainer.getPreferredSize().x - padding) / 2,
(app.getCamera().getHeight() + buildingPropertyContainer.getPreferredSize().y + padding) / 2,
7
(app.getCamera().getWidth() - buildingPropertyContainer.getPreferredSize().x - padding) / 2,
(app.getCamera().getHeight() + buildingPropertyContainer.getPreferredSize().y+ padding) / 2,
7
);
}
/**
* Attaches the popup to the GUI through the DialogManager.
*/
@Override
public void show() {
app.getGuiNode().attachChild(backgroundContainer);
app.getGuiNode().attachChild(buildingPropertyContainer);
}
/**
* Closes the popup and removes associated GUI elements.
* Erstellt einen halbtransparenten Hintergrund für das Menü.
*
* @return Geometrie des Overlays
*/
@Override
public void close() {
app.getGuiNode().detachChild(buildingPropertyContainer);
app.getGuiNode().detachChild(backgroundContainer);
super.close();
private Geometry createOverlayBackground() {
Quad quad = new Quad(app.getCamera().getWidth(), app.getCamera().getHeight());
Geometry overlay = new Geometry("Overlay", quad);
Material material = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
material.setColor("Color", new ColorRGBA(0, 0, 0, 0.5f)); // Halbtransparent
material.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
overlay.setMaterial(material);
overlay.setLocalTranslation(0, 0, 0);
return overlay;
}
/**
* Opens the settings menu when the escape key is pressed.
* Schließt das Menü und entfernt die GUI-Elemente.
*/
@Override
public void escape() {
new SettingsMenu(app).open();
public void close() {
System.out.println("Schließe SettingsMenu..."); // Debugging-Ausgabe
app.getGuiNode().detachChild(buildingPropertyContainer); // Entferne das Menü
app.getGuiNode().detachChild(backgroundContainer); //Entfernt Rand
app.getGuiNode().detachChild(overlayBackground); // Entferne das Overlay
app.setSettingsMenuOpen(false); // Menü als geschlossen markieren TODO passt diese Variable noch (zu finden unter den Temps in MonopolyApp
app.unblockInputs(); // Eingaben wieder aktivieren
System.out.println("SettingsMenu geschlossen."); // Debugging-Ausgabe
}
public void setIndex(int index) {
this.index = index;
}
}

View File

@@ -0,0 +1,124 @@
package pp.monopoly.client.gui.popups;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Quad;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.model.fields.BuildingProperty;
/**
* SettingsMenu ist ein Overlay-Menü, das durch ESC aufgerufen werden kann.
*/
public class BuyCard extends Dialog {
private final MonopolyApp app;
private final Geometry overlayBackground;
private final Container buyCardContainer;
private final Container backgroundContainer;
private int index = 37;
public BuyCard(MonopolyApp app) {
super(app.getDialogManager());
this.app = app;
//Generate the corresponfing field
BuildingProperty field = (BuildingProperty) app.getBoardManager().getFieldAtIndex(index);
// Halbtransparentes Overlay hinzufügen
overlayBackground = createOverlayBackground();
app.getGuiNode().attachChild(overlayBackground);
// Create the background container
backgroundContainer = new Container();
backgroundContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f))); // Darker background
app.getGuiNode().attachChild(backgroundContainer);
// Hauptcontainer für die Gebäudekarte
buyCardContainer = new Container();
buyCardContainer.setBackground(new QuadBackgroundComponent(field.getColor().getColor()));
Label settingsTitle = buyCardContainer.addChild(new Label( field.getName(), new ElementId("settings-title")));
settingsTitle.setFontSize(48);
// Text, der auf der Karte steht
// Die Preise werden dynamisch dem BoardManager entnommen
Container propertyValuesContainer = buyCardContainer.addChild(new Container());
propertyValuesContainer.addChild(new Label("„Grundstückswert: " + field.getPrice() + " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("", new ElementId("label-Text")));// Leerzeile
propertyValuesContainer.addChild(new Label("„Miete allein: " + field.getAllRent().get(0)+ " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("„-mit 1 Haus: " + field.getAllRent().get(1) + " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("„-mit 2 Häuser: " + field.getAllRent().get(2) + " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("„-mit 3 Häuser: " + field.getAllRent().get(3) + " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("„-mit 4 Häuser: " + field.getAllRent().get(4) + " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("„-mit 1 Hotel: " + field.getAllRent().get(5) + " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("„-1 Haus kostet: " + field.getHousePrice()+ " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("", new ElementId("label-Text")));// Leerzeile
propertyValuesContainer.addChild(new Label("„Hypothek: " + field.getHypo() + " EUR", new ElementId("label-Text")));
propertyValuesContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
// Beenden-Button
Button quitButton = buyCardContainer.addChild(new Button("Beenden", new ElementId("button")));
quitButton.setFontSize(32);
// Kaufen-Button
Button buyButton = buyCardContainer.addChild(new Button("Kaufen", new ElementId("button")));
buyButton.setFontSize(32);
float padding = 10; // Padding around the settingsContainer for the background
backgroundContainer.setPreferredSize(buyCardContainer.getPreferredSize().addLocal(padding, padding, 0));
// Zentriere das Menü
buyCardContainer.setLocalTranslation(
(app.getCamera().getWidth() - buyCardContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + buyCardContainer.getPreferredSize().y) / 2,
8
);
backgroundContainer.setLocalTranslation(
(app.getCamera().getWidth() - buyCardContainer.getPreferredSize().x - padding) / 2,
(app.getCamera().getHeight() + buyCardContainer.getPreferredSize().y+ padding) / 2,
7
);
app.getGuiNode().attachChild(buyCardContainer);
}
/**
* Erstellt einen halbtransparenten Hintergrund für das Menü.
*
* @return Geometrie des Overlays
*/
private Geometry createOverlayBackground() {
Quad quad = new Quad(app.getCamera().getWidth(), app.getCamera().getHeight());
Geometry overlay = new Geometry("Overlay", quad);
Material material = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
material.setColor("Color", new ColorRGBA(0, 0, 0, 0.5f)); // Halbtransparent
material.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
overlay.setMaterial(material);
overlay.setLocalTranslation(0, 0, 0);
return overlay;
}
/**
* Schließt das Menü und entfernt die GUI-Elemente.
*/
@Override
public void close() {
System.out.println("Schließe SettingsMenu..."); // Debugging-Ausgabe
app.getGuiNode().detachChild(buyCardContainer); // Entferne das Menü
app.getGuiNode().detachChild(backgroundContainer); //Entfernt Rand
app.getGuiNode().detachChild(overlayBackground); // Entferne das Overlay
app.setSettingsMenuOpen(false); // Menü als geschlossen markieren TODO passt diese Variable noch (zu finden unter den Temps in MonopolyApp
app.unblockInputs(); // Eingaben wieder aktivieren
System.out.println("SettingsMenu geschlossen."); // Debugging-Ausgabe
}
}

View File

@@ -1,247 +0,0 @@
package pp.monopoly.client.gui.popups;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.simsilica.lemur.Axis;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.Selector;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.component.SpringGridLayout;
import com.simsilica.lemur.core.VersionedList;
import com.simsilica.lemur.core.VersionedReference;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.client.gui.SettingsMenu;
import pp.monopoly.game.server.Player;
import pp.monopoly.message.client.AlterProperty;
import pp.monopoly.model.fields.BoardManager;
import pp.monopoly.model.fields.BuildingProperty;
import pp.monopoly.notification.Sound;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* BuyHouse is a popup which appears when a player clicks on the "Buy House"-button in the BuildingAdminMenu
*/
public class BuyHouse extends Dialog {
/** Reference to the Monopoly application instance. */
private final MonopolyApp app;
/** Main container for the "Buy House" popup UI. */
private final Container buyHouseContainer;
/** Background container providing a border for the popup. */
private final Container backgroundContainer;
/** Label to display selected properties. */
private Label selectionDisplay;
/** Reference for tracking dropdown selection changes. */
private VersionedReference<Set<Integer>> selectionRef;
/** Dropdown selector for choosing properties to build houses on. */
private Selector<String> propertySelector;
/** Set of selected properties for house purchase. */
private Set<String> selectedProperties = new HashSet<>();
/** Label displaying the total cost of building houses on the selected properties. */
private Label cost = new Label("0", new ElementId("label-Text"));
/**
* Constructs the "Buy House" popup.
*
* @param app the Monopoly application instance
*/
public BuyHouse(MonopolyApp app) {
super(app.getDialogManager());
this.app = app;
// Create the background container
backgroundContainer = new Container();
backgroundContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f))); // Darker background
attachChild(backgroundContainer);
// Main container for the menu
buyHouseContainer = new Container();
buyHouseContainer.setPreferredSize(new Vector3f(800, 600, 0));
float padding = 10; // Adjust backgroundContainer size to match buyHouseContainer
backgroundContainer.setPreferredSize(buyHouseContainer.getPreferredSize().addLocal(padding, padding, 0));
// Title
Label title = buyHouseContainer.addChild(new Label("Gebäude Kaufen", new ElementId("label-Bold")));
title.setFontSize(48);
title.setColor(ColorRGBA.Black);
// Divide buyHouseContainer into three sub-containers
Container upContainer = buyHouseContainer.addChild(new Container());
Container middleContainer = buyHouseContainer.addChild(new Container());
Container downContainer = buyHouseContainer.addChild(new Container());
// Upper section text
upContainer.addChild(new Label("„Grundstück wählen:", new ElementId("label-Text")));
upContainer.addChild(new Label("", new ElementId("label-Text"))); // Empty line
upContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
middleContainer.setPreferredSize(new Vector3f(100, 150, 0));
middleContainer.setBackground(new QuadBackgroundComponent(ColorRGBA.Orange));
// Add the property selector dropdown
middleContainer.addChild(createPropertyDropdown());
downContainer.addChild(new Label("", new ElementId("label-Text"))); // Empty line
downContainer.addChild(new Label("Kosten:", new ElementId("label-Text"))); // Label for cost
downContainer.addChild(cost); // Cost details
downContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
// Cancel button
Button cancelButton = buyHouseContainer.addChild(new Button("Abbrechen", new ElementId("button")));
cancelButton.setFontSize(32);
cancelButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
close();
}));
// Confirm button
Button confirmButton = buyHouseContainer.addChild(new Button("Bestätigen", new ElementId("button")));
confirmButton.setFontSize(32);
confirmButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
AlterProperty msg = new AlterProperty("BuyHouse");
msg.setProperties(selectedProperties.stream().map(p -> app.getGameLogic().getBoardManager().getFieldByName(p).getId()).map(p -> (Integer) p).collect(Collectors.toSet()));
app.getGameLogic().send(msg);
close();
}));
// Center the popup
buyHouseContainer.setLocalTranslation(
(app.getCamera().getWidth() - buyHouseContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + buyHouseContainer.getPreferredSize().y) / 2,
9
);
backgroundContainer.setLocalTranslation(
(app.getCamera().getWidth() - buyHouseContainer.getPreferredSize().x - padding) / 2,
(app.getCamera().getHeight() + buyHouseContainer.getPreferredSize().y + padding) / 2,
8
);
app.getGuiNode().attachChild(buyHouseContainer);
}
/**
* Creates a dropdown menu for selecting properties eligible for house construction.
*
* @return The container holding the dropdown menu.
*/
private Container createPropertyDropdown() {
Container dropdownContainer = new Container(new SpringGridLayout(Axis.Y, Axis.X));
dropdownContainer.setPreferredSize(new Vector3f(300, 200, 0));
dropdownContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.0f, 0.0f, 0.0f, 1.0f)));
VersionedList<String> propertyOptions = new VersionedList<>();
List<BuildingProperty> playerProperties = getPlayerProperties();
// Populate the dropdown with property names
for (BuildingProperty property : playerProperties) {
propertyOptions.add(property.getName());
}
propertySelector = new Selector<>(propertyOptions, "glass");
dropdownContainer.addChild(propertySelector);
// Track selection changes
selectionRef = propertySelector.getSelectionModel().createReference();
// Initialize the selection display here
selectionDisplay = new Label("");
selectionDisplay.setPreferredSize(new Vector3f(300, 30, 0));
selectionDisplay.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
dropdownContainer.addChild(selectionDisplay); // Add it to the dropdown container
// Set initial selection
if (!propertyOptions.isEmpty()) {
onDropdownSelectionChanged(propertySelector);
}
return dropdownContainer;
}
/**
* Retrieves the list of properties owned by the current player that are eligible for house construction.
*
* @return A list of {@link BuildingProperty} objects owned by the player.
*/
private List<BuildingProperty> getPlayerProperties() {
Player self = app.getGameLogic().getPlayerHandler().getPlayerById(app.getId());
BoardManager boardManager = app.getGameLogic().getBoardManager();
return boardManager.getPropertyFields(self.getProperties()).stream()
.filter(property -> property instanceof BuildingProperty)
.map(property -> (BuildingProperty) property)
.filter(property -> app.getGameLogic().getBoardManager().canBuild(property))
.collect(Collectors.toList());
}
/**
* Periodically updates the popup, tracking selection changes in the dropdown menu.
*
* @param delta Time since the last update in seconds.
*/
@Override
public void update(float delta) {
if(selectionRef.update()) {
onDropdownSelectionChanged(propertySelector);
}
}
/**
* Handles property selection changes in the dropdown menu.
*
* @param playerProperties the dropdown selector for the player's properties
*/
private void onDropdownSelectionChanged(Selector<String> playerProperties) {
String selected = playerProperties.getSelectedItem();
app.getGameLogic().playSound(Sound.BUTTON);
if (selectedProperties.contains(selected)) {
selectedProperties.remove(selected);
} else {
selectedProperties.add(selected);
}
int cost = 0;
for (String s : selectedProperties) {
cost += ((BuildingProperty) app.getGameLogic().getBoardManager().getFieldByName(s)).getHousePrice();
}
String display = String.join(" | ", selectedProperties);
selectionDisplay.setText(display);
this.cost.setText(cost+"");
}
/**
* Closes the popup and removes its GUI elements.
*/
@Override
public void close() {
app.getGuiNode().detachChild(buyHouseContainer);
app.getGuiNode().detachChild(backgroundContainer);
super.close();
}
/**
* Opens the settings menu when the escape key is pressed.
*/
@Override
public void escape() {
new SettingsMenu(app).open();
}
}

View File

@@ -1,169 +0,0 @@
package pp.monopoly.client.gui.popups;
import com.jme3.math.ColorRGBA;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.dialog.PopupDialog;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.client.gui.SettingsMenu;
import pp.monopoly.client.gui.TradeMenu;
import pp.monopoly.message.client.TradeResponse;
import pp.monopoly.model.TradeHandler;
import pp.monopoly.model.fields.PropertyField;
import pp.monopoly.notification.Sound;
/**
* ConfirmTrade is a popup which appears when a trade is proposed to this certain player.
*/
public class ConfirmTrade extends Dialog implements PopupDialog {
/** Reference to the Monopoly application instance. */
private final MonopolyApp app;
/** Main container for the "Confirm Trade" popup UI. */
private Container confirmTradeContainer;
/** Background container providing a border for the popup. */
private Container backgroundContainer;
/** The trade handler managing the details of the trade proposal. */
private final TradeHandler tradeHandler;
/**
* Constructs the "Confirm Trade" popup.
*
* @param app the Monopoly application instance
*/
public ConfirmTrade(MonopolyApp app) {
super(app.getDialogManager());
this.app = app;
this.tradeHandler = app.getGameLogic().getTradeHandler();
// Initialize components
createBackgroundContainer();
createConfirmTradeContainer();
}
/**
* Initializes the background container.
*/
private void createBackgroundContainer() {
backgroundContainer = new Container();
backgroundContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f)));
}
/**
* Initializes the main confirm trade container and its UI components.
*/
private void createConfirmTradeContainer() {
confirmTradeContainer = new Container();
// Title
Label title = confirmTradeContainer.addChild(new Label("Handel", new ElementId("warning-title")));
title.setFontSize(48);
title.setColor(ColorRGBA.Black);
// Build trade information strings
StringBuilder offeredProperties = new StringBuilder();
for (PropertyField field : tradeHandler.getOfferedProperties()) {
offeredProperties.append(field.getName()).append(", ");
}
StringBuilder requestedProperties = new StringBuilder();
for (PropertyField field : tradeHandler.getRequestedProperties()) {
requestedProperties.append(field.getName()).append(", ");
}
// Trade details
Container propertyValuesContainer = confirmTradeContainer.addChild(new Container());
propertyValuesContainer.addChild(new Label( tradeHandler.getSender().getName() + " möchte:", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("- " + offeredProperties, new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("- " + tradeHandler.getOfferedAmount() + " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("- " + tradeHandler.getOfferedJailCards() + " Sonderkarten", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("gegen:", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("- " + requestedProperties, new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("- " + tradeHandler.getRequestedAmount() + " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("- " + tradeHandler.getRequestedJailCards() + " Sonderkarten", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("tauschen, willst du das Angebot annehmen?", new ElementId("label-Text")));
propertyValuesContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
// Decline button
Button declineButton = confirmTradeContainer.addChild(new Button("Ablehnen", new ElementId("button")));
declineButton.setFontSize(32);
declineButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
app.getGameLogic().send(new TradeResponse(false, tradeHandler));
close();
}));
// Negotiate button
Button negotiateButton = confirmTradeContainer.addChild(new Button("Verhandeln", new ElementId("button")));
negotiateButton.setFontSize(32);
negotiateButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
close();
TradeHandler t = new TradeHandler(app.getGameLogic().getPlayerHandler().getPlayerById(tradeHandler.getSender().getId()));
t.setReceiver(app.getGameLogic().getPlayerHandler().getPlayerById(tradeHandler.getReceiver().getId()));
new TradeMenu(app, t).open();
}));
// Confirm button
Button confirmButton = confirmTradeContainer.addChild(new Button("Bestätigen", new ElementId("button")));
confirmButton.setFontSize(32);
confirmButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
app.getGameLogic().send(new TradeResponse(true, tradeHandler));
close();
}));
}
/**
* Displays the popup by attaching it to the GUI.
*/
@Override
public void show() {
float padding = 10;
// Center and adjust sizes
backgroundContainer.setPreferredSize(confirmTradeContainer.getPreferredSize().addLocal(padding, padding, 0));
confirmTradeContainer.setLocalTranslation(
(app.getCamera().getWidth() - confirmTradeContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + confirmTradeContainer.getPreferredSize().y) / 2,
8
);
backgroundContainer.setLocalTranslation(
(app.getCamera().getWidth() - confirmTradeContainer.getPreferredSize().x - padding) / 2,
(app.getCamera().getHeight() + confirmTradeContainer.getPreferredSize().y + padding) / 2,
7
);
// Attach to GUI node
app.getGuiNode().attachChild(backgroundContainer);
app.getGuiNode().attachChild(confirmTradeContainer);
}
/**
* Closes the popup and removes its GUI elements.
*/
@Override
public void close() {
app.getGuiNode().detachChild(confirmTradeContainer);
app.getGuiNode().detachChild(backgroundContainer);
super.close();
}
/**
* Opens the settings menu when the escape key is pressed.
*/
@Override
public void escape() {
new SettingsMenu(app).open();
}
}

View File

@@ -0,0 +1,118 @@
package pp.monopoly.client.gui.popups;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Quad;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.model.card.Card; // TODO für den Import der Queue notwendig
/**
* SettingsMenu ist ein Overlay-Menü, das durch ESC aufgerufen werden kann.
*/
public class EventCard extends Dialog {
private final MonopolyApp app;
private final Geometry overlayBackground;
private final Container eventCardContainer;
private final Container backgroundContainer;
public EventCard(MonopolyApp app) {
super(app.getDialogManager());
this.app = app;
//Generate the corresponfing field
Card card = app.getDeckHelper().drawCard(); // TODO nimmt die Karten gerade unabhängig aus dem DeckHelper
// Halbtransparentes Overlay hinzufügen
overlayBackground = createOverlayBackground();
app.getGuiNode().attachChild(overlayBackground);
// Create the background container
backgroundContainer = new Container();
backgroundContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f))); // Darker background
app.getGuiNode().attachChild(backgroundContainer);
// Hauptcontainer für die Gebäudekarte
eventCardContainer = new Container();
eventCardContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f)));
// Titel
// Die Namen werden dynamisch dem BoardManager entnommen
Label gateFieldTitle = eventCardContainer.addChild(new Label("Ereigniskarte", new ElementId("settings-title")));
gateFieldTitle.setFontSize(48);
gateFieldTitle.setColor(ColorRGBA.Black);
// Text, der auf der Karte steht
// Die Preise werden dynamisch dem BoardManager entnommen
Container propertyValuesContainer = eventCardContainer.addChild(new Container());
propertyValuesContainer.addChild(new Label(card.getDescription(), new ElementId("label-Text")));
propertyValuesContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
// Beenden-Button
Button quitButton = eventCardContainer.addChild(new Button("Jawohl", new ElementId("button")));
quitButton.setFontSize(32);
quitButton.addClickCommands(source -> close());
// TODO Kaufen-Button wird nicht mehr benötigt, prüfen ob weg kann
//Button buyButton = buyCardContainer.addChild(new Button("Kaufen", new ElementId("button")));
//buyButton.setFontSize(32);
float padding = 10; // Padding around the settingsContainer for the background
backgroundContainer.setPreferredSize(eventCardContainer.getPreferredSize().addLocal(padding, padding, 0));
// Zentriere das Menü
eventCardContainer.setLocalTranslation(
(app.getCamera().getWidth() - eventCardContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + eventCardContainer.getPreferredSize().y) / 2,
8
);
backgroundContainer.setLocalTranslation(
(app.getCamera().getWidth() - eventCardContainer.getPreferredSize().x - padding) / 2,
(app.getCamera().getHeight() + eventCardContainer.getPreferredSize().y+ padding) / 2,
7
);
app.getGuiNode().attachChild(eventCardContainer);
}
/**
* Erstellt einen halbtransparenten Hintergrund für das Menü.
*
* @return Geometrie des Overlays
*/
private Geometry createOverlayBackground() {
Quad quad = new Quad(app.getCamera().getWidth(), app.getCamera().getHeight());
Geometry overlay = new Geometry("Overlay", quad);
Material material = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
material.setColor("Color", new ColorRGBA(0, 0, 0, 0.5f)); // Halbtransparent
material.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
overlay.setMaterial(material);
overlay.setLocalTranslation(0, 0, 0);
return overlay;
}
/**
* Schließt das Menü und entfernt die GUI-Elemente.
*/
@Override
public void close() {
System.out.println("Schließe SettingsMenu..."); // Debugging-Ausgabe
app.getGuiNode().detachChild(eventCardContainer); // Entferne das Menü
app.getGuiNode().detachChild(backgroundContainer); //Entfernt Rand
app.getGuiNode().detachChild(overlayBackground); // Entferne das Overlay
app.setBuyCardPopupOpen(false); // Menü als geschlossen markieren TODO passt diese Variable noch (zu finden unter den Temps in MonopolyApp
app.unblockInputs(); // Eingaben wieder aktivieren
System.out.println("SettingsMenu geschlossen."); // Debugging-Ausgabe
}
}

View File

@@ -1,146 +0,0 @@
package pp.monopoly.client.gui.popups;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Quad;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.dialog.PopupDialog;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.notification.Sound;
/**
* EventCardPopup is a popup which appears when a certain EventCard is triggered by entering an EventCardField.
*/
public class EventCardPopup extends Dialog implements PopupDialog {
/** Reference to the Monopoly application instance. */
private final MonopolyApp app;
/** Semi-transparent overlay background for the popup. */
private Geometry overlayBackground;
/** Main container for the event card information. */
private Container eventCardContainer;
/** Background container providing a border for the popup. */
private Container backgroundContainer;
/**
* Constructs the EventCardPopup to display the details of a triggered event card.
*
* @param app the Monopoly application instance
* @param description the description of the triggered event card
*/
public EventCardPopup(MonopolyApp app, String description) {
super(app.getDialogManager());
this.app = app;
// Initialize the UI components
createOverlayBackground();
createBackgroundContainer();
createEventCardContainer(description);
}
/**
* Initializes the semi-transparent background overlay.
*/
private void createOverlayBackground() {
Quad quad = new Quad(app.getCamera().getWidth(), app.getCamera().getHeight());
overlayBackground = new Geometry("Overlay", quad);
Material material = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
material.setColor("Color", new ColorRGBA(0, 0, 0, 0.5f)); // Semi-transparent black
material.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
overlayBackground.setMaterial(material);
overlayBackground.setLocalTranslation(0, 0, 0);
}
/**
* Initializes the background container.
*/
private void createBackgroundContainer() {
backgroundContainer = new Container();
backgroundContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f))); // Light gray background
}
/**
* Initializes the main event card container and its UI components.
*
* @param description the description of the triggered event card
*/
private void createEventCardContainer(String description) {
eventCardContainer = new Container();
eventCardContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f)));
eventCardContainer.setPreferredSize(new Vector3f(550, 400, 10));
// Title
Label title = eventCardContainer.addChild(new Label("Ereigniskarte", new ElementId("settings-title")));
title.setFontSize(48);
title.setColor(ColorRGBA.Black);
// Event description
Container textContainer = eventCardContainer.addChild(new Container());
textContainer.addChild(new Label(description, new ElementId("label-Text")));
textContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
textContainer.setPreferredSize(new Vector3f(300, 200, 0));
// Confirm button
Button confirmButton = eventCardContainer.addChild(new Button("Jawohl", new ElementId("button")));
confirmButton.setFontSize(32);
confirmButton.addClickCommands(source -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
close();
}));
}
/**
* Displays the popup by attaching it to the GUI.
*/
@Override
public void show() {
float padding = 10;
// Adjust sizes and center elements
backgroundContainer.setPreferredSize(eventCardContainer.getPreferredSize().addLocal(padding, padding, 0));
eventCardContainer.setLocalTranslation(
(app.getCamera().getWidth() - eventCardContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + eventCardContainer.getPreferredSize().y) / 2,
8
);
backgroundContainer.setLocalTranslation(
(app.getCamera().getWidth() - eventCardContainer.getPreferredSize().x - padding) / 2,
(app.getCamera().getHeight() + eventCardContainer.getPreferredSize().y + padding) / 2,
7
);
// Attach components to the GUI
app.getGuiNode().attachChild(overlayBackground);
app.getGuiNode().attachChild(backgroundContainer);
app.getGuiNode().attachChild(eventCardContainer);
}
/**
* Closes the popup and removes its associated GUI elements.
*/
@Override
public void close() {
app.getGuiNode().detachChild(overlayBackground);
app.getGuiNode().detachChild(eventCardContainer);
app.getGuiNode().detachChild(backgroundContainer);
super.close();
}
/**
* Handles the escape key action by closing the popup.
*/
@Override
public void escape() {
close();
}
}

View File

@@ -3,168 +3,134 @@ package pp.monopoly.client.gui.popups;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Quad;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.dialog.PopupDialog;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.message.client.BuyPropertyResponse;
import pp.monopoly.model.fields.FoodField;
import pp.monopoly.notification.Sound;
/**
* FoodFieldCard creates the popup for field information.
* FoodFieldCard erstellt die Geböudekarte vom Brandl und der Truppenküche
*/
public class FoodFieldCard extends Dialog implements PopupDialog {
/** Reference to the Monopoly application instance. */
public class FoodFieldCard extends Dialog {
private final MonopolyApp app;
private final Geometry overlayBackground;
private final Container foodFieldContainer;
private final Container backgroundContainer;
private int index = 12;
/** Semi-transparent overlay background for the popup. */
private Geometry overlayBackground;
/** Main container for the food field information. */
private Container foodFieldContainer;
/** Background container providing a border for the popup. */
private Container backgroundContainer;
/**
* Constructs a FoodFieldCard popup displaying details about a food field.
*
* @param app the Monopoly application instance
*/
public FoodFieldCard(MonopolyApp app) {
super(app.getDialogManager());
this.app = app;
// Retrieve field information
int index = app.getGameLogic().getPlayerHandler().getPlayerById(app.getId()).getFieldID();
//Generate the corresponfing field
FoodField field = (FoodField) app.getGameLogic().getBoardManager().getFieldAtIndex(index);
// Create UI elements
createOverlayBackground();
createBackgroundContainer();
createFoodFieldContainer(field);
}
// Halbtransparentes Overlay hinzufügen
overlayBackground = createOverlayBackground();
app.getGuiNode().attachChild(overlayBackground);
/**
* Initializes the semi-transparent background overlay.
*/
private void createOverlayBackground() {
Quad quad = new Quad(app.getCamera().getWidth(), app.getCamera().getHeight());
overlayBackground = new Geometry("Overlay", quad);
Material material = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
material.setColor("Color", new ColorRGBA(0, 0, 0, 0.5f)); // Semi-transparent
material.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
overlayBackground.setMaterial(material);
overlayBackground.setLocalTranslation(0, 0, 0);
}
/**
* Initializes the background container.
*/
private void createBackgroundContainer() {
// Create the background container
backgroundContainer = new Container();
backgroundContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f))); // Light gray background
backgroundContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f))); // Darker background
app.getGuiNode().attachChild(backgroundContainer);
}
/**
* Initializes the main food field container and its UI components.
*
* @param field the food field information to display
*/
private void createFoodFieldContainer(FoodField field) {
// Hauptcontainer für die Gebäudekarte
foodFieldContainer = new Container();
foodFieldContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.1f, 0.1f, 0.1f, 0.9f)));
foodFieldContainer.setPreferredSize(new Vector3f(360,445,1));
// Title
Label title = foodFieldContainer.addChild(new Label(field.getName(), new ElementId("label-Bold")));
title.setFontSize(48);
title.setColor(ColorRGBA.White);
// Field details
// Titel, bestehend aus dynamischen Namen anhand der ID und der Schriftfarbe/größe
Label settingsTitle = foodFieldContainer.addChild(new Label(field.getName(), new ElementId("settings-title")));
settingsTitle.setFontSize(48);
// Text, der auf der Karte steht
Container propertyValuesContainer = foodFieldContainer.addChild(new Container());
propertyValuesContainer.addChild(new Label("„Preis: " + field.getPrice() + " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("", new ElementId("label-Text"))); // Empty line
propertyValuesContainer.addChild(new Label("Miete: 40x Würfel-Augen,", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("„wenn Besitzer eines ", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("„Restaurants.", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("„Miete: 100x Würfel-Augen, ", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("„wenn Besitzer eines ", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("Restaurants.", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("", new ElementId("label-Text"))); // Empty line
propertyValuesContainer.addChild(new Label("", new ElementId("label-Text"))); // Leerzeile
propertyValuesContainer.addChild(new Label("Wenn man Besitzer des", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label(field.getName()+" ist, so ist die", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("Miete 40-mal so hoch, wie", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("Augen auf den zwei Würfeln sind.", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("", new ElementId("label-Text"))); // Leerzeile
propertyValuesContainer.addChild(new Label("Wenn man Besitzer beider", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("Restaurants ist, so ist die", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("Miete 100-mal so hoch, wie", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("Augen auf den zwei Würfeln sind.", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("", new ElementId("label-Text"))); // Leerzeile
propertyValuesContainer.addChild(new Label("„Hypothek: " + field.getHypo() + " EUR", new ElementId("label-Text")));
propertyValuesContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
// Quit button
//TODO eventuell diese Stelle löschen, da nur die BuyCard Kaufen und beenden hat
/*
// Beenden-Button
Button quitButton = foodFieldContainer.addChild(new Button("Beenden", new ElementId("button")));
quitButton.setFontSize(32);
quitButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
close();
}));
// Buy button
// Kaufen-Button
Button buyButton = foodFieldContainer.addChild(new Button("Kaufen", new ElementId("button")));
buyButton.setFontSize(32);
buyButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
app.getGameLogic().send(new BuyPropertyResponse());
close();
}));
}
*/
/**
* Displays the popup by attaching its elements to the GUI.
*/
@Override
public void show() {
float padding = 10;
// Adjust sizes and center elements
float padding = 10; // Padding around the settingsContainer for the background
backgroundContainer.setPreferredSize(foodFieldContainer.getPreferredSize().addLocal(padding, padding, 0));
// Zentriere das Menü
foodFieldContainer.setLocalTranslation(
(app.getCamera().getWidth() - foodFieldContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + foodFieldContainer.getPreferredSize().y) / 2,
8
(app.getCamera().getWidth() - foodFieldContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + foodFieldContainer.getPreferredSize().y) / 2,
8
);
backgroundContainer.setLocalTranslation(
(app.getCamera().getWidth() - foodFieldContainer.getPreferredSize().x - padding) / 2,
(app.getCamera().getHeight() + foodFieldContainer.getPreferredSize().y + padding) / 2,
(app.getCamera().getHeight() + foodFieldContainer.getPreferredSize().y+ padding) / 2,
7
);
// Attach components to the GUI
app.getGuiNode().attachChild(overlayBackground);
app.getGuiNode().attachChild(backgroundContainer);
app.getGuiNode().attachChild(foodFieldContainer);
}
/**
* Closes the popup and removes its associated GUI elements.
* Erstellt einen halbtransparenten Hintergrund für das Menü.
*
* @return Geometrie des Overlays
*/
@Override
public void close() {
app.getGuiNode().detachChild(overlayBackground);
app.getGuiNode().detachChild(foodFieldContainer);
app.getGuiNode().detachChild(backgroundContainer);
super.close();
private Geometry createOverlayBackground() {
Quad quad = new Quad(app.getCamera().getWidth(), app.getCamera().getHeight());
Geometry overlay = new Geometry("Overlay", quad);
Material material = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
material.setColor("Color", new ColorRGBA(0, 0, 0, 0.5f)); // Halbtransparent
material.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
overlay.setMaterial(material);
overlay.setLocalTranslation(0, 0, 0);
return overlay;
}
/**
* Handles the escape key action by closing the popup.
* Schließt das Menü und entfernt die GUI-Elemente.
*/
@Override
public void escape() {
close();
public void close() {
System.out.println("Schließe SettingsMenu..."); // Debugging-Ausgabe
app.getGuiNode().detachChild(foodFieldContainer); // Entferne das Menü
app.getGuiNode().detachChild(backgroundContainer); //Entfernt Rand
app.getGuiNode().detachChild(overlayBackground); // Entferne das Overlay
app.setSettingsMenuOpen(false); // Menü als geschlossen markieren TODO passt diese Variable noch (zu finden unter den Temps in MonopolyApp
app.unblockInputs(); // Eingaben wieder aktivieren
System.out.println("SettingsMenu geschlossen."); // Debugging-Ausgabe
}
public void setIndex(int index) {
this.index = index;
}
}

View File

@@ -1,149 +1,129 @@
package pp.monopoly.client.gui.popups;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.simsilica.lemur.Button;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Quad;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.dialog.PopupDialog;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.client.gui.SettingsMenu;
import pp.monopoly.message.client.BuyPropertyResponse;
import pp.monopoly.model.fields.GateField;
import pp.monopoly.notification.Sound;
/**
* GateFieldCard creates the popup for field information.
* SettingsMenu ist ein Overlay-Menü, das durch ESC aufgerufen werden kann.
*/
public class GateFieldCard extends Dialog implements PopupDialog {
/** Reference to the Monopoly application instance. */
public class GateFieldCard extends Dialog {
private final MonopolyApp app;
private final Geometry overlayBackground;
private final Container gateFieldContainer;
private final Container backgroundContainer;
private int index = 5;
/** Main container for the gate field information. */
private Container gateFieldContainer;
/** Background container providing a border for the popup. */
private Container backgroundContainer;
/**
* Constructs a GateFieldCard popup displaying details about a gate field.
*
* @param app the Monopoly application instance
*/
public GateFieldCard(MonopolyApp app) {
super(app.getDialogManager());
this.app = app;
// Generate the corresponding field
int index = app.getGameLogic().getPlayerHandler().getPlayerById(app.getId()).getFieldID();
//Generate the corresponfing field
GateField field = (GateField) app.getGameLogic().getBoardManager().getFieldAtIndex(index);
// Initialize UI elements
createBackgroundContainer();
createGateFieldContainer(field);
}
// Halbtransparentes Overlay hinzufügen
overlayBackground = createOverlayBackground();
app.getGuiNode().attachChild(overlayBackground);
/**
* Initializes the background container.
*/
private void createBackgroundContainer() {
// Create the background container
backgroundContainer = new Container();
backgroundContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f))); // Light gray background
}
backgroundContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f))); // Darker background
app.getGuiNode().attachChild(backgroundContainer);
/**
* Initializes the main gate field container and its UI components.
*
* @param field the gate field information to display
*/
private void createGateFieldContainer(GateField field) {
// Hauptcontainer für die Gebäudekarte
gateFieldContainer = new Container();
//TODO: Set the size of the container to the size of the screen @Simon
gateFieldContainer.setPreferredSize(new Vector3f(360,460,1));
gateFieldContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f)));
// Title
Label gateFieldTitle = gateFieldContainer.addChild(new Label(field.getName(), new ElementId("label-Bold")));
// Titel
// Die Namen werden dynamisch dem BoardManager entnommen
Label gateFieldTitle = gateFieldContainer.addChild(new Label(field.getName(), new ElementId("settings-title")));
gateFieldTitle.setFontSize(48);
gateFieldTitle.setColor(ColorRGBA.Black);
// Field details
// Text, der auf der Karte steht
// Die Preise werden dynamisch dem BoardManager entnommen
Container propertyValuesContainer = gateFieldContainer.addChild(new Container());
propertyValuesContainer.addChild(new Label("„Preis: " + field.getPrice() + " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("", new ElementId("label-Text"))); // Empty line
propertyValuesContainer.addChild(new Label("Miete: 250 EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("Wenn man 2 Tore", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("besitzt: 500 EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("Wenn man 3 Tore", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("besitzt: 1000 EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("Wenn man 4 Tore", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("besitzt: 2000 EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("", new ElementId("label-Text"))); // Empty line
propertyValuesContainer.addChild(new Label("", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("Wenn man 1 Bahnhof besitzt: 250 EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("Wenn man 2 Bahnhöfe besitzt: 500 EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("Wenn man 3 Bahnhöfe besitzt: 1000 EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("Wenn man 4 Bahnhöfe besitzt: 2000 EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("„Hypothek: " + field.getHypo() + " EUR", new ElementId("label-Text")));
propertyValuesContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
// Quit button
Button quitButton = gateFieldContainer.addChild(new Button("Beenden", new ElementId("button")));
//TODO eventuell diese Stelle löschen, da nur die BuyCard Kaufen und beenden hat
/*
// Beenden-Button
Button quitButton = foodFieldContainer.addChild(new Button("Beenden", new ElementId("button")));
quitButton.setFontSize(32);
quitButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
close();
}));
// Buy button
Button buyButton = gateFieldContainer.addChild(new Button("Kaufen", new ElementId("button")));
// Kaufen-Button
Button buyButton = foodFieldContainer.addChild(new Button("Kaufen", new ElementId("button")));
buyButton.setFontSize(32);
buyButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
app.getGameLogic().send(new BuyPropertyResponse());
close();
}));
}
*/
/**
* Displays the popup by attaching its elements to the GUI.
*/
@Override
public void show() {
float padding = 10;
// Adjust sizes and center elements
float padding = 10; // Padding around the settingsContainer for the background
backgroundContainer.setPreferredSize(gateFieldContainer.getPreferredSize().addLocal(padding, padding, 0));
// Zentriere das Menü
gateFieldContainer.setLocalTranslation(
(app.getCamera().getWidth() - gateFieldContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + gateFieldContainer.getPreferredSize().y) / 2,
8
(app.getCamera().getWidth() - gateFieldContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + gateFieldContainer.getPreferredSize().y) / 2,
8
);
backgroundContainer.setLocalTranslation(
(app.getCamera().getWidth() - gateFieldContainer.getPreferredSize().x - padding) / 2,
(app.getCamera().getHeight() + gateFieldContainer.getPreferredSize().y + padding) / 2,
(app.getCamera().getHeight() + gateFieldContainer.getPreferredSize().y+ padding) / 2,
7
);
// Attach components to the GUI
app.getGuiNode().attachChild(backgroundContainer);
app.getGuiNode().attachChild(gateFieldContainer);
}
/**
* Closes the popup and removes its associated GUI elements.
* Erstellt einen halbtransparenten Hintergrund für das Menü.
*
* @return Geometrie des Overlays
*/
@Override
public void close() {
app.getGuiNode().detachChild(gateFieldContainer); // Remove main container
app.getGuiNode().detachChild(backgroundContainer); // Remove background container
super.close();
private Geometry createOverlayBackground() {
Quad quad = new Quad(app.getCamera().getWidth(), app.getCamera().getHeight());
Geometry overlay = new Geometry("Overlay", quad);
Material material = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
material.setColor("Color", new ColorRGBA(0, 0, 0, 0.5f)); // Halbtransparent
material.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
overlay.setMaterial(material);
overlay.setLocalTranslation(0, 0, 0);
return overlay;
}
/**
* Opens the settings menu when the escape key is pressed.
* Schließt das Menü und entfernt die GUI-Elemente.
*/
@Override
public void escape() {
new SettingsMenu(app).open();
public void close() {
System.out.println("Schließe SettingsMenu..."); // Debugging-Ausgabe
app.getGuiNode().detachChild(gateFieldContainer); // Entferne das Menü
app.getGuiNode().detachChild(backgroundContainer); //Entfernt Rand
app.getGuiNode().detachChild(overlayBackground); // Entferne das Overlay
app.setSettingsMenuOpen(false); // Menü als geschlossen markieren TODO passt diese Variable noch (zu finden unter den Temps in MonopolyApp
app.unblockInputs(); // Eingaben wieder aktivieren
System.out.println("SettingsMenu geschlossen."); // Debugging-Ausgabe
}
public void setIndex(int index) {
this.index = index;
}
}

View File

@@ -1,141 +0,0 @@
package pp.monopoly.client.gui.popups;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Quad;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.dialog.PopupDialog;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.notification.Sound;
/**
* Gulag is a warning popup triggered when a player lands on the "Wache" field in the Monopoly game.
* <p>
* This popup informs the player that they are being sent to the Gulag and includes a confirmation button.
* </p>
*/
public class Gulag extends Dialog implements PopupDialog {
/** Reference to the Monopoly application instance. */
private final MonopolyApp app;
/** Semi-transparent overlay background for the popup. */
private Geometry overlayBackground;
/** Main container for the Gulag warning message. */
private Container gulagContainer;
/** Background container providing a border for the popup. */
private Container backgroundContainer;
/**
* Constructs the Gulag popup.
*
* @param app the Monopoly application instance
*/
public Gulag(MonopolyApp app) {
super(app.getDialogManager());
this.app = app;
// Initialize UI elements
createOverlayBackground();
createBackgroundContainer();
createGulagContainer();
}
/**
* Creates the semi-transparent overlay background for the popup.
*/
private void createOverlayBackground() {
Quad quad = new Quad(app.getCamera().getWidth(), app.getCamera().getHeight());
overlayBackground = new Geometry("Overlay", quad);
Material material = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
material.setColor("Color", new ColorRGBA(0, 0, 0, 0.5f)); // Semi-transparent black
material.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
overlayBackground.setMaterial(material);
overlayBackground.setLocalTranslation(0, 0, 0);
}
/**
* Creates the background container providing a border for the popup.
*/
private void createBackgroundContainer() {
backgroundContainer = new Container();
backgroundContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f))); // Light gray background
}
/**
* Creates the main container for the Gulag warning message.
*/
private void createGulagContainer() {
gulagContainer = new Container();
gulagContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f)));
gulagContainer.setPreferredSize(new Vector3f(550, 250, 10));
// Title
Label title = gulagContainer.addChild(new Label("Du kommst ins Gulag!", new ElementId("warning-title")));
title.setFontSize(48);
title.setColor(ColorRGBA.Black);
// Confirmation Button
Button confirmButton = gulagContainer.addChild(new Button("Jawohl Gulag", new ElementId("button")));
confirmButton.setFontSize(32);
confirmButton.addClickCommands(source -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
close();
}));
}
/**
* Displays the popup by attaching its elements to the GUI.
*/
@Override
public void show() {
float padding = 10;
// Adjust and position the containers
backgroundContainer.setPreferredSize(gulagContainer.getPreferredSize().addLocal(padding, padding, 0));
gulagContainer.setLocalTranslation(
(app.getCamera().getWidth() - gulagContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + gulagContainer.getPreferredSize().y) / 2,
8
);
backgroundContainer.setLocalTranslation(
(app.getCamera().getWidth() - gulagContainer.getPreferredSize().x - padding) / 2,
(app.getCamera().getHeight() + gulagContainer.getPreferredSize().y + padding) / 2,
7
);
// Attach components to the GUI
app.getGuiNode().attachChild(overlayBackground);
app.getGuiNode().attachChild(backgroundContainer);
app.getGuiNode().attachChild(gulagContainer);
}
/**
* Closes the popup and removes its associated GUI elements.
*/
@Override
public void close() {
app.getGuiNode().detachChild(overlayBackground);
app.getGuiNode().detachChild(gulagContainer);
app.getGuiNode().detachChild(backgroundContainer);
super.close();
}
/**
* Handles the escape action by closing the popup.
*/
@Override
public void escape() {
close();
}
}

View File

@@ -1,154 +0,0 @@
package pp.monopoly.client.gui.popups;
import com.jme3.math.ColorRGBA;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.dialog.PopupDialog;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.message.client.NotificationAnswer;
import pp.monopoly.notification.Sound;
/**
* GulagInfo is a popup that provides options for a player who is stuck in the "Gulag" (jail) field.
* This dialog offers multiple actions, including paying a bribe, using a "Get Out of Jail" card, or waiting.
*/
public class GulagInfo extends Dialog implements PopupDialog {
/** Reference to the Monopoly application instance. */
private final MonopolyApp app;
/** Main container for the Gulag information dialog. */
private Container gulagInfoContainer;
/** Background container providing a styled border around the dialog. */
private Container backgroundContainer;
/**
* Constructs a GulagInfo popup that provides the player with options for getting out of the "Gulag" field.
*
* @param app the Monopoly application instance
* @param trys the number of failed attempts to roll doubles for release
*/
public GulagInfo(MonopolyApp app, int trys) {
super(app.getDialogManager());
this.app = app;
// Initialize UI components
createBackgroundContainer();
createGulagInfoContainer(trys);
}
/**
* Creates the background container providing a border for the dialog.
*/
private void createBackgroundContainer() {
backgroundContainer = new Container();
backgroundContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f))); // Light gray background
}
/**
* Creates the main container for the Gulag information dialog.
*
* @param trys the number of failed attempts to roll doubles for release
*/
private void createGulagInfoContainer(int trys) {
gulagInfoContainer = new Container();
gulagInfoContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f)));
// Title
Label title = gulagInfoContainer.addChild(new Label("Gulag", new ElementId("warning-title")));
title.setFontSize(48);
title.setColor(ColorRGBA.Black);
// Text Description
Container textContainer = gulagInfoContainer.addChild(new Container());
textContainer.addChild(new Label("„Du sitzt im Gefängnis und kommst nicht raus ...", new ElementId("label-Text")));
textContainer.addChild(new Label("Es sei denn, du ...", new ElementId("label-Text")));
textContainer.addChild(new Label("- bestichst die Wache mit 500 EUR", new ElementId("label-Text")));
textContainer.addChild(new Label("- löst eine Gulag-Frei-Karte ein", new ElementId("label-Text")));
textContainer.addChild(new Label("- wartest 3 Runden und bezahlst dann", new ElementId("label-Text")));
textContainer.addChild(new Label("- oder du würfelst einen Pasch", new ElementId("label-Text")));
textContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
// Action Buttons
addActionButtons(trys);
}
/**
* Adds action buttons to the dialog.
*
* @param trys the number of failed attempts to roll doubles for release
*/
private void addActionButtons(int trys) {
// Bribe Button
Button payButton = gulagInfoContainer.addChild(new Button("Bestechungsgeld bezahlen", new ElementId("button")));
payButton.setFontSize(32);
payButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
app.getGameLogic().send(new NotificationAnswer("PayJail"));
close();
}));
// Use Jail-Free Card Button
Button eventCardButton = gulagInfoContainer.addChild(new Button("Ereigniskarte nutzen", new ElementId("button-toolbar2")));
eventCardButton.setFontSize(32);
eventCardButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
app.getGameLogic().send(new NotificationAnswer("UseJailCard"));
close();
}));
// Close Button
Button closeButton = gulagInfoContainer.addChild(new Button("Schließen", new ElementId("button")));
closeButton.setFontSize(32);
closeButton.addClickCommands(s -> ifTopDialog(this::close));
// Disable options based on conditions
if (app.getGameLogic().getPlayerHandler().getPlayerById(app.getId()).getNumJailCard() == 0) {
eventCardButton.setEnabled(false);
}
if (trys == 3) {
closeButton.setEnabled(false);
}
}
/**
* Displays the popup by attaching its elements to the GUI.
*/
@Override
public void show() {
float padding = 10;
// Adjust the background size
backgroundContainer.setPreferredSize(gulagInfoContainer.getPreferredSize().addLocal(padding, padding, 0));
// Center the dialog and background
gulagInfoContainer.setLocalTranslation(
(app.getCamera().getWidth() - gulagInfoContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + gulagInfoContainer.getPreferredSize().y) / 2,
8
);
backgroundContainer.setLocalTranslation(
(app.getCamera().getWidth() - gulagInfoContainer.getPreferredSize().x - padding) / 2,
(app.getCamera().getHeight() + gulagInfoContainer.getPreferredSize().y + padding) / 2,
7
);
// Attach containers to the GUI
app.getGuiNode().attachChild(backgroundContainer);
app.getGuiNode().attachChild(gulagInfoContainer);
}
/**
* Closes the GulagInfo popup and removes its GUI elements.
*/
@Override
public void close() {
app.getGuiNode().detachChild(gulagInfoContainer); // Remove dialog
app.getGuiNode().detachChild(backgroundContainer); // Remove background
super.close();
}
}

View File

@@ -1,145 +1,52 @@
package pp.monopoly.client.gui.popups;
import com.jme3.material.Material;
import com.jme3.material.RenderState;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Quad;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.component.IconComponent;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.notification.Sound;
/**
* LooserPopUp is a dialog that appears when a player loses the game.
* <p>
* This popup provides a message of encouragement and an option to quit the game.
* </p>
*/
public class LooserPopUp extends Dialog {
/** Reference to the Monopoly application instance. */
private final MonopolyApp app;
/** Semi-transparent overlay background for the dialog. */
private final Geometry overlayBackground;
/** Main container for the "Looser" dialog UI. */
private final Container LooserContainer;
/** Background container providing a styled border around the main dialog. */
private final Container backgroundContainer;
/**
* Constructs a new WinnerPopUp dialog.
* Constructs a new NetworkDialog.
*
* @param app The MonopolyApp instance.
* @param network The NetworkSupport instance to be used for network operations.
*/
public LooserPopUp(MonopolyApp app) {
super(app.getDialogManager());
this.app = app;
initializeDialog();
}
/**
* Initializes the dialog with input fields and connection buttons.
*/
private void initializeDialog() {
Container inputContainer = new Container();
// Halbtransparentes Overlay hinzufügen
overlayBackground = createOverlayBackground();
app.getGuiNode().attachChild(overlayBackground);
// Titel und Eingabefelder für Host und Port
inputContainer.addChild(new Label("Schade, du hast leider verloren!"));
inputContainer.addChild(new Label("Die nächste Runde wird besser!"));
// Create the background container
backgroundContainer = new Container();
backgroundContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f))); // Darker background
app.getGuiNode().attachChild(backgroundContainer);
// Hauptcontainer für die Warnung
LooserContainer = new Container();
LooserContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f)));
LooserContainer.setPreferredSize(new Vector3f(355,600,10));
float padding = 10; // Passt den backgroundContainer an die Größe des bankruptContainers an
backgroundContainer.setPreferredSize(LooserContainer.getPreferredSize().addLocal(padding, padding, 0));
// Titel
Label looserTitle = LooserContainer.addChild(new Label("Schade, du hast leider verloren, die nächste Runde wird besser!", new ElementId("header")));
looserTitle.setFontSize(25);
// looserTitle.setColor(ColorRGBA.Black);
// Create the image container
Container imageContainer = LooserContainer.addChild(new Container());
imageContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f))); // Dark gray background
imageContainer.setPreferredSize(LooserContainer.getPreferredSize().addLocal(-250, -200, 0)); // Adjust size for layout
// Add the image to the container
Label imageLabel = new Label(""); // Create a label for the image
IconComponent icon = new IconComponent("Pictures/MonopolyLooser.png"); // Load the image as an icon
icon.setIconScale(0.7f); // Scale the image appropriately
Label imageLabel = new Label("");
IconComponent icon = new IconComponent("Pictures/MonopolyLooser.png"); // Icon mit Textur erstellen
icon.setIconScale(1); // Skalierung des Bildes
imageLabel.setIcon(icon);
imageContainer.addChild(imageLabel); // Add the image label to the container
//Beenden Button
Button quitButton = LooserContainer.addChild(new Button("Spiel Beenden", new ElementId("button")));
quitButton.setFontSize(32);
quitButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
app.closeApp();
}));
// Setze das Icon im Label
inputContainer.addChild(imageLabel);
Button cancelButton = inputContainer.addChild(new Button("Spiel beenden"));
cancelButton.addClickCommands(source -> ifTopDialog(app::closeApp));
// Zentriere das Popup
LooserContainer.setLocalTranslation(
(app.getCamera().getWidth() - LooserContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + LooserContainer.getPreferredSize().y) / 2,
8
);
inputContainer.setLocalTranslation(300, 800, 0);
app.getGuiNode().attachChild(inputContainer);
// Zentriere das Popup
backgroundContainer.setLocalTranslation(
(app.getCamera().getWidth() - LooserContainer.getPreferredSize().x - padding) / 2,
(app.getCamera().getHeight() + LooserContainer.getPreferredSize().y+ padding) / 2,
7
);
app.getGuiNode().attachChild(LooserContainer);
}
/**
* Creates a semi-transparent background overlay for the popup.
*
* @return The overlay geometry.
*/
private Geometry createOverlayBackground() {
Quad quad = new Quad(app.getCamera().getWidth(), app.getCamera().getHeight());
Geometry overlay = new Geometry("Overlay", quad);
Material material = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
material.setColor("Color", new ColorRGBA(0, 0, 0, 0.5f)); // Halbtransparent
material.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
overlay.setMaterial(material);
overlay.setLocalTranslation(0, 0, 0);
return overlay;
}
/**
* Closes the LooserPopUp dialog and removes its GUI elements.
*/
@Override
public void close() {
app.getGuiNode().detachChild(LooserContainer); // Entferne das Menü
app.getGuiNode().detachChild(backgroundContainer); //Entfernt Rand
app.getGuiNode().detachChild(overlayBackground); // Entferne das Overlay
super.close();
}
/**
* Handles the escape action to close the dialog.
*/
@Override
public void escape() {
close();
}
}

View File

@@ -0,0 +1,55 @@
package pp.monopoly.client.gui.popups;
import com.jme3.asset.TextureKey;
import com.jme3.math.Vector2f;
import com.jme3.texture.Texture;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.component.IconComponent;
import pp.dialog.Dialog;
import pp.monopoly.client.MonopolyApp;
public class LoserPopUp extends Dialog {
private final MonopolyApp app;
/**
* Constructs a new NetworkDialog.
*
* @param network The NetworkSupport instance to be used for network operations.
*/
public LoserPopUp(MonopolyApp app) {
super(app.getDialogManager());
this.app = app;
initializeDialog();
}
/**
* Initializes the dialog with input fields and connection buttons.
*/
private void initializeDialog() {
Container inputContainer = new Container();
// Titel und Eingabefelder für Host und Port
inputContainer.addChild(new Label("Schade, du hast leider verloren!"));
inputContainer.addChild(new Label("Die nächste Runde wird besser!"));
Label imageLabel = new Label("");
TextureKey key = new TextureKey("Pictures/MonopolyLoser.png", true);
Texture texture = app.getAssetManager().loadTexture(key);
IconComponent icon = new IconComponent(texture.toString()); // Icon mit Textur erstellen
icon.setIconSize(new Vector2f(155f, 120f)); // Skalierung des Bildes
imageLabel.setIcon(icon); // Setze das Icon im Label
inputContainer.addChild(imageLabel);
Button cancelButton = inputContainer.addChild(new Button("Spiel beenden"));
cancelButton.addClickCommands(source -> ifTopDialog(app::closeApp));
inputContainer.setLocalTranslation(300,500,0);
attachChild(inputContainer);
}
}

View File

@@ -1,158 +0,0 @@
package pp.monopoly.client.gui.popups;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Quad;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.dialog.PopupDialog;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.notification.Sound;
/**
* NoMoneyWarning is a warning popup that informs the player they lack sufficient funds to proceed with an action.
*/
public class NoMoneyWarning extends Dialog implements PopupDialog {
/** Reference to the Monopoly application instance. */
private final MonopolyApp app;
/** Semi-transparent overlay background for the warning popup. */
private final Geometry overlayBackground;
/** Main container for the NoMoneyWarning dialog UI. */
private final Container noMoneyWarningContainer;
/** Background container providing a styled border around the main dialog. */
private final Container backgroundContainer;
/**
* Constructs a new NoMoneyWarning dialog.
*
* @param app The MonopolyApp instance.
*/
public NoMoneyWarning(MonopolyApp app) {
super(app.getDialogManager());
this.app = app;
overlayBackground = createOverlayBackground();
backgroundContainer = createBackgroundContainer();
noMoneyWarningContainer = createNoMoneyWarningContainer();
adjustPaddingAndCenter();
}
/**
* Creates the semi-transparent overlay background.
*
* @return The geometry representing the overlay background.
*/
private Geometry createOverlayBackground() {
Quad quad = new Quad(app.getCamera().getWidth(), app.getCamera().getHeight());
Geometry overlay = new Geometry("Overlay", quad);
Material material = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
material.setColor("Color", new ColorRGBA(0, 0, 0, 0.5f)); // Semi-transparent black
material.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
overlay.setMaterial(material);
overlay.setLocalTranslation(0, 0, 0);
return overlay;
}
/**
* Creates the background container for the dialog.
*
* @return A styled container for the dialog background.
*/
private Container createBackgroundContainer() {
Container container = new Container();
container.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f))); // Light gray
return container;
}
/**
* Creates the main container for the NoMoneyWarning dialog UI.
*
* @return The container for the dialog content.
*/
private Container createNoMoneyWarningContainer() {
Container container = new Container();
container.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f)));
container.setPreferredSize(new Vector3f(550, 250, 10));
// Title
Label title = container.addChild(new Label("Na, schon wieder Pleite?", new ElementId("warning-title")));
title.setFontSize(38);
title.setColor(ColorRGBA.Black);
// Warning message
Container textContainer = container.addChild(new Container());
textContainer.addChild(new Label("Du hast nicht genug Geld, um dieses Gebäude zu kaufen", new ElementId("label-Text")));
textContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
textContainer.setPreferredSize(container.getPreferredSize().addLocal(-250, -200, 0));
// Confirmation button
Button confirmButton = container.addChild(new Button("Bestätigen", new ElementId("button")));
confirmButton.setFontSize(32);
confirmButton.addClickCommands(source -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
close();
}));
return container;
}
/**
* Adjusts the padding and centers the dialog on the screen.
*/
private void adjustPaddingAndCenter() {
float padding = 10;
backgroundContainer.setPreferredSize(noMoneyWarningContainer.getPreferredSize().addLocal(padding, padding, 0));
noMoneyWarningContainer.setLocalTranslation(
(app.getCamera().getWidth() - noMoneyWarningContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + noMoneyWarningContainer.getPreferredSize().y) / 2,
8
);
backgroundContainer.setLocalTranslation(
(app.getCamera().getWidth() - backgroundContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + backgroundContainer.getPreferredSize().y) / 2,
7
);
}
/**
* Displays the dialog by attaching its components to the GUI node.
*/
@Override
public void show() {
app.getGuiNode().attachChild(overlayBackground);
app.getGuiNode().attachChild(backgroundContainer);
app.getGuiNode().attachChild(noMoneyWarningContainer);
}
/**
* Closes the dialog and removes its components from the GUI node.
*/
@Override
public void close() {
app.getGuiNode().detachChild(overlayBackground);
app.getGuiNode().detachChild(backgroundContainer);
app.getGuiNode().detachChild(noMoneyWarningContainer);
super.close();
}
/**
* Handles the escape action to close the dialog.
*/
@Override
public void escape() {
close();
}
}

View File

@@ -1,157 +0,0 @@
package pp.monopoly.client.gui.popups;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Quad;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.dialog.PopupDialog;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.notification.Sound;
/**
* ReceivedRent is a popup that informs a player about rent they have received.
*/
public class ReceivedRent extends Dialog implements PopupDialog {
/** Reference to the Monopoly application instance. */
private final MonopolyApp app;
/** Semi-transparent overlay background for the popup. */
private Geometry overlayBackground;
/** Main container for the rent information and action. */
private Container rentContainer;
/** Background container providing a border for the rent popup. */
private Container backgroundContainer;
/**
* Constructs the ReceivedRent popup displaying the rent amount and payer.
*
* @param app the Monopoly application instance
* @param playerName the name of the player who paid the rent
* @param amount the amount of rent received
*/
public ReceivedRent(MonopolyApp app, String playerName, int amount) {
super(app.getDialogManager());
this.app = app;
// Initialize GUI elements
createOverlayBackground();
createBackgroundContainer();
createRentContainer(playerName, amount);
}
/**
* Creates a semi-transparent overlay background.
*/
private void createOverlayBackground() {
Quad quad = new Quad(app.getCamera().getWidth(), app.getCamera().getHeight());
overlayBackground = new Geometry("Overlay", quad);
Material material = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
material.setColor("Color", new ColorRGBA(0, 0, 0, 0.5f)); // Semi-transparent black
material.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
overlayBackground.setMaterial(material);
overlayBackground.setLocalTranslation(0, 0, 0);
}
/**
* Creates the background container with styling.
*/
private void createBackgroundContainer() {
backgroundContainer = new Container();
backgroundContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f))); // Light gray background
}
/**
* Creates the main rent container with title, text, and button.
*
* @param playerName the name of the player who paid the rent
* @param amount the rent amount
*/
private void createRentContainer(String playerName, int amount) {
rentContainer = new Container();
rentContainer.setBackground(new QuadBackgroundComponent(ColorRGBA.Gray));
rentContainer.setPreferredSize(new Vector3f(550, 250, 10));
// Title
Label title = rentContainer.addChild(new Label("Miete!", new ElementId("warning-title")));
title.setFontSize(48);
title.setColor(ColorRGBA.Black);
// Rent message
Container textContainer = rentContainer.addChild(new Container());
textContainer.addChild(new Label(playerName + " zahlt dir " + amount + " EUR Miete",
new ElementId("label-Text")));
textContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
textContainer.setPreferredSize(rentContainer.getPreferredSize().addLocal(-250, -200, 0));
// Confirmation button
Button confirmButton = rentContainer.addChild(new Button("Bestätigen", new ElementId("button")));
confirmButton.setFontSize(32);
confirmButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
close();
}));
}
/**
* Centers the rent and background containers on the screen.
*/
private void centerContainers() {
float padding = 10;
// Center rent container
rentContainer.setLocalTranslation(
(app.getCamera().getWidth() - rentContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + rentContainer.getPreferredSize().y) / 2,
8
);
// Center background container with padding
backgroundContainer.setPreferredSize(rentContainer.getPreferredSize().addLocal(padding, padding, 0));
backgroundContainer.setLocalTranslation(
(app.getCamera().getWidth() - backgroundContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + backgroundContainer.getPreferredSize().y) / 2,
7
);
}
/**
* Displays the popup by attaching it to the GUI through the DialogManager.
*/
@Override
public void show() {
app.getGuiNode().attachChild(overlayBackground);
app.getGuiNode().attachChild(backgroundContainer);
app.getGuiNode().attachChild(rentContainer);
centerContainers();
}
/**
* Closes the popup and removes GUI elements.
*/
@Override
public void close() {
app.getGuiNode().detachChild(overlayBackground);
app.getGuiNode().detachChild(backgroundContainer);
app.getGuiNode().detachChild(rentContainer);
super.close();
}
/**
* Handles the escape action to close the dialog.
*/
@Override
public void escape() {
close();
}
}

View File

@@ -1,165 +0,0 @@
package pp.monopoly.client.gui.popups;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Quad;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.dialog.PopupDialog;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.message.server.TradeReply;
import pp.monopoly.notification.Sound;
/**
* RejectTrade is a popup that appears when a trade proposal is rejected by another player.
* Displays a message indicating the rejection and provides an option to close the popup.
*/
public class RejectTrade extends Dialog implements PopupDialog {
/** Reference to the Monopoly application instance. */
private final MonopolyApp app;
/** Semi-transparent overlay background for the popup. */
private final Geometry overlayBackground;
/** Main container for the rejection message content. */
private final Container rejectTradeContainer;
/** Background container providing a border for the popup. */
private final Container backgroundContainer;
/**
* Constructs the RejectTrade popup displaying the rejection of a trade proposal.
*
* @param app the Monopoly application instance
* @param msg the trade reply message containing details about the rejected trade
*/
public RejectTrade(MonopolyApp app, TradeReply msg) {
super(app.getDialogManager());
this.app = app;
overlayBackground = createOverlayBackground();
backgroundContainer = createBackgroundContainer();
rejectTradeContainer = createRejectTradeContainer(msg);
adjustPaddingAndCenter();
}
/**
* Creates the semi-transparent background overlay for the popup.
*
* @return the geometry of the overlay
*/
private Geometry createOverlayBackground() {
Quad quad = new Quad(app.getCamera().getWidth(), app.getCamera().getHeight());
Geometry overlay = new Geometry("Overlay", quad);
Material material = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
material.setColor("Color", new ColorRGBA(0, 0, 0, 0.5f)); // Semi-transparent black
material.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
overlay.setMaterial(material);
overlay.setLocalTranslation(0, 0, 0);
return overlay;
}
/**
* Creates the background container for the dialog.
*
* @return A styled container for the dialog background.
*/
private Container createBackgroundContainer() {
Container container = new Container();
container.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f))); // Light gray background
return container;
}
/**
* Creates the main container for the RejectTrade dialog UI.
*
* @param msg the trade reply message containing details about the rejected trade
* @return The container for the rejection message and action button
*/
private Container createRejectTradeContainer(TradeReply msg) {
Container container = new Container();
container.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f)));
container.setPreferredSize(new Vector3f(550, 250, 10));
// Title
Label title = container.addChild(new Label("Handel abgelehnt!", new ElementId("warning-title")));
title.setFontSize(48);
title.setColor(ColorRGBA.Black);
// Rejection message
Container textContainer = container.addChild(new Container());
textContainer.addChild(new Label("Du hast " + msg.getTradeHandler().getReceiver().getName()
+ " einen Handel vorgeschlagen.", new ElementId("label-Text")));
textContainer.addChild(new Label("", new ElementId("label-Text")));
textContainer.addChild(new Label("Der Handel wurde abgelehnt.", new ElementId("label-Text")));
textContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
textContainer.setPreferredSize(container.getPreferredSize().addLocal(-250, -200, 0));
// Confirmation button
Button confirmButton = container.addChild(new Button("Bestätigen", new ElementId("button")));
confirmButton.setFontSize(32);
confirmButton.addClickCommands(source -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
close();
}));
return container;
}
/**
* Adjusts the padding and centers the dialog on the screen.
*/
private void adjustPaddingAndCenter() {
float padding = 10;
backgroundContainer.setPreferredSize(rejectTradeContainer.getPreferredSize().addLocal(padding, padding, 0));
rejectTradeContainer.setLocalTranslation(
(app.getCamera().getWidth() - rejectTradeContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + rejectTradeContainer.getPreferredSize().y) / 2,
8
);
backgroundContainer.setLocalTranslation(
(app.getCamera().getWidth() - backgroundContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + backgroundContainer.getPreferredSize().y) / 2,
7
);
}
/**
* Displays the popup by attaching its elements to the GUI node.
*/
@Override
public void show() {
app.getGuiNode().attachChild(overlayBackground);
app.getGuiNode().attachChild(backgroundContainer);
app.getGuiNode().attachChild(rejectTradeContainer);
}
/**
* Closes the menu and removes the GUI elements.
*/
@Override
public void close() {
app.getGuiNode().detachChild(overlayBackground);
app.getGuiNode().detachChild(backgroundContainer);
app.getGuiNode().detachChild(rejectTradeContainer);
super.close();
}
/**
* Handles the escape key action by closing the popup.
*/
@Override
public void escape() {
close();
}
}

View File

@@ -1,126 +0,0 @@
package pp.monopoly.client.gui.popups;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Quad;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.dialog.PopupDialog;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.notification.Sound;
/**
* Rent is a popup that is triggered when a player lands on a property owned by another player
* and needs to pay rent in the Monopoly application.
* <p>
* Displays the rent amount and the recipient player's name, with an option to confirm the payment.
* </p>
*/
public class Rent extends Dialog implements PopupDialog {
private final MonopolyApp app;
private final Geometry overlayBackground;
private final Container rentContainer;
private final Container backgroundContainer;
public Rent(MonopolyApp app, String playerName, int amount) {
super(app.getDialogManager());
this.app = app;
// Create the overlay and containers
overlayBackground = createOverlayBackground();
backgroundContainer = createBackgroundContainer();
rentContainer = createRentContainer(playerName, amount);
// Center containers (positioning logic only, no GUI attachment)
centerContainers();
}
private Geometry createOverlayBackground() {
Quad quad = new Quad(app.getCamera().getWidth(), app.getCamera().getHeight());
Geometry overlay = new Geometry("Overlay", quad);
Material material = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
material.setColor("Color", new ColorRGBA(0, 0, 0, 0.5f));
material.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
overlay.setMaterial(material);
overlay.setLocalTranslation(0, 0, 0);
return overlay;
}
private Container createBackgroundContainer() {
Container container = new Container();
container.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f)));
return container;
}
private Container createRentContainer(String playerName, int amount) {
Container container = new Container();
container.setBackground(new QuadBackgroundComponent(ColorRGBA.Gray));
container.setPreferredSize(new Vector3f(550, 250, 10));
Label title = container.addChild(new Label("Miete!", new ElementId("warning-title")));
title.setFontSize(48);
title.setColor(ColorRGBA.Black);
Container textContainer = container.addChild(new Container());
textContainer.addChild(new Label("Du musst " + amount + " EUR Miete an " + playerName + " zahlen",
new ElementId("label-Text")));
textContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
textContainer.setPreferredSize(container.getPreferredSize().addLocal(-250, -200, 0));
Button payButton = container.addChild(new Button("Überweisen", new ElementId("button")));
payButton.setFontSize(32);
payButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
close();
}));
return container;
}
private void centerContainers() {
float padding = 10;
rentContainer.setLocalTranslation(
(app.getCamera().getWidth() - rentContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + rentContainer.getPreferredSize().y) / 2,
8
);
backgroundContainer.setPreferredSize(rentContainer.getPreferredSize().addLocal(padding, padding, 0));
backgroundContainer.setLocalTranslation(
(app.getCamera().getWidth() - backgroundContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + backgroundContainer.getPreferredSize().y) / 2,
7
);
}
@Override
public void show() {
// Attach components to GUI only when the dialog is displayed via DialogManager
app.getGuiNode().attachChild(overlayBackground);
app.getGuiNode().attachChild(backgroundContainer);
app.getGuiNode().attachChild(rentContainer);
}
@Override
public void close() {
app.getGuiNode().detachChild(overlayBackground);
app.getGuiNode().detachChild(backgroundContainer);
app.getGuiNode().detachChild(rentContainer);
super.close();
}
@Override
public void escape() {
close();
}
}

View File

@@ -1,251 +0,0 @@
package pp.monopoly.client.gui.popups;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.simsilica.lemur.Axis;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.Selector;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.component.SpringGridLayout;
import com.simsilica.lemur.core.VersionedList;
import com.simsilica.lemur.core.VersionedReference;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.client.gui.SettingsMenu;
import pp.monopoly.game.server.Player;
import pp.monopoly.message.client.AlterProperty;
import pp.monopoly.model.fields.BoardManager;
import pp.monopoly.model.fields.PropertyField;
import pp.monopoly.notification.Sound;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* RepayMortage is a popup that appears when a player selects the "Repay Mortgage" option
* in the Building Administration Menu.
* <p>
* This popup allows the player to select mortgaged properties and repay their mortgages,
* showing the total cost of the repayment. Includes options to confirm or cancel the repayment.
* </p>
*/
public class RepayMortage extends Dialog {
/** Reference to the Monopoly application instance. */
private final MonopolyApp app;
/** Main container for the mortgage repayment menu. */
private final Container repayMortageContainer;
/** Background container providing a border for the popup. */
private final Container backgroundContainer;
/** Label to display selected properties. */
private Label selectionDisplay;
/** Reference to track property selections in the dropdown menu. */
private VersionedReference<Set<Integer>> selectionRef;
/** Dropdown menu for selecting mortgaged properties. */
private Selector<String> propertySelector;
/** Set of selected properties for mortgage repayment. */
private Set<String> selectedProperties = new HashSet<>();
/** Label displaying the total repayment cost. */
private Label cost = new Label("0", new ElementId("label-Text"));
/**
* Constructs the RepayMortage popup for handling mortgage repayment.
*
* @param app the Monopoly application instance
*/
public RepayMortage(MonopolyApp app) {
super(app.getDialogManager());
this.app = app;
// Create the background container
backgroundContainer = new Container();
backgroundContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f))); // Darker background
attachChild(backgroundContainer);
// Hauptcontainer für das Menü
repayMortageContainer = new Container();
repayMortageContainer.setPreferredSize(new Vector3f(800, 600, 0));
float padding = 10; // Passt den backgroundContainer an die Größe des sellhouseContainers an
backgroundContainer.setPreferredSize(repayMortageContainer.getPreferredSize().addLocal(padding, padding, 0));
// Titel
Label title = repayMortageContainer.addChild(new Label( "Hypothek Abbezahlen", new ElementId("label-Bold")));
title.setFontSize(48);
title.setColor(ColorRGBA.Black);
//Unterteilund des sellHouseContainer in drei "Untercontainer"
Container upContainer = repayMortageContainer.addChild(new Container());
Container middleContainer = repayMortageContainer.addChild(new Container());
Container downContainer = repayMortageContainer.addChild(new Container());
// Text, der auf der Karte steht
upContainer.addChild(new Label("„Grundstück wählen:", new ElementId("label-Text")));
upContainer.addChild(new Label("", new ElementId("label-Text")));// Leerzeile
upContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
middleContainer.setPreferredSize(new Vector3f(100, 150, 0));
middleContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.0f, 0.0f, 0.0f, 1.0f)));
middleContainer.addChild(createPropertyDropdown());
downContainer.addChild(new Label("", new ElementId("label-Text")));// Leerzeile
downContainer.addChild(new Label("Kosten:", new ElementId("label-Text")));// Leerzeile
downContainer.addChild(cost);
downContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
// Beenden-Button
Button cancelButton = repayMortageContainer.addChild(new Button("Abbrechen", new ElementId("button")));
cancelButton.setFontSize(32);
cancelButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
close();
}));
// Kaufen-Button
Button confirmButton = repayMortageContainer.addChild(new Button("Bestätigen", new ElementId("button")));
confirmButton.setFontSize(32);
confirmButton.addClickCommands(s -> ifTopDialog( () -> {
app.getGameLogic().playSound(Sound.BUTTON);
AlterProperty msg = new AlterProperty("RepayMortage");
msg.setProperties(selectedProperties.stream().map(p -> app.getGameLogic().getBoardManager().getFieldByName(p).getId()).map(p -> (Integer) p).collect(Collectors.toSet()));
app.getGameLogic().send(msg);
close();
}));
// Zentriere das Popup
repayMortageContainer.setLocalTranslation(
(app.getCamera().getWidth() - repayMortageContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + repayMortageContainer.getPreferredSize().y) / 2,
9
);
// Zentriere das Popup
backgroundContainer.setLocalTranslation(
(app.getCamera().getWidth() - repayMortageContainer.getPreferredSize().x - padding) / 2,
(app.getCamera().getHeight() + repayMortageContainer.getPreferredSize().y+ padding) / 2,
8
);
app.getGuiNode().attachChild(repayMortageContainer);
}
/**
* Creates a dropdown menu for selecting a property.
*
* @return The dropdown container.
*/
private Container createPropertyDropdown() {
Container dropdownContainer = new Container(new SpringGridLayout(Axis.Y, Axis.X));
dropdownContainer.setPreferredSize(new Vector3f(300, 200, 0));
dropdownContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.0f, 0.0f, 0.0f, 1.0f)));
VersionedList<String> propertyOptions = new VersionedList<>();
List<PropertyField> playerProperties = getPlayerProperties();
// Populate the dropdown with property names
for (PropertyField property : playerProperties) {
propertyOptions.add(property.getName());
}
propertySelector = new Selector<>(propertyOptions, "glass");
dropdownContainer.addChild(propertySelector);
// Track selection changes
selectionRef = propertySelector.getSelectionModel().createReference();
// Initialize the selection display here
selectionDisplay = new Label(""); // Create TextField for displaying selections
selectionDisplay.setPreferredSize(new Vector3f(300, 30, 0));
selectionDisplay.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
dropdownContainer.addChild(selectionDisplay); // Add it to the dropdown container
// Set initial selection
if (!propertyOptions.isEmpty()) {
onDropdownSelectionChanged(propertySelector);
}
return dropdownContainer;
}
/**
* Retrieves the list of properties owned by the current player.
*
* @return List of PropertyField objects owned by the player.
*/
private List<PropertyField> getPlayerProperties() {
Player self = app.getGameLogic().getPlayerHandler().getPlayerById(app.getId());
BoardManager boardManager = app.getGameLogic().getBoardManager();
return boardManager.getPropertyFields(self.getProperties()).stream()
.filter(property -> property instanceof PropertyField)
.map(property -> (PropertyField) property)
.filter(p -> p.isMortgaged())
.collect(Collectors.toList());
}
/**
* Updates the UI based on selection changes in the dropdown menu.
*
* @param delta the time elapsed since the last update
*/
@Override
public void update(float delta) {
if(selectionRef.update()) {
onDropdownSelectionChanged(propertySelector);
}
}
/**
* Handles changes in the property selection and updates the total repayment cost.
*
* @param playerProperties the dropdown menu for selecting properties
*/
private void onDropdownSelectionChanged(Selector<String> playerProperties) {
String selected = playerProperties.getSelectedItem();
app.getGameLogic().playSound(Sound.BUTTON);
if (selectedProperties.contains(selected)) {
selectedProperties.remove(selected);
} else {
selectedProperties.add(selected);
}
int cost = 0;
for (String s : selectedProperties) {
cost += ((PropertyField) app.getGameLogic().getBoardManager().getFieldByName(s)).getHypo();
}
String display = String.join(" | ", selectedProperties);
selectionDisplay.setText(display);
this.cost.setText(cost+"");
}
/**
* Closes the popup and removes its associated GUI elements.
*/
@Override
public void close() {
app.getGuiNode().detachChild(repayMortageContainer); // Entferne das Menü
app.getGuiNode().detachChild(backgroundContainer); //Entfernt Rand
super.close();
}
/**
* Opens the settings menu when the escape key is pressed.
*/
@Override
public void escape() {
new SettingsMenu(app).open();
}
}

View File

@@ -1,250 +0,0 @@
package pp.monopoly.client.gui.popups;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.simsilica.lemur.Axis;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.Selector;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.component.SpringGridLayout;
import com.simsilica.lemur.core.VersionedList;
import com.simsilica.lemur.core.VersionedReference;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.client.gui.SettingsMenu;
import pp.monopoly.game.server.Player;
import pp.monopoly.message.client.AlterProperty;
import pp.monopoly.model.fields.BoardManager;
import pp.monopoly.model.fields.BuildingProperty;
import pp.monopoly.notification.Sound;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* SellHouse is a popup that appears when a player clicks on the "Demolish" button
* in the BuildingAdminMenu.
* <p>
* This dialog allows players to select their properties and demolish houses or hotels
* for a partial refund of their purchase cost.
* </p>
*/
public class SellHouse extends Dialog {
/** Reference to the Monopoly application instance. */
private final MonopolyApp app;
/** Main container for the SellHouse dialog UI. */
private final Container sellhouseContainer;
/** Background container providing a styled border around the main dialog. */
private final Container backgroundContainer;
/** Label to display selected properties. */
private Label selectionDisplay;
/** Reference to track selection changes in the property selector. */
private VersionedReference<Set<Integer>> selectionRef;
/** Dropdown selector for displaying available properties. */
private Selector<String> propertySelector;
/** Set of properties selected for selling. */
private Set<String> selectedProperties = new HashSet<>();
/** Label to display the total refund amount for the selected properties. */
private Label cost = new Label("0", new ElementId("label-Text"));
/**
* Constructs a new SellHouse dialog.
*
* @param app The MonopolyApp instance.
*/
public SellHouse(MonopolyApp app) {
super(app.getDialogManager());
this.app = app;
// Create the background container
backgroundContainer = new Container();
backgroundContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f))); // Darker background
attachChild(backgroundContainer);
// Hauptcontainer für das Menü
sellhouseContainer = new Container();
sellhouseContainer.setPreferredSize(new Vector3f(800, 600, 0));
float padding = 10; // Passt den backgroundContainer an die Größe des sellhouseContainers an
backgroundContainer.setPreferredSize(sellhouseContainer.getPreferredSize().addLocal(padding, padding, 0));
// Titel
Label title = sellhouseContainer.addChild(new Label( "Gebäude Abreißen", new ElementId("label-Bold")));
title.setFontSize(48);
title.setColor(ColorRGBA.Black);
//Unterteilung des sellHouseContainer in drei "Untercontainer"
Container upContainer = sellhouseContainer.addChild(new Container());
Container middleContainer = sellhouseContainer.addChild(new Container());
Container downContainer = sellhouseContainer.addChild(new Container());
// Text, der auf der Karte steht
upContainer.addChild(new Label("„Grundstück wählen:", new ElementId("label-Text")));
upContainer.addChild(new Label("", new ElementId("label-Text")));// Leerzeile
upContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
middleContainer.setPreferredSize(new Vector3f(100, 150, 0));
middleContainer.setBackground(new QuadBackgroundComponent(ColorRGBA.Orange));
middleContainer.addChild(createPropertyDropdown());
downContainer.addChild(new Label("", new ElementId("label-Text")));// Leerzeile
downContainer.addChild(new Label("Erstattung:", new ElementId("label-Text")));// Leerzeile
downContainer.addChild(cost); // Cost details
downContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
// Beenden-Button
Button cancelButton = sellhouseContainer.addChild(new Button("Abbrechen", new ElementId("button")));
cancelButton.setFontSize(32);
cancelButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
close();
}));
// Kaufen-Button
Button confirmButton = sellhouseContainer.addChild(new Button("Bestätigen", new ElementId("button")));
confirmButton.setFontSize(32);
confirmButton.addClickCommands(s -> ifTopDialog( () -> {
app.getGameLogic().playSound(Sound.BUTTON);
AlterProperty msg = new AlterProperty("SellHouse");
msg.setProperties(selectedProperties.stream().map(p -> app.getGameLogic().getBoardManager().getFieldByName(p).getId()).map(p -> (Integer) p).collect(Collectors.toSet()));
app.getGameLogic().send(msg);
close();
}));
// Zentriere das Popup
sellhouseContainer.setLocalTranslation(
(app.getCamera().getWidth() - sellhouseContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + sellhouseContainer.getPreferredSize().y) / 2,
9
);
// Zentriere das Popup
backgroundContainer.setLocalTranslation(
(app.getCamera().getWidth() - sellhouseContainer.getPreferredSize().x - padding) / 2,
(app.getCamera().getHeight() + sellhouseContainer.getPreferredSize().y+ padding) / 2,
8
);
app.getGuiNode().attachChild(sellhouseContainer);
}
/**
* Creates a dropdown menu for selecting a property.
*
* @return The dropdown container.
*/
private Container createPropertyDropdown() {
Container dropdownContainer = new Container(new SpringGridLayout(Axis.Y, Axis.X));
dropdownContainer.setPreferredSize(new Vector3f(300, 200, 0));
dropdownContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.0f, 0.0f, 0.0f, 1.0f)));
VersionedList<String> propertyOptions = new VersionedList<>();
List<BuildingProperty> playerProperties = getPlayerProperties();
// Populate the dropdown with property names
for (BuildingProperty property : playerProperties) {
propertyOptions.add(property.getName());
}
propertySelector = new Selector<>(propertyOptions, "glass");
dropdownContainer.addChild(propertySelector);
// Track selection changes
selectionRef = propertySelector.getSelectionModel().createReference();
// Initialize the selection display here
selectionDisplay = new Label("");
selectionDisplay.setPreferredSize(new Vector3f(300, 30, 0));
selectionDisplay.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
dropdownContainer.addChild(selectionDisplay); // Add it to the dropdown container
// Set initial selection
if (!propertyOptions.isEmpty()) {
onDropdownSelectionChanged(propertySelector);
}
return dropdownContainer;
}
/**
* Retrieves the list of properties owned by the current player.
*
* @return List of BuildingProperty objects owned by the player.
*/
private List<BuildingProperty> getPlayerProperties() {
Player self = app.getGameLogic().getPlayerHandler().getPlayerById(app.getId());
BoardManager boardManager = app.getGameLogic().getBoardManager();
return boardManager.getPropertyFields(self.getProperties()).stream()
.filter(property -> property instanceof BuildingProperty)
.map(property -> (BuildingProperty) property)
.filter(p -> app.getGameLogic().getBoardManager().canSell(p))
.collect(Collectors.toList());
}
/**
* Updates the dialog UI, tracking changes in the property selection.
*
* @param delta Time since the last update.
*/
@Override
public void update(float delta) {
if(selectionRef.update()) {
onDropdownSelectionChanged(propertySelector);
}
}
/**
* Handles changes to the property selection.
*
* @param playerProperties The dropdown menu's selection state.
*/
private void onDropdownSelectionChanged(Selector<String> playerProperties) {
String selected = playerProperties.getSelectedItem();
app.getGameLogic().playSound(Sound.BUTTON);
if (selectedProperties.contains(selected)) {
selectedProperties.remove(selected);
} else {
selectedProperties.add(selected);
}
int cost = 0;
for (String s : selectedProperties) {
cost += ((BuildingProperty) app.getGameLogic().getBoardManager().getFieldByName(s)).getHousePrice() / 2;
}
String display = String.join(" | ", selectedProperties);
selectionDisplay.setText(display);
this.cost.setText(cost+"");
}
/**
* Closes the dialog and removes GUI elements from the screen.
*/
@Override
public void close() {
app.getGuiNode().detachChild(sellhouseContainer); // Entferne das Menü
app.getGuiNode().detachChild(backgroundContainer); //Entfernt Rand
super.close();
}
/**
* Handles the escape action to close the dialog.
*/
@Override
public void escape() {
new SettingsMenu(app).open();
}
}

View File

@@ -1,260 +0,0 @@
package pp.monopoly.client.gui.popups;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.simsilica.lemur.Axis;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.Selector;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.component.SpringGridLayout;
import com.simsilica.lemur.core.VersionedList;
import com.simsilica.lemur.core.VersionedReference;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.client.gui.SettingsMenu;
import pp.monopoly.game.server.Player;
import pp.monopoly.message.client.AlterProperty;
import pp.monopoly.model.fields.BoardManager;
import pp.monopoly.model.fields.BuildingProperty;
import pp.monopoly.model.fields.PropertyField;
import pp.monopoly.notification.Sound;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* TakeMortage is a popup that appears when a player clicks on the "Take Mortage" button
* in the BuildingAdminMenu.
* <p>
* This popup allows the player to select properties and take a mortgage on them
* to gain financial benefit during gameplay.
* </p>
*/
public class TakeMortage extends Dialog {
/** Reference to the Monopoly application instance. */
private final MonopolyApp app;
/** Main container for the TakeMortage dialog UI. */
private final Container takeMortageContainer;
/** Background container providing a styled border around the main dialog. */
private final Container backgroundContainer;
/** Label to display selected properties. */
private Label selectionDisplay;
/** Reference to track selection changes in the property selector. */
private VersionedReference<Set<Integer>> selectionRef;
/** Dropdown selector for displaying available properties. */
private Selector<String> propertySelector;
/** Set of properties selected for mortgaging. */
private Set<String> selectedProperties = new HashSet<>();
/** Label to display the total mortgage amount. */
private Label cost = new Label("0", new ElementId("label-Text"));
/**
* Constructs a new TakeMortage dialog.
*
* @param app The MonopolyApp instance.
*/
public TakeMortage(MonopolyApp app) {
super(app.getDialogManager());
this.app = app;
// Create the background container
backgroundContainer = new Container();
backgroundContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f))); // Darker background
attachChild(backgroundContainer);
// Hauptcontainer für das Menü
takeMortageContainer = new Container();
takeMortageContainer.setPreferredSize(new Vector3f(800, 600, 0));
float padding = 10; // Passt den backgroundContainer an die Größe des sellhouseContainers an
backgroundContainer.setPreferredSize(takeMortageContainer.getPreferredSize().addLocal(padding, padding, 0));
// Titel
Label title = takeMortageContainer.addChild(new Label( "Hypothek aufnehmen", new ElementId("label-Bold")));
title.setFontSize(48);
title.setColor(ColorRGBA.Black);
//Unterteilund des sellHouseContainer in drei "Untercontainer"
Container upContainer = takeMortageContainer.addChild(new Container());
Container middleContainer = takeMortageContainer.addChild(new Container());
Container downContainer = takeMortageContainer.addChild(new Container());
// Text, der auf der Karte steht
upContainer.addChild(new Label("„Grundstück wählen:", new ElementId("label-Text")));
upContainer.addChild(new Label("", new ElementId("label-Text")));// Leerzeile
upContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
middleContainer.setPreferredSize(new Vector3f(100, 150, 0));
middleContainer.setBackground(new QuadBackgroundComponent(ColorRGBA.Orange));
middleContainer.addChild(createPropertyDropdown());
downContainer.addChild(new Label("", new ElementId("label-Text")));// Leerzeile
downContainer.addChild(new Label("Erstattung:", new ElementId("label-Text")));// Leerzeile
downContainer.addChild(cost);
downContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
// Beenden-Button
Button cancelButton = takeMortageContainer.addChild(new Button("Abbrechen", new ElementId("button")));
cancelButton.setFontSize(32);
cancelButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
close();
}));
// Kaufen-Button
Button confirmButton = takeMortageContainer.addChild(new Button("Bestätigen", new ElementId("button")));
confirmButton.setFontSize(32);
confirmButton.addClickCommands(s -> ifTopDialog( () -> {
app.getGameLogic().playSound(Sound.BUTTON);
AlterProperty msg = new AlterProperty("TakeMortage");
msg.setProperties(selectedProperties.stream().map(p -> app.getGameLogic().getBoardManager().getFieldByName(p).getId()).map(p -> (Integer) p).collect(Collectors.toSet()));
app.getGameLogic().send(msg);
close();
}));
// Zentriere das Popup
takeMortageContainer.setLocalTranslation(
(app.getCamera().getWidth() - takeMortageContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + takeMortageContainer.getPreferredSize().y) / 2,
9
);
// Zentriere das Popup
backgroundContainer.setLocalTranslation(
(app.getCamera().getWidth() - takeMortageContainer.getPreferredSize().x - padding) / 2,
(app.getCamera().getHeight() + takeMortageContainer.getPreferredSize().y+ padding) / 2,
8
);
app.getGuiNode().attachChild(takeMortageContainer);
}
/**
* Creates a dropdown menu for selecting a property.
*
* @return The dropdown container with property options.
*/
private Container createPropertyDropdown() {
Container dropdownContainer = new Container(new SpringGridLayout(Axis.Y, Axis.X));
dropdownContainer.setPreferredSize(new Vector3f(300, 200, 0));
dropdownContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.0f, 0.0f, 0.0f, 1.0f)));
VersionedList<String> propertyOptions = new VersionedList<>();
List<PropertyField> playerProperties = getPlayerProperties();
// Populate the dropdown with property names
for (PropertyField property : playerProperties) {
if(property instanceof BuildingProperty) {
if (((BuildingProperty)property).getHouses()!=0) {
break;
}
}
propertyOptions.add(property.getName());
}
propertySelector = new Selector<>(propertyOptions, "glass");
dropdownContainer.addChild(propertySelector);
// Track selection changes
selectionRef = propertySelector.getSelectionModel().createReference();
// Initialize the selection display here
selectionDisplay = new Label(""); // Create TextField for displaying selections
selectionDisplay.setPreferredSize(new Vector3f(300, 30, 0));
selectionDisplay.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
dropdownContainer.addChild(selectionDisplay); // Add it to the dropdown container
// Set initial selection
if (!propertyOptions.isEmpty()) {
onDropdownSelectionChanged(propertySelector);
}
return dropdownContainer;
}
/**
* Retrieves the list of properties owned by the current player.
* <p>
* Only properties that are not currently mortgaged are included.
* </p>
*
* @return List of eligible PropertyField objects owned by the player.
*/
private List<PropertyField> getPlayerProperties() {
Player self = app.getGameLogic().getPlayerHandler().getPlayerById(app.getId());
BoardManager boardManager = app.getGameLogic().getBoardManager();
return boardManager.getPropertyFields(self.getProperties()).stream()
.filter(property -> property instanceof PropertyField)
.map(property -> (PropertyField) property)
.filter(p -> !p.isMortgaged())
.collect(Collectors.toList());
}
/**
* Updates the dialog UI, tracking changes in the property selection.
*
* @param delta Time since the last update.
*/
@Override
public void update(float delta) {
if(selectionRef.update()) {
onDropdownSelectionChanged(propertySelector);
}
}
/**
* Handles changes to the property selection.
*
* @param playerProperties The dropdown menu's selection state.
*/
private void onDropdownSelectionChanged(Selector<String> playerProperties) {
String selected = playerProperties.getSelectedItem();
app.getGameLogic().playSound(Sound.BUTTON);
if (selectedProperties.contains(selected)) {
selectedProperties.remove(selected);
} else {
selectedProperties.add(selected);
}
int cost = 0;
for (String s : selectedProperties) {
cost += ((PropertyField) app.getGameLogic().getBoardManager().getFieldByName(s)).getHypo();
}
String display = String.join(" | ", selectedProperties);
selectionDisplay.setText(display);
this.cost.setText(cost+"");
}
/**
* Closes the dialog and removes GUI elements from the screen.
*/
@Override
public void close() {
app.getGuiNode().detachChild(takeMortageContainer); // Entferne das Menü
app.getGuiNode().detachChild(backgroundContainer); //Entfernt Rand
super.close();
}
/**
* Handles the escape action to close the dialog.
*/
@Override
public void escape() {
new SettingsMenu(app).open();
}
}

View File

@@ -1,139 +0,0 @@
package pp.monopoly.client.gui.popups;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Quad;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.notification.Sound;
/**
* TimeOut is a warning popup triggered when the connection to the server is interrupted.
* <p>
* This popup informs the user about the loss of connection and provides an option to acknowledge it.
* </p>
*/
public class TimeOut extends Dialog {
/** Reference to the Monopoly application instance. */
private final MonopolyApp app;
/** Semi-transparent overlay background for the dialog. */
private final Geometry overlayBackground;
/** Main container for the TimeOut dialog UI. */
private final Container timeOutContainer;
/** Background container providing a styled border around the main dialog. */
private final Container backgroundContainer;
/**
* Constructs a new TimeOut dialog to notify the user about a connection loss.
*
* @param app The MonopolyApp instance.
*/
public TimeOut(MonopolyApp app) {
super(app.getDialogManager());
this.app = app;
// Halbtransparentes Overlay hinzufügen
overlayBackground = createOverlayBackground();
app.getGuiNode().attachChild(overlayBackground);
// Create the background container
backgroundContainer = new Container();
backgroundContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f))); // Darker background
app.getGuiNode().attachChild(backgroundContainer);
// Hauptcontainer für die Warnung
timeOutContainer = new Container();
timeOutContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f)));
timeOutContainer.setPreferredSize(new Vector3f(550,250,10));
float padding = 10; // Passt den backgroundContainer an die Größe des bankruptContainers an
backgroundContainer.setPreferredSize(timeOutContainer.getPreferredSize().addLocal(padding, padding, 0));
// Titel
Label gateFieldTitle = timeOutContainer.addChild(new Label("Vorsicht !", new ElementId("warning-title")));
gateFieldTitle.setFontSize(48);
gateFieldTitle.setColor(ColorRGBA.Black);
// Text, der auf der Karte steht
Container textContainer = timeOutContainer.addChild(new Container());
textContainer.addChild(new Label("Du hast die Verbindung verloren und kannst nichts dagegen machen. Akzeptiere einfach, dass du verloren hast!", new ElementId("label-Text")));
textContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
textContainer.setPreferredSize(timeOutContainer.getPreferredSize().addLocal(-250,-200,0));
// Beenden-Button
Button quitButton = timeOutContainer.addChild(new Button("Bestätigen", new ElementId("button")));
quitButton.setFontSize(32);
quitButton.addClickCommands(source -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
close();
}));
// Zentriere das Popup
timeOutContainer.setLocalTranslation(
(app.getCamera().getWidth() - timeOutContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + timeOutContainer.getPreferredSize().y) / 2,
8
);
// Zentriere das Popup
backgroundContainer.setLocalTranslation(
(app.getCamera().getWidth() - timeOutContainer.getPreferredSize().x - padding) / 2,
(app.getCamera().getHeight() + timeOutContainer.getPreferredSize().y+ padding) / 2,
7
);
app.getGuiNode().attachChild(timeOutContainer);
}
/**
* Creates a semi-transparent background overlay for the popup.
*
* @return The overlay geometry.
*/
private Geometry createOverlayBackground() {
Quad quad = new Quad(app.getCamera().getWidth(), app.getCamera().getHeight());
Geometry overlay = new Geometry("Overlay", quad);
Material material = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
material.setColor("Color", new ColorRGBA(0, 0, 0, 0.5f)); // Halbtransparent
material.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
overlay.setMaterial(material);
overlay.setLocalTranslation(0, 0, 0);
return overlay;
}
/**
* Closes the TimeOut dialog and removes its GUI elements.
*/
@Override
public void close() {
app.getGuiNode().detachChild(timeOutContainer); // Entferne das Menü
app.getGuiNode().detachChild(backgroundContainer); //Entfernt Rand
app.getGuiNode().detachChild(overlayBackground); // Entferne das Overlay
super.close();
}
/**
* Handles the escape action to close the dialog.
*/
@Override
public void escape() {
close();
}
}

View File

@@ -1,143 +1,51 @@
package pp.monopoly.client.gui.popups;
import com.jme3.material.Material;
import com.jme3.material.RenderState;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Quad;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.component.IconComponent;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.notification.Sound;
/**
* WinnerPopUp is a dialog displayed when a player wins the Monopoly game.
* <p>
* This popup congratulates the player for their victory and provides an option to quit the game.
* </p>
*/
public class WinnerPopUp extends Dialog {
/** Reference to the Monopoly application instance. */
private final MonopolyApp app;
/** Semi-transparent overlay background for the dialog. */
private final Geometry overlayBackground;
/** Main container for the "Winner" dialog UI. */
private final Container WinnerContainer;
/** Background container providing a styled border around the main dialog. */
private final Container backgroundContainer;
/**
* Constructs a new WinnerPopUp dialog.
* Constructs a new NetworkDialog.
*
* @param app The MonopolyApp instance.
* @param app The NetworkSupport instance to be used for network operations.
*/
public WinnerPopUp(MonopolyApp app) {
super(app.getDialogManager());
this.app = app;
initializeDialog();
}
/**
* Initializes the dialog with input fields and connection buttons.
*/
private void initializeDialog() {
Container inputContainer = new Container();
// Halbtransparentes Overlay hinzufügen
overlayBackground = createOverlayBackground();
app.getGuiNode().attachChild(overlayBackground);
// Titel und Eingabefelder für Host und Port
inputContainer.addChild(new Label("Herlichen Glückwunsch!"));
inputContainer.addChild(new Label("Du,bist der Monopoly Champion!!!"));
// Create the background container
backgroundContainer = new Container();
backgroundContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f))); // Darker background
app.getGuiNode().attachChild(backgroundContainer);
// Hauptcontainer für die Warnung
WinnerContainer = new Container();
WinnerContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f)));
WinnerContainer.setPreferredSize(new Vector3f(440,600,10));
float padding = 10; // Passt den backgroundContainer an die Größe des bankruptContainers an
backgroundContainer.setPreferredSize(WinnerContainer.getPreferredSize().addLocal(padding, padding, 0));
// Titel
Label winnerTitle = WinnerContainer.addChild(new Label("Herzlichen Glückwunsch, du bist der neue Monopoly Champion!", new ElementId("header")));
winnerTitle.setFontSize(25);
// winnerTitle.setColor(ColorRGBA.Black);
// Create the image container
Container imageContainer = WinnerContainer.addChild(new Container());
imageContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f))); // Dark gray background
imageContainer.setPreferredSize(WinnerContainer.getPreferredSize().addLocal(-250, -200, 0)); // Adjust size for layout
// Add the image to the container
Label imageLabel = new Label(""); // Create a label for the image
IconComponent icon = new IconComponent("Pictures/MonopolyWinner.png"); // Load the image as an icon
icon.setIconScale(1); // Scale the image appropriately
Label imageLabel = new Label("");
IconComponent icon = new IconComponent("Pictures/MonopolyWinner.png"); // Icon mit Textur erstellen
icon.setIconScale(1); // Skalierung des Bildes
imageLabel.setIcon(icon);
imageContainer.addChild(imageLabel); // Add the image label to the container
// Setze das Icon im Label
inputContainer.addChild(imageLabel);
Button quitButton = WinnerContainer.addChild(new Button("Spiel Beenden", new ElementId("button")));
quitButton.setFontSize(32);
quitButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
app.closeApp();
}));
Button cancelButton = inputContainer.addChild(new Button("Spiel beenden"));
cancelButton.addClickCommands(source -> ifTopDialog(app::closeApp));
// Zentriere das Popup
WinnerContainer.setLocalTranslation(
(app.getCamera().getWidth() - WinnerContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + WinnerContainer.getPreferredSize().y) / 2,
8
);
// Zentriere das Popup
backgroundContainer.setLocalTranslation(
(app.getCamera().getWidth() - WinnerContainer.getPreferredSize().x - padding) / 2,
(app.getCamera().getHeight() + WinnerContainer.getPreferredSize().y+ padding) / 2,
7
);
app.getGuiNode().attachChild(WinnerContainer);
inputContainer.setLocalTranslation(300, 800, 0);
app.getGuiNode().attachChild(inputContainer);
}
/**
* Creates a semi-transparent background overlay for the popup.
*
* @return The overlay geometry.
*/
private Geometry createOverlayBackground() {
Quad quad = new Quad(app.getCamera().getWidth(), app.getCamera().getHeight());
Geometry overlay = new Geometry("Overlay", quad);
Material material = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
material.setColor("Color", new ColorRGBA(0, 0, 0, 0.5f)); // Halbtransparent
material.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
overlay.setMaterial(material);
overlay.setLocalTranslation(0, 0, 0);
return overlay;
}
/**
* Closes the WinnerPopUp dialog and removes its GUI elements.
*/
@Override
public void close() {
app.getGuiNode().detachChild(WinnerContainer); // Entferne das Menü
app.getGuiNode().detachChild(backgroundContainer); //Entfernt Rand
app.getGuiNode().detachChild(overlayBackground); // Entferne das Overlay
super.close();
}
/**
* Handles the escape action to close the dialog.
*/
@Override
public void escape() {
close();
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 473 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Some files were not shown because too many files have changed in this diff Show More