diff --git a/source/core/assets/images/spanner.png b/source/core/assets/images/spanner.png new file mode 100644 index 000000000..d5b7acbf1 Binary files /dev/null and b/source/core/assets/images/spanner.png differ diff --git a/source/core/assets/images/turret-select/droid-tower-selected.png b/source/core/assets/images/turret-select/droid-tower-selected.png new file mode 100644 index 000000000..f08c574bc Binary files /dev/null and b/source/core/assets/images/turret-select/droid-tower-selected.png differ diff --git a/source/core/assets/images/turret-select/fire-tower-clicked.png b/source/core/assets/images/turret-select/fire-tower-clicked.png deleted file mode 100644 index ce1969010..000000000 Binary files a/source/core/assets/images/turret-select/fire-tower-clicked.png and /dev/null differ diff --git a/source/core/assets/images/turret-select/fire-tower-selected.png b/source/core/assets/images/turret-select/fire-tower-selected.png new file mode 100644 index 000000000..029fa1391 Binary files /dev/null and b/source/core/assets/images/turret-select/fire-tower-selected.png differ diff --git a/source/core/assets/images/turret-select/firework-tower-default.png b/source/core/assets/images/turret-select/firework-tower-default.png new file mode 100644 index 000000000..666995a7a Binary files /dev/null and b/source/core/assets/images/turret-select/firework-tower-default.png differ diff --git a/source/core/assets/images/turret-select/firework-tower-selected.png b/source/core/assets/images/turret-select/firework-tower-selected.png new file mode 100644 index 000000000..a047f5688 Binary files /dev/null and b/source/core/assets/images/turret-select/firework-tower-selected.png differ diff --git a/source/core/assets/images/turret-select/mine-tower-selected.png b/source/core/assets/images/turret-select/mine-tower-selected.png new file mode 100644 index 000000000..072186dc7 Binary files /dev/null and b/source/core/assets/images/turret-select/mine-tower-selected.png differ diff --git a/source/core/assets/images/turret-select/pierce-tower-default.png b/source/core/assets/images/turret-select/pierce-tower-default.png new file mode 100644 index 000000000..79534f699 Binary files /dev/null and b/source/core/assets/images/turret-select/pierce-tower-default.png differ diff --git a/source/core/assets/images/turret-select/pierce-tower-selected.png b/source/core/assets/images/turret-select/pierce-tower-selected.png new file mode 100644 index 000000000..5d376fce5 Binary files /dev/null and b/source/core/assets/images/turret-select/pierce-tower-selected.png differ diff --git a/source/core/assets/images/turret-select/ricochet-tower-default.png b/source/core/assets/images/turret-select/ricochet-tower-default.png new file mode 100644 index 000000000..882a58ce0 Binary files /dev/null and b/source/core/assets/images/turret-select/ricochet-tower-default.png differ diff --git a/source/core/assets/images/turret-select/ricochet-tower-selected.png b/source/core/assets/images/turret-select/ricochet-tower-selected.png new file mode 100644 index 000000000..2a837e0e5 Binary files /dev/null and b/source/core/assets/images/turret-select/ricochet-tower-selected.png differ diff --git a/source/core/assets/images/turret-select/stun-tower-selected.png b/source/core/assets/images/turret-select/stun-tower-selected.png new file mode 100644 index 000000000..52eef1443 Binary files /dev/null and b/source/core/assets/images/turret-select/stun-tower-selected.png differ diff --git a/source/core/assets/images/turret-select/tnt-tower-selected.png b/source/core/assets/images/turret-select/tnt-tower-selected.png new file mode 100644 index 000000000..bc6b58873 Binary files /dev/null and b/source/core/assets/images/turret-select/tnt-tower-selected.png differ diff --git a/source/core/assets/images/turret-select/wall-tower-default.png b/source/core/assets/images/turret-select/wall-tower-default.png index bc7ba42f8..059e51602 100644 Binary files a/source/core/assets/images/turret-select/wall-tower-default.png and b/source/core/assets/images/turret-select/wall-tower-default.png differ diff --git a/source/core/assets/images/turret-select/wall-tower-selected.png b/source/core/assets/images/turret-select/wall-tower-selected.png new file mode 100644 index 000000000..4d6564c3a Binary files /dev/null and b/source/core/assets/images/turret-select/wall-tower-selected.png differ diff --git a/source/core/assets/images/turret-select/weapon-tower-selected.png b/source/core/assets/images/turret-select/weapon-tower-selected.png new file mode 100644 index 000000000..f9e319656 Binary files /dev/null and b/source/core/assets/images/turret-select/weapon-tower-selected.png differ diff --git a/source/core/assets/images/ui/buttons/glass.atlas b/source/core/assets/images/ui/buttons/glass.atlas index 4a7987fe5..3e095821f 100644 --- a/source/core/assets/images/ui/buttons/glass.atlas +++ b/source/core/assets/images/ui/buttons/glass.atlas @@ -6,693 +6,714 @@ filter: Linear, Linear repeat: none dot_gothic_16 rotate: false - xy: 1, 989 + xy: 1, 979 size: 505, 107 orig: 505, 107 offset: 0, 0 index: -1 dot_gothic_32 rotate: false - xy: 509, 1527 + xy: 509, 1517 size: 505, 240 orig: 505, 240 offset: 0, 0 index: -1 Emulogic-zrEw rotate: false - xy: 1, 763 + xy: 1, 753 size: 505, 224 orig: 505, 224 offset: 0, 0 index: -1 determination_mono_18 rotate: false - xy: 1525, 1974 + xy: 1525, 1964 size: 505, 64 orig: 505, 64 offset: 0, 0 index: -1 determination_mono_18_bold rotate: false - xy: 509, 1769 + xy: 509, 1759 size: 506, 106 orig: 506, 106 offset: 0, 0 index: -1 determination_mono_22 rotate: false - xy: 1017, 1949 + xy: 1017, 1939 size: 506, 89 orig: 506, 89 offset: 0, 0 index: -1 determination_mono_32 rotate: false - xy: 509, 1380 + xy: 509, 1370 size: 503, 145 orig: 503, 145 offset: 0, 0 index: -1 determination_mono_48_title rotate: false - xy: 1, 1642 + xy: 1, 1632 size: 506, 396 orig: 506, 396 offset: 0, 0 index: -1 emulogic_18 rotate: false - xy: 1017, 1850 + xy: 1017, 1840 size: 505, 97 orig: 505, 97 offset: 0, 0 index: -1 game_paused_24 rotate: false - xy: 1, 1587 + xy: 1, 1577 size: 506, 53 orig: 506, 53 offset: 0, 0 index: -1 game_paused_title rotate: false - xy: 1, 657 + xy: 1, 647 size: 502, 104 orig: 502, 104 offset: 0, 0 index: -1 glitch_24 rotate: false - xy: 509, 1877 + xy: 509, 1867 size: 506, 161 orig: 506, 161 offset: 0, 0 index: -1 glitch_title rotate: false - xy: 1, 1098 + xy: 1, 1088 size: 506, 487 orig: 506, 487 offset: 0, 0 index: -1 UI_Glass_Arrow_Large_01a rotate: false - xy: 965, 1346 + xy: 965, 1336 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Arrow_Medium_01a rotate: false - xy: 99, 167 + xy: 457, 613 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Arrow_Small_01a rotate: false - xy: 251, 319 + xy: 403, 461 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Banner_01a rotate: false - xy: 1017, 1816 + xy: 1017, 1806 size: 96, 32 orig: 96, 32 offset: 0, 0 index: -1 UI_Glass_Banner_01b rotate: false - xy: 403, 589 + xy: 99, 5 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Textfield_01a rotate: false - xy: 403, 589 + xy: 99, 5 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Button_Large_Lock_01a1 rotate: false - xy: 509, 1194 + xy: 509, 1184 size: 96, 32 orig: 96, 32 offset: 0, 0 index: -1 UI_Glass_Button_Large_Release_01a3 rotate: false - xy: 509, 1194 + xy: 509, 1184 size: 96, 32 orig: 96, 32 offset: 0, 0 index: -1 UI_Glass_Button_Large_Lock_01a2 rotate: false - xy: 305, 623 + xy: 305, 461 size: 96, 32 orig: 96, 32 offset: 0, 0 index: -1 UI_Glass_Button_Large_Release_01a2 rotate: false - xy: 305, 623 + xy: 305, 461 size: 96, 32 orig: 96, 32 offset: 0, 0 index: -1 UI_Glass_Button_Large_Lock_01a3 rotate: false - xy: 1, 167 + xy: 1, 5 size: 96, 32 orig: 96, 32 offset: 0, 0 index: -1 UI_Glass_Button_Large_Release_01a1 rotate: false - xy: 1, 167 + xy: 1, 5 size: 96, 32 orig: 96, 32 offset: 0, 0 index: -1 UI_Glass_Button_Large_Lock_01a4 rotate: false - xy: 153, 319 + xy: 153, 157 size: 96, 32 orig: 96, 32 offset: 0, 0 index: -1 UI_Glass_Button_Large_Press_01a1 rotate: false - xy: 1017, 1782 + xy: 1017, 1772 size: 96, 32 orig: 96, 32 offset: 0, 0 index: -1 UI_Glass_Button_Large_Press_01a2 rotate: false - xy: 1115, 1816 + xy: 1115, 1806 size: 96, 32 orig: 96, 32 offset: 0, 0 index: -1 UI_Glass_Button_Large_Press_01a3 rotate: false - xy: 509, 1160 + xy: 509, 1150 size: 96, 32 orig: 96, 32 offset: 0, 0 index: -1 UI_Glass_Button_Large_Press_01a4 rotate: false - xy: 607, 1194 + xy: 607, 1184 size: 96, 32 orig: 96, 32 offset: 0, 0 index: -1 UI_Glass_Button_Large_Release_01a4 rotate: false - xy: 607, 1194 + xy: 607, 1184 size: 96, 32 orig: 96, 32 offset: 0, 0 index: -1 UI_Glass_Button_Medium_Lock_01a1 rotate: false - xy: 403, 623 + xy: 1115, 1772 size: 64, 32 orig: 64, 32 offset: 0, 0 index: -1 UI_Glass_Button_Medium_Release_01a3 rotate: false - xy: 403, 623 + xy: 1115, 1772 size: 64, 32 orig: 64, 32 offset: 0, 0 index: -1 UI_Glass_Button_Medium_Lock_01a2 rotate: false - xy: 1115, 1782 + xy: 1213, 1806 size: 64, 32 orig: 64, 32 offset: 0, 0 index: -1 UI_Glass_Button_Medium_Release_01a2 rotate: false - xy: 1115, 1782 + xy: 1213, 1806 size: 64, 32 orig: 64, 32 offset: 0, 0 index: -1 UI_Glass_Button_Medium_Lock_01a3 rotate: false - xy: 1213, 1816 + xy: 509, 1116 size: 64, 32 orig: 64, 32 offset: 0, 0 index: -1 UI_Glass_Button_Medium_Release_01a1 rotate: false - xy: 1213, 1816 + xy: 509, 1116 size: 64, 32 orig: 64, 32 offset: 0, 0 index: -1 UI_Glass_Button_Medium_Lock_01a4 rotate: false - xy: 509, 1126 + xy: 607, 1150 size: 64, 32 orig: 64, 32 offset: 0, 0 index: -1 UI_Glass_Button_Medium_Press_01a1 rotate: false - xy: 607, 1160 + xy: 705, 1184 size: 64, 32 orig: 64, 32 offset: 0, 0 index: -1 UI_Glass_Button_Medium_Press_01a2 rotate: false - xy: 705, 1194 + xy: 305, 295 size: 64, 32 orig: 64, 32 offset: 0, 0 index: -1 UI_Glass_Button_Medium_Press_01a3 rotate: false - xy: 305, 555 + xy: 1181, 1772 size: 64, 32 orig: 64, 32 offset: 0, 0 index: -1 UI_Glass_Button_Medium_Press_01a4 rotate: false - xy: 1, 35 + xy: 1279, 1806 size: 64, 32 orig: 64, 32 offset: 0, 0 index: -1 UI_Glass_Button_Medium_Release_01a4 rotate: false - xy: 1, 35 + xy: 1279, 1806 size: 64, 32 orig: 64, 32 offset: 0, 0 index: -1 UI_Glass_Button_Small_Lock_01a1 _1 rotate: false - xy: 469, 623 + xy: 251, 157 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Button_Small_Release_01a3 rotate: false - xy: 469, 623 + xy: 251, 157 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Button_Small_Lock_01a2_2 rotate: false - xy: 1181, 1782 + xy: 575, 1116 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Button_Small_Release_01a2 rotate: false - xy: 1181, 1782 + xy: 575, 1116 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Button_Small_Lock_01a3_3 rotate: false - xy: 1279, 1816 + xy: 673, 1150 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Button_Small_Release_01a1 rotate: false - xy: 1279, 1816 + xy: 673, 1150 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Button_Small_Lock_01a4_4 rotate: false - xy: 575, 1126 + xy: 771, 1184 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Button_Small_Press_01a1_ rotate: false - xy: 673, 1160 + xy: 305, 261 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Button_Small_Press_01a2 rotate: false - xy: 771, 1194 + xy: 1247, 1772 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Button_Small_Press_01a3 rotate: false - xy: 305, 521 + xy: 1345, 1806 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Button_Small_Press_01a4 rotate: false - xy: 371, 555 + xy: 965, 1302 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Button_Small_Release_01a4 rotate: false - xy: 371, 555 + xy: 965, 1302 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Checkmark_Large_01a rotate: false - xy: 1, 1 + xy: 457, 579 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Checkmark_Medium_01a rotate: false - xy: 965, 1312 + xy: 403, 427 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Checkmark_Small_01a rotate: false - xy: 99, 133 + xy: 251, 123 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Cross_Large_01a rotate: false - xy: 251, 285 + xy: 609, 1116 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Cross_Medium_01a rotate: false - xy: 437, 589 + xy: 707, 1150 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Cross_Small_01a rotate: false - xy: 1215, 1782 + xy: 805, 1184 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Dropdown_01a rotate: false - xy: 1313, 1816 + xy: 305, 227 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Dropdown_Handle_01a rotate: false - xy: 609, 1126 + xy: 1281, 1772 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Fillbar_01a rotate: false - xy: 707, 1160 + xy: 1379, 1806 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Fillbar_Filler_01a rotate: false - xy: 805, 1194 + xy: 965, 1268 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Frame_Horizontal_01a rotate: false - xy: 305, 589 + xy: 305, 427 size: 96, 32 orig: 96, 32 offset: 0, 0 index: -1 UI_Glass_Frame_Inward_01a rotate: false - xy: 1, 69 + xy: 153, 59 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 UI_Glass_Frame_Lite_01a rotate: false - xy: 305, 487 + xy: 457, 545 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Frame_Standard_01a rotate: false - xy: 153, 221 + xy: 305, 329 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 UI_Glass_Frame_Vertical_01a rotate: false - xy: 305, 389 + xy: 403, 329 size: 32, 96 orig: 32, 96 offset: 0, 0 index: -1 UI_Glass_Minus_Large_01a rotate: false - xy: 339, 521 + xy: 371, 295 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Minus_Medium_01a rotate: false - xy: 405, 555 + xy: 339, 261 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Minus_Small_01a rotate: false - xy: 965, 1278 + xy: 251, 89 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Plus_Large_01a rotate: false - xy: 99, 99 + xy: 643, 1116 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Plus_Medium_01a rotate: false - xy: 251, 251 + xy: 741, 1150 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Plus_Small_01a rotate: false - xy: 1249, 1782 + xy: 839, 1184 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Scrollbar_01a rotate: false - xy: 1347, 1816 + xy: 305, 193 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Scrollbar_Handle_01a rotate: false - xy: 643, 1126 + xy: 1315, 1772 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Select_01a1 rotate: false - xy: 741, 1160 + xy: 1413, 1806 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Select_01a2 rotate: false - xy: 839, 1194 + xy: 965, 1234 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Select_01a4 rotate: false - xy: 839, 1194 + xy: 965, 1234 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Select_01a3 rotate: false - xy: 305, 355 + xy: 457, 511 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Slider_01a rotate: false - xy: 339, 487 + xy: 339, 227 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Slider_Filler_01a rotate: false - xy: 373, 521 + xy: 677, 1116 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Slider_Handle_01a rotate: false - xy: 965, 1244 + xy: 775, 1150 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Slot_Available_01a rotate: false - xy: 1283, 1782 + xy: 873, 1184 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Slot_Selected_01a rotate: false - xy: 1381, 1816 + xy: 1349, 1772 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Slot_Unavailable_01a rotate: false - xy: 677, 1126 + xy: 1447, 1806 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Toggle_Bar_01a rotate: false - xy: 775, 1160 + xy: 339, 193 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Toggle_Cover_01a rotate: false - xy: 873, 1194 + xy: 711, 1116 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 UI_Glass_Toggle_Handle_01a rotate: false - xy: 339, 453 + xy: 809, 1150 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 Weapon-Tower-Default rotate: false - xy: 153, 353 + xy: 153, 343 size: 150, 150 orig: 150, 150 offset: 0, 0 index: -1 droid-tower-default rotate: false - xy: 509, 1228 + xy: 509, 1218 size: 150, 150 orig: 150, 150 offset: 0, 0 index: -1 fire-tower-default rotate: false - xy: 1, 505 + xy: 1, 495 + size: 150, 150 + orig: 150, 150 + offset: 0, 0 + index: -1 +firework-tower-default + rotate: false + xy: 153, 191 size: 150, 150 orig: 150, 150 offset: 0, 0 index: -1 imageedit_2_8132799771 rotate: false - xy: 661, 1228 + xy: 661, 1218 size: 150, 150 orig: 150, 150 offset: 0, 0 index: -1 mine-tower-default rotate: false - xy: 1, 353 + xy: 1, 343 + size: 150, 150 + orig: 150, 150 + offset: 0, 0 + index: -1 +pierce-tower-default + rotate: false + xy: 305, 495 + size: 150, 150 + orig: 150, 150 + offset: 0, 0 + index: -1 +ricochet-tower-default + rotate: false + xy: 1, 39 size: 150, 150 orig: 150, 150 offset: 0, 0 index: -1 stun-tower-default rotate: false - xy: 153, 505 + xy: 153, 495 size: 150, 150 orig: 150, 150 offset: 0, 0 index: -1 tnt-tower-default rotate: false - xy: 813, 1228 + xy: 813, 1218 size: 150, 150 orig: 150, 150 offset: 0, 0 index: -1 wall-tower-default rotate: false - xy: 1, 201 + xy: 1, 191 size: 150, 150 orig: 150, 150 offset: 0, 0 diff --git a/source/core/assets/images/ui/buttons/glass.json b/source/core/assets/images/ui/buttons/glass.json index 8637af19f..77582a6c8 100644 --- a/source/core/assets/images/ui/buttons/glass.json +++ b/source/core/assets/images/ui/buttons/glass.json @@ -301,6 +301,87 @@ com.badlogic.gdx.scenes.scene2d.ui.Skin$TintedDrawable: { a: 1 } } + pierce_tower_selected: { + name: pierce-tower-default + color: { + r: 0 + g: 0.74509805 + b: 0.003921569 + a: 1 + } + } + ricochet_tower_selected: { + name: ricochet-tower-default + color: { + r: 0 + g: 0.74509805 + b: 0.003921569 + a: 1 + } + } + firework_tower_selected: { + name: firework-tower-default + color: { + r: 0 + g: 0.74509805 + b: 0.003921569 + a: 1 + } + } + pierce_tower_disabled: { + name: pierce-tower-default + color: { + r: 0.8156863 + g: 0 + b: 0 + a: 1 + } + } + ricochet_tower_disabled: { + name: ricochet-tower-default + color: { + r: 0.8156863 + g: 0 + b: 0 + a: 1 + } + } + firework_tower_disabled: { + name: firework-tower-default + color: { + r: 0.8156863 + g: 0 + b: 0 + a: 1 + } + } + pierce_tower_over: { + name: pierce-tower-default + color: { + r: 0 + g: 0.9137255 + b: 0.9843137 + a: 1 + } + } + ricochet_tower_over: { + name: ricochet-tower-default + color: { + r: 0 + g: 0.9137255 + b: 0.9843137 + a: 1 + } + } + firework_tower_over: { + name: firework-tower-default + color: { + r: 0 + g: 0.9137255 + b: 0.9843137 + a: 1 + } + } } com.badlogic.gdx.scenes.scene2d.ui.Button$ButtonStyle: { default: { @@ -396,6 +477,24 @@ com.badlogic.gdx.scenes.scene2d.ui.ImageButton$ImageButtonStyle: { imageCheckedDown: mine_tower_down imageCheckedOver: mine_tower_over } + pierce_tower: { + imageUp: pierce-tower-default + imageDown: pierce_tower_selected + imageOver: pierce_tower_over + imageDisabled: pierce_tower_disabled + } + ricochet_tower: { + imageUp: ricochet-tower-default + imageDown: ricochet_tower_selected + imageOver: ricochet_tower_over + imageDisabled: ricochet_tower_disabled + } + fireworks_tower: { + imageUp: firework-tower-default + imageDown: firework_tower_selected + imageOver: firework_tower_over + imageDisabled: firework_tower_disabled + } } com.badlogic.gdx.scenes.scene2d.ui.Label$LabelStyle: { default: { diff --git a/source/core/assets/images/ui/buttons/glass.png b/source/core/assets/images/ui/buttons/glass.png index 57c85ace2..d0a06883c 100644 Binary files a/source/core/assets/images/ui/buttons/glass.png and b/source/core/assets/images/ui/buttons/glass.png differ diff --git a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java index ab760cf1f..8fccaf74b 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -206,9 +206,9 @@ public class ForestGameArea extends GameArea { "sounds/mobs/archerArrow.mp3" }; - private static final String backgroundMusic = "sounds/background/Sci-Fi1.ogg"; + private static final String BACKGROUND_MUSIC = "sounds/background/Sci-Fi1.ogg"; - private static final String[] forestMusic = {backgroundMusic}; + private static final String[] forestMusic = {BACKGROUND_MUSIC}; private Entity player; private Entity waves; @@ -888,7 +888,7 @@ private void spawnDroidTower() { } private void playMusic() { - Music music = ServiceLocator.getResourceService().getAsset(backgroundMusic, Music.class); + Music music = ServiceLocator.getResourceService().getAsset(BACKGROUND_MUSIC, Music.class); music.setLooping(true); music.setVolume(0.3f); music.play(); diff --git a/source/core/src/main/com/csse3200/game/components/gamearea/CurrencyDisplay.java b/source/core/src/main/com/csse3200/game/components/gamearea/CurrencyDisplay.java index 6b667204e..3e3ee086b 100644 --- a/source/core/src/main/com/csse3200/game/components/gamearea/CurrencyDisplay.java +++ b/source/core/src/main/com/csse3200/game/components/gamearea/CurrencyDisplay.java @@ -29,7 +29,7 @@ public class CurrencyDisplay extends UIComponent { private TextButton scrapsTb; private TextButton crystalsTb; private Sound clickSound; - private static final String defaultFont = "determination_mono_18"; + private static final String DEFAULT_FONT = "determination_mono_18"; /** * Adds actors to stage @@ -74,7 +74,7 @@ private void addActors() { private TextButton createButton(String imageFilePath, int value) { Drawable drawable = new TextureRegionDrawable(new TextureRegion(new Texture(imageFilePath))); TextButton.TextButtonStyle style = new TextButton.TextButtonStyle( - drawable, drawable, drawable, getSkin().getFont(defaultFont)); + drawable, drawable, drawable, getSkin().getFont(DEFAULT_FONT)); // create button TextButton tb = new TextButton(String.format("%d", value), style); diff --git a/source/core/src/main/com/csse3200/game/components/gamearea/EngineerCountDisplay.java b/source/core/src/main/com/csse3200/game/components/gamearea/EngineerCountDisplay.java index 414fce76f..2081831bb 100644 --- a/source/core/src/main/com/csse3200/game/components/gamearea/EngineerCountDisplay.java +++ b/source/core/src/main/com/csse3200/game/components/gamearea/EngineerCountDisplay.java @@ -19,8 +19,11 @@ public class EngineerCountDisplay extends UIComponent { private TextButton engineerTb; - private static final String defaultFont = "determination_mono_18"; + + private static final String DEFAULT_FONT = "determination_mono_18"; + private static final float Z_INDEX = 2f; + @Override public void create() { super.create(); @@ -41,7 +44,7 @@ private void addActors() { Drawable drawable = new TextureRegionDrawable(new TextureRegion( new Texture("images/engineers/engineerBanner.png"))); TextButton.TextButtonStyle style = new TextButton.TextButtonStyle( - drawable, drawable, drawable, getSkin().getFont(defaultFont)); + drawable, drawable, drawable, getSkin().getFont(DEFAULT_FONT)); String text = String.format("%d", ServiceLocator.getGameEndService().getEngineerCount()); engineerTb = new TextButton(text, style); diff --git a/source/core/src/main/com/csse3200/game/components/gamearea/GameAreaDisplay.java b/source/core/src/main/com/csse3200/game/components/gamearea/GameAreaDisplay.java index 3db923bca..9a8149869 100644 --- a/source/core/src/main/com/csse3200/game/components/gamearea/GameAreaDisplay.java +++ b/source/core/src/main/com/csse3200/game/components/gamearea/GameAreaDisplay.java @@ -15,7 +15,7 @@ */ public class GameAreaDisplay extends UIComponent { private static final Logger logger = LoggerFactory.getLogger(GameAreaDisplay.class); - + private static final String DEFAULT_STYLE = "default"; private String gameAreaName = ""; private Label title; @@ -45,10 +45,10 @@ private Dialog createTowerDetailsDialog() { Label.LabelStyle labelStyle = new Label.LabelStyle(); labelStyle.font = new BitmapFont(); labelStyle.fontColor = Color.WHITE; - skin.add("default", labelStyle); + skin.add(DEFAULT_STYLE, labelStyle); // Create the dialog using the registered label style - Dialog dialog = new Dialog("Tower Details", skin,"default"); + Dialog dialog = new Dialog("Tower Details", skin, DEFAULT_STYLE); dialog.text("Health: 100"); // Set tower health here dialog.getContentTable().row(); dialog.text("Attack: 50"); // Set tower attack here @@ -56,8 +56,9 @@ private Dialog createTowerDetailsDialog() { dialog.setVisible(false); // Hide the dialog initially return dialog; } + private void addActors() { - title = new Label(this.gameAreaName, skin, "default"); + title = new Label(this.gameAreaName, skin, DEFAULT_STYLE); stage.addActor(title); } @@ -68,7 +69,6 @@ public void draw(SpriteBatch batch) { float offsetY = 30f; title.setPosition(offsetX, screenHeight - offsetY); - } @Override diff --git a/source/core/src/main/com/csse3200/game/components/pausemenu/PauseMenuButtonComponent.java b/source/core/src/main/com/csse3200/game/components/pausemenu/PauseMenuButtonComponent.java index 030d05494..23fb243c9 100644 --- a/source/core/src/main/com/csse3200/game/components/pausemenu/PauseMenuButtonComponent.java +++ b/source/core/src/main/com/csse3200/game/components/pausemenu/PauseMenuButtonComponent.java @@ -27,8 +27,8 @@ public class PauseMenuButtonComponent extends UIComponent { private static final float Z_INDEX = 2f; private Window window; private final GdxGame game; - private static final float windowSizeX = 300; - private static final float windowSizeY = 400; + private static final float WINDOW_SIZE_X = 300; + private static final float WINDOW_SIZE_Y = 400; private final String[] sounds = { "sounds/ui/click/click_01.ogg", "sounds/ui/open_close/close_01.ogg", @@ -119,20 +119,23 @@ public void changed(ChangeEvent changeEvent, Actor actor) { window.add(planetSelectBtn).center(); window.row(); window.add(mainMenuBtn).center(); - window.setWidth(windowSizeX); - window.setHeight(windowSizeY); - window.setX((ServiceLocator.getRenderService().getStage().getWidth() / 2) - (windowSizeX / 2)); - window.setY((ServiceLocator.getRenderService().getStage().getHeight() / 2) - (windowSizeY / 2)); + + window.setWidth(WINDOW_SIZE_X); + window.setHeight(WINDOW_SIZE_Y); + window.setX((ServiceLocator.getRenderService().getStage().getWidth() / 2) - (WINDOW_SIZE_X / 2)); + window.setY((ServiceLocator.getRenderService().getStage().getHeight() / 2) - (WINDOW_SIZE_Y / 2)); // Animate the pause menu opening - window.setPosition(((float) Gdx.graphics.getWidth() / 2) - (windowSizeX / 2),0); + window.setPosition(((float) Gdx.graphics.getWidth() / 2) - (WINDOW_SIZE_X / 2),0); window.addAction(new SequenceAction(Actions.moveTo( - ( ((float) Gdx.graphics.getWidth() / 2) - (windowSizeX / 2) ), - ( ((float) Gdx.graphics.getHeight() / 2) - (windowSizeY / 2) ), + ( ((float) Gdx.graphics.getWidth() / 2) - (WINDOW_SIZE_X / 2) ), + ( ((float) Gdx.graphics.getHeight() / 2) - (WINDOW_SIZE_Y / 2) ), 0.3f, Interpolation.fastSlow), Actions.fadeIn(0.3f))); + + stage.addActor(window); } diff --git a/source/core/src/main/com/csse3200/game/components/pausemenu/PauseMenuTimeStopComponent.java b/source/core/src/main/com/csse3200/game/components/pausemenu/PauseMenuTimeStopComponent.java index f8f50068e..80ebb6db0 100644 --- a/source/core/src/main/com/csse3200/game/components/pausemenu/PauseMenuTimeStopComponent.java +++ b/source/core/src/main/com/csse3200/game/components/pausemenu/PauseMenuTimeStopComponent.java @@ -12,6 +12,7 @@ public class PauseMenuTimeStopComponent extends Component { private Array freezeList; public PauseMenuTimeStopComponent() { + // Not implemented } /** diff --git a/source/core/src/main/com/csse3200/game/components/tasks/DroidCombatTask.java b/source/core/src/main/com/csse3200/game/components/tasks/DroidCombatTask.java index 502f1c4b7..b3c15e9c2 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/DroidCombatTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/DroidCombatTask.java @@ -33,7 +33,6 @@ public class DroidCombatTask extends DefaultTask implements PriorityTask { public static final String SHOOT_UP = "ShootUp"; public static final String SHOOT_DOWN = "ShootDown"; - // class attributes private final int priority; // The active priority this task will have private final float maxRange; @@ -90,7 +89,7 @@ public void update() { } else { endTime = timeSource.getTime() + (INTERVAL * 1000); } - } + } } /** @@ -104,64 +103,28 @@ public void updateTowerState() { towerState = STATE.DIE; return; } + switch (towerState) { case WALK -> { - owner.getEntity().getEvents().trigger(WALK); - towerState = STATE.IDLE; + handleWalkState(); } case IDLE -> { - if (isTargetVisible()) { - owner.getEntity().getEvents().trigger(ATTACK_UP); - owner.getEntity().getEvents().trigger(SHOOT_UP); - towerState = STATE.DOWN; - } else { - owner.getEntity().getEvents().trigger(IDLE); - } + handleIdleState(); } case SHOOT_DOWN -> { - if (isTargetVisible()) { - owner.getEntity().getEvents().trigger(ATTACK_DOWN); - owner.getEntity().getEvents().trigger(SHOOT_DOWN); - towerState = STATE.UP; - } else { - owner.getEntity().getEvents().trigger(GO_UP); - towerState = STATE.UP; - } + handleShootDownState(); } case SHOOT_UP -> { - if (isTargetVisible()) { - - owner.getEntity().getEvents().trigger(ATTACK_UP); - owner.getEntity().getEvents().trigger(SHOOT_UP); - towerState = STATE.DOWN; - } else { - owner.getEntity().getEvents().trigger(IDLE); - towerState = STATE.IDLE; - } + handleShootUpState(); } case DOWN -> { - if (isTargetVisible()) { - owner.getEntity().getEvents().trigger(GO_DOWN); - towerState = STATE.SHOOT_DOWN; - } else { - owner.getEntity().getEvents().trigger(IDLE); - towerState = STATE.IDLE; - } + handleDownState(); } case UP -> { - if (isTargetVisible()) { - owner.getEntity().getEvents().trigger(GO_UP); - towerState = STATE.SHOOT_UP; - } else { - owner.getEntity().getEvents().trigger(GO_UP); - towerState = STATE.IDLE; - - } + handleUpState(); } - case DIE -> { - if (owner.getEntity().getComponent(AnimationRenderComponent.class).isFinished()) { - owner.getEntity().setFlagForDelete(true); - } + default -> { // DIE + handleDieState(); } } } @@ -210,4 +173,87 @@ public float getFireRateInterval() { return fireRateInterval; } -} + /** + * Function triggers walk and changes state from WALK to IDLE + */ + private void handleWalkState() { + owner.getEntity().getEvents().trigger(WALK); + towerState = STATE.IDLE; + } + + /** + * Function triggers actions at IDLE state + */ + private void handleIdleState() { + if (isTargetVisible()) { + owner.getEntity().getEvents().trigger(ATTACK_UP); + owner.getEntity().getEvents().trigger(SHOOT_UP); + towerState = STATE.DOWN; + } else { + owner.getEntity().getEvents().trigger(IDLE); + } + } + + /** + * Function triggers actions at SHOOT_DOWN state, then switch to UP + */ + private void handleShootDownState() { + if (isTargetVisible()) { + owner.getEntity().getEvents().trigger(ATTACK_DOWN); + owner.getEntity().getEvents().trigger(SHOOT_DOWN); + } else { + owner.getEntity().getEvents().trigger(GO_UP); + } + + towerState = STATE.UP; + } + + /** + * Function triggers actions at SHOOT_UP state, then switch to DOWN or IDLE + */ + private void handleShootUpState() { + if (isTargetVisible()) { + owner.getEntity().getEvents().trigger(ATTACK_UP); + owner.getEntity().getEvents().trigger(SHOOT_UP); + towerState = STATE.DOWN; + } else { + owner.getEntity().getEvents().trigger(IDLE); + towerState = STATE.IDLE; + } + } + + /** + * Function triggers actions at DOWN state, then switch to SHOOT_DOWN or IDLE + */ + private void handleDownState() { + if (isTargetVisible()) { + owner.getEntity().getEvents().trigger(GO_DOWN); + towerState = STATE.SHOOT_DOWN; + } else { + owner.getEntity().getEvents().trigger(IDLE); + towerState = STATE.IDLE; + } + } + + /** + * Function triggers actions at UP state, then switch to SHOOT_UP or IDLE + */ + private void handleUpState() { + if (isTargetVisible()) { + owner.getEntity().getEvents().trigger(GO_UP); + towerState = STATE.SHOOT_UP; + } else { + owner.getEntity().getEvents().trigger(GO_UP); + towerState = STATE.IDLE; + } + } + + /** + * Function handles DIE state + */ + private void handleDieState() { + if (owner.getEntity().getComponent(AnimationRenderComponent.class).isFinished()) { + owner.getEntity().setFlagForDelete(true); + } + } +} \ No newline at end of file diff --git a/source/core/src/main/com/csse3200/game/components/tasks/FireTowerCombatTask.java b/source/core/src/main/com/csse3200/game/components/tasks/FireTowerCombatTask.java index 13aa11a18..60714c560 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/FireTowerCombatTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/FireTowerCombatTask.java @@ -47,7 +47,7 @@ public class FireTowerCombatTask extends DefaultTask implements PriorityTask { public enum STATE { IDLE, PREP_ATTACK, ATTACK, DEATH } - public STATE towerState = STATE.IDLE; + private STATE towerState = STATE.IDLE; /** * Starts the task running, triggers the initial 'IDLE' event @@ -67,7 +67,7 @@ public FireTowerCombatTask(int priority, float maxRange) { public void start() { super.start(); // get the tower coordinates - this.towerPosition = owner.getEntity().getCenterPosition(); + this.towerPosition = owner.getEntity().getCenterPosition().sub(0.125f,0.125f); this.maxRangePosition.set(towerPosition.x + maxRange, towerPosition.y); owner.getEntity().getEvents().addListener("addFireRate",this::changeFireRateInterval); //default to idle state @@ -99,43 +99,19 @@ public void updateTowerState() { towerState = STATE.DEATH; return; } + switch (towerState) { case IDLE -> { - if (isTargetVisible()) { - owner.getEntity().getEvents().trigger(PREP_ATTACK); - towerState = STATE.PREP_ATTACK; - } + handleIdleState(); } case PREP_ATTACK -> { - if (isTargetVisible()) { - owner.getEntity().getEvents().trigger(ATTACK); - towerState = STATE.ATTACK; - } else { - owner.getEntity().getEvents().trigger(IDLE); - towerState = STATE.IDLE; - } + handlePrepAttackState(); } case ATTACK -> { - if (shoot) { - if (!isTargetVisible()) { - owner.getEntity().getEvents().trigger(IDLE); - towerState = STATE.IDLE; - } else { - owner.getEntity().getEvents().trigger(ATTACK); - Entity newProjectile = ProjectileFactory.createEffectProjectile(PhysicsLayer.NPC, - new Vector2(100, owner.getEntity().getPosition().y), new Vector2(2f, 2f), ProjectileEffects.BURN, false); - newProjectile.setPosition((float) (owner.getEntity().getPosition().x + 0.25), - (float) (owner.getEntity().getPosition().y)); - ServiceLocator.getEntityService().register(newProjectile); - } - } - shoot = !shoot; - + handleAttackState(); } - case DEATH -> { - if (owner.getEntity().getComponent(AnimationRenderComponent.class).isFinished()) { - owner.getEntity().setFlagForDelete(true); - } + default -> { // DEATH + handleDeathState(); } } } @@ -143,6 +119,7 @@ public void updateTowerState() { /** * stops the current animation. */ + @Override public void stop() { super.stop(); owner.getEntity().getEvents().trigger(IDLE); @@ -167,7 +144,7 @@ public int getPriority() { * not currently used. * @return the priority for this task */ - private int getActivePriority() { + public int getActivePriority() { return !isTargetVisible() ? 0 : priority; } @@ -175,7 +152,7 @@ private int getActivePriority() { * not currently used. * @return */ - private int getInactivePriority() { + public int getInactivePriority() { return isTargetVisible() ? priority : 0; } @@ -200,4 +177,74 @@ public float getFireRateInterval() { return fireRateInterval; } + /** + * Function for getting the tower's state. + * + * @return The tower's state + */ + public STATE getTowerState() { + return this.towerState; + } + + /** + * Function for setting the tower's state + * + * @param newState The new state of this tower + */ + public void setTowerState(STATE newState) { + this.towerState = newState; + } + + /** + * Function triggers actions at IDLE state, then switch to PREP_ATTACK + */ + private void handleIdleState() { + if (isTargetVisible()) { + owner.getEntity().getEvents().trigger(PREP_ATTACK); + towerState = STATE.PREP_ATTACK; + } + } + + /** + * Functions triggers actions at PREP_ATTACH state, then switch to ATTACK or IDLE + */ + private void handlePrepAttackState() { + if (isTargetVisible()) { + owner.getEntity().getEvents().trigger(ATTACK); + towerState = STATE.ATTACK; + } else { + owner.getEntity().getEvents().trigger(IDLE); + towerState = STATE.IDLE; + } + } + + /** + * Functions trigger actions at ATTACK state + */ + private void handleAttackState() { + if (shoot) { + if (!isTargetVisible()) { + owner.getEntity().getEvents().trigger(IDLE); + towerState = STATE.IDLE; + } else { + owner.getEntity().getEvents().trigger(ATTACK); + Entity newProjectile = ProjectileFactory.createEffectProjectile(PhysicsLayer.NPC, + new Vector2(100, owner.getEntity().getPosition().y), new Vector2(2f, 2f), ProjectileEffects.BURN, false); + newProjectile.setPosition((float) (owner.getEntity().getPosition().x + 0.25), + (owner.getEntity().getPosition().y)); + ServiceLocator.getEntityService().register(newProjectile); + } + } + + shoot = !shoot; + } + + /** + * Functions triggers actions at DEATH state + */ + private void handleDeathState() { + if (owner.getEntity().getComponent(AnimationRenderComponent.class).isFinished()) { + owner.getEntity().setFlagForDelete(true); + } + } } diff --git a/source/core/src/main/com/csse3200/game/components/tasks/FireworksTowerCombatTask.java b/source/core/src/main/com/csse3200/game/components/tasks/FireworksTowerCombatTask.java index 8d10036ae..b40cfa0db 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/FireworksTowerCombatTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/FireworksTowerCombatTask.java @@ -45,7 +45,7 @@ public class FireworksTowerCombatTask extends DefaultTask implements PriorityTas public enum STATE { IDLE, ATTACK, DEATH } - public STATE towerState = STATE.IDLE; + private STATE towerState = STATE.IDLE; /** * @param priority Task priority when targets are detected (0 when nothing is present) @@ -77,6 +77,7 @@ public void start() { * updates the current state of the tower based on the current state of the game. If enemies are detected, attack * state is activated and otherwise idle state remains. */ + @Override public void update() { if (timeSource.getTime() >= endTime) { updateTowerState(); @@ -111,7 +112,7 @@ public void updateTowerState() { Entity newProjectile = ProjectileFactory.createSplitFireWorksFireball(PhysicsLayer.NPC, new Vector2(100, owner.getEntity().getPosition().y), new Vector2(2f, 2f), 3); newProjectile.setPosition((float) (owner.getEntity().getPosition().x + 0.25), - (float) (owner.getEntity().getPosition().y)); + (owner.getEntity().getPosition().y)); ServiceLocator.getEntityService().register(newProjectile); } else { owner.getEntity().getEvents().trigger(IDLE); @@ -139,6 +140,7 @@ public STATE getState() { /** * stops the current animation and switches back the state of the tower to IDLE. */ + @Override public void stop() { super.stop(); owner.getEntity().getEvents().trigger(IDLE); @@ -159,4 +161,21 @@ public int getPriority() { public boolean isTargetVisible() { return physics.raycast(towerPosition, maxRangePosition, TARGET, hit); } + + /** + * Function for getting the tower's state + * + * @return The state of this tower + */ + public STATE getTowerState() { + return this.towerState; + } + + /** + * Function for setting the tower's state + * @param newState The new state of this tower + */ + public void setTowerState(STATE newState) { + this.towerState = newState; + } } diff --git a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java index c5fc7f0bf..39215cb9e 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/MobAttackTask.java @@ -36,7 +36,7 @@ public class MobAttackTask extends DefaultTask implements PriorityTask { private final Vector2 maxRangePosition = new Vector2(); private final PhysicsEngine physics; private GameTime timeSource; - private long endTime; + private final RaycastHit hit = new RaycastHit(); private static final long DELAY = 1000; // delay between shots @@ -50,7 +50,6 @@ private enum STATE { /** * @param priority Task priority when targets are detected (0 when nothing detected). Must be a positive integer. - * @param maxRange Maximum effective range of the weapon mob. This determines the detection distance of targets */ public MobAttackTask(int priority) { this.priority = priority; @@ -69,9 +68,7 @@ public void start() { startTime = timeSource.getTime(); Vector2 mobPosition = owner.getEntity().getCenterPosition(); this.maxRangePosition.set(0, mobPosition.y); - //owner.getEntity().getEvents().trigger(IDLE); - endTime = timeSource.getTime() + (INTERVAL * 500); -// owner.getEntity().getEvents().trigger("shootStart"); + long endTime = timeSource.getTime() + (INTERVAL * 500); } /** @@ -130,7 +127,6 @@ public void updateMobState() { newProjectile.setScale(-1f, 1f); ServiceLocator.getEntityService().register(newProjectile); -// System.out.printf("ANIMATION: " + owner.getEntity().getComponent(AnimationRenderComponent.class).getCurrentAnimation() + "\n"); this.owner.getEntity().getEvents().trigger(FIRING); mobState = STATE.STOW; } @@ -193,11 +189,10 @@ private boolean isTargetVisible() { * the function will return null. If it returns null when the mob is in state FIRING or DEPLOY, it will not fire * and will STOW. * - * returns the Weapon (Melee or Projectile) the mob will use to attack the target. null if immune target or no target + * @return the Weapon (Melee or Projectile) the mob will use to attack the target. null if immune target or no target * */ private Weapon meleeOrProjectile() { -// Vector2 newVector = new Vector2(owner.getEntity().getPosition().x - 10f, owner.getEntity().getPosition().y - 2f); -// Fixture hitraycast = physics.raycastGetHit(owner.getEntity().getPosition(), newVector, TARGET); + setTarget(); TouchAttackComponent comp = owner.getEntity().getComponent(TouchAttackComponent.class); Weapon chosenWeapon = null; diff --git a/source/core/src/main/com/csse3200/game/components/tasks/MobDeathTask.java b/source/core/src/main/com/csse3200/game/components/tasks/MobDeathTask.java index 478623bcf..5782ca8f9 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/MobDeathTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/MobDeathTask.java @@ -7,10 +7,8 @@ import com.csse3200.game.entities.Entity; import com.csse3200.game.entities.factories.DropFactory; import com.csse3200.game.physics.PhysicsEngine; -import com.csse3200.game.physics.raycast.RaycastHit; import com.csse3200.game.services.ServiceLocator; import com.csse3200.game.services.GameTime; -//import com.csse3200.game.rendering.DebugRenderer; /** @@ -60,7 +58,6 @@ public void update() { public void updateBossState() { mobHealth = owner.getEntity().getComponent(CombatStatsComponent.class).getHealth(); - // TODO: inset a bit that picks from a list of drop options and drops this if (mobIsDead(mobHealth)) { killMob(); diff --git a/source/core/src/main/com/csse3200/game/components/tasks/MobTask/MobTask.java b/source/core/src/main/com/csse3200/game/components/tasks/MobTask/MobTask.java index 89f510efd..08aa0b627 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/MobTask/MobTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/MobTask/MobTask.java @@ -15,6 +15,7 @@ import com.csse3200.game.rendering.AnimationRenderComponent; import com.csse3200.game.services.GameTime; import com.csse3200.game.services.ServiceLocator; +import com.csse3200.game.components.tasks.MobTask.MobType; /** * The AI Task for all general mobs. This task handles the sequencing for melee @@ -163,7 +164,6 @@ public void update() { runFlag = true; } } - case DEATH, DEFAULT -> {} } } @@ -180,67 +180,6 @@ private void animate() { } case DEFAULT -> owner.getEntity().getEvents().trigger("mob_default"); } - // switch (mobType) { - // case SKELETON -> { - // switch (state) { - // case RUN -> owner.getEntity().getEvents().trigger("skeleton_walk"); - // case ATTACK -> owner.getEntity().getEvents().trigger("skeleton_attack"); - // case DEATH -> owner.getEntity().getEvents().trigger("skeleton_death"); - // case DEFAULT -> owner.getEntity().getEvents().trigger("skeleton_default"); - // } - // } - // case WIZARD -> { - // switch (state) { - // case RUN -> owner.getEntity().getEvents().trigger("wizard_run"); - // case ATTACK -> owner.getEntity().getEvents().trigger("wizard_attack"); - // case DEATH -> owner.getEntity().getEvents().trigger("wizard_death"); - // case DEFAULT -> owner.getEntity().getEvents().trigger("default"); - // } - // } - // case WATER_QUEEN -> { - // switch (state) { - // case RUN -> owner.getEntity().getEvents().trigger("water_queen_walk"); - // case ATTACK -> owner.getEntity().getEvents().trigger("water_queen_attack"); - // case DEATH -> owner.getEntity().getEvents().trigger("water_queen_death"); - // case DEFAULT -> owner.getEntity().getEvents().trigger("default"); - // } - // } - // case WATER_SLIME -> { - // switch (state) { - // case RUN -> owner.getEntity().getEvents().trigger("water_slime_walk"); - // case ATTACK -> owner.getEntity().getEvents().trigger("water_slime_attack"); - // case DEATH -> { - // owner.getEntity().getEvents().trigger("water_slime_death"); - // owner.getEntity().getEvents().trigger("splitDeath"); - // } - // case DEFAULT -> owner.getEntity().getEvents().trigger("default"); - // } - // } - // case FIRE_WORM -> { - // switch (state) { - // case RUN -> owner.getEntity().getEvents().trigger("fire_worm_walk"); - // case ATTACK -> owner.getEntity().getEvents().trigger("fire_worm_attack"); - // case DEATH -> owner.getEntity().getEvents().trigger("fire_worm_death"); - // case DEFAULT -> owner.getEntity().getEvents().trigger("default"); - // } - // } - // case DRAGON_KNIGHT -> { - // switch (state) { - // case RUN -> owner.getEntity().getEvents().trigger("dragon_knight_run"); - // case ATTACK -> owner.getEntity().getEvents().trigger("dragon_knight_attack"); - // case DEATH -> owner.getEntity().getEvents().trigger("dragon_knight_death"); - // case DEFAULT -> owner.getEntity().getEvents().trigger("default"); - // } - // } - // case COAT -> { - // switch (state) { - // case RUN -> owner.getEntity().getEvents().trigger("coat_run"); - // case ATTACK -> owner.getEntity().getEvents().trigger("coat_attack"); - // case DEATH -> owner.getEntity().getEvents().trigger("coat_death"); - // case DEFAULT -> owner.getEntity().getEvents().trigger("default"); - // } - // } - // } } /** diff --git a/source/core/src/main/com/csse3200/game/components/tasks/PierceTowerCombatTask.java b/source/core/src/main/com/csse3200/game/components/tasks/PierceTowerCombatTask.java index cdefde434..75268d9b6 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/PierceTowerCombatTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/PierceTowerCombatTask.java @@ -43,7 +43,7 @@ public class PierceTowerCombatTask extends DefaultTask implements PriorityTask { public enum STATE { IDLE, ATTACK, DEATH } - public STATE towerState = STATE.IDLE; + private STATE towerState = STATE.IDLE; /** * @param priority Task priority when targets are detected (0 when nothing is present) @@ -63,7 +63,7 @@ public PierceTowerCombatTask(int priority, float maxRange) { public void start() { super.start(); // Get the tower coordinates - this.towerPosition = owner.getEntity().getCenterPosition(); + this.towerPosition = owner.getEntity().getCenterPosition().sub(0.25f, 0.25f); this.maxRangePosition.set(towerPosition.x + maxRange, towerPosition.y); // Set the default state to IDLE state owner.getEntity().getEvents().trigger(IDLE); @@ -75,6 +75,7 @@ public void start() { * updates the current state of the tower based on the current state of the game. If enemies are detected, attack * state is activated and otherwise idle state remains. */ + @Override public void update() { if (timeSource.getTime() >= endTime) { updateTowerState(); @@ -113,14 +114,14 @@ public void updateTowerState() { Entity newProjectile = ProjectileFactory.createPierceFireBall(PhysicsLayer.NPC, new Vector2(100, owner.getEntity().getPosition().y), new Vector2(2f, 2f)); newProjectile.setPosition((float) (owner.getEntity().getPosition().x + 0.25), - (float) (owner.getEntity().getPosition().y)); + (owner.getEntity().getPosition().y)); ServiceLocator.getEntityService().register(newProjectile); } } shoot = !shoot; } - case DEATH -> { + default -> { // DEATH if (owner.getEntity().getComponent(AnimationRenderComponent.class).isFinished()) { owner.getEntity().setFlagForDelete(true); } @@ -139,6 +140,7 @@ public STATE getState() { /** * stops the current animation and switches back the state of the tower to IDLE. */ + @Override public void stop() { super.stop(); owner.getEntity().getEvents().trigger(IDLE); @@ -159,4 +161,21 @@ public int getPriority() { public boolean isTargetVisible() { return physics.raycast(towerPosition, maxRangePosition, TARGET, hit); } + + /** + * Function for getting the tower's state + * + * @return The state of this tower + */ + public STATE getTowerState() { + return this.towerState; + } + + /** + * Function for setting the tower's state + * @param newState The new state of this tower + */ + public void setTowerState(STATE newState) { + this.towerState = newState; + } } diff --git a/source/core/src/main/com/csse3200/game/components/tasks/RicochetTowerCombatTask.java b/source/core/src/main/com/csse3200/game/components/tasks/RicochetTowerCombatTask.java index 7fc3e5728..6e60bf01d 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/RicochetTowerCombatTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/RicochetTowerCombatTask.java @@ -45,7 +45,7 @@ public class RicochetTowerCombatTask extends DefaultTask implements PriorityTask public enum STATE { IDLE, ATTACK, DEATH } - public STATE towerState = STATE.IDLE; + private STATE towerState = STATE.IDLE; /** * @param priority Task priority when targets are detected (0 when nothing is present) @@ -65,7 +65,7 @@ public RicochetTowerCombatTask(int priority, float maxRange) { public void start() { super.start(); // Get the tower coordinates - this.towerPosition = owner.getEntity().getCenterPosition(); + this.towerPosition = owner.getEntity().getCenterPosition().sub(0.25f, 0.25f); this.maxRangePosition.set(towerPosition.x + maxRange, towerPosition.y); // Set the default state to IDLE state owner.getEntity().getEvents().trigger(IDLE); @@ -77,6 +77,7 @@ public void start() { * updates the current state of the tower based on the current state of the game. If enemies are detected, attack * state is activated and otherwise idle state remains. */ + @Override public void update() { if (timeSource.getTime() >= endTime) { updateTowerState(); @@ -89,7 +90,6 @@ public void update() { * of the game. If enemies are detected, state of the tower is changed to attack state. */ public void updateTowerState() { - if (owner.getEntity().getComponent(CombatStatsComponent.class).getHealth() <= 0 && towerState != STATE.DEATH) { owner.getEntity().getEvents().trigger(DEATH); towerState = STATE.DEATH; @@ -114,13 +114,13 @@ public void updateTowerState() { // NEED TO DO USER TESTING TO FIGURE OUT THE BOUNCE COUNT new Vector2(100, owner.getEntity().getPosition().y), new Vector2(2f, 2f), 3); newProjectile.setPosition((float) (owner.getEntity().getPosition().x + 0.25), - (float) (owner.getEntity().getPosition().y)); + (owner.getEntity().getPosition().y)); ServiceLocator.getEntityService().register(newProjectile); } } shoot = !shoot; } - case DEATH -> { + default -> { // DEATH if (owner.getEntity().getComponent(AnimationRenderComponent.class).isFinished()) { owner.getEntity().setFlagForDelete(true); } @@ -128,13 +128,27 @@ public void updateTowerState() { } } + /** + * Function for getting the tower's state + * + * @return The state of this tower + */ public STATE getState() { return this.towerState; } + /** + * Function for setting the tower's state + * @param newState The new state of this tower + */ + public void setState(STATE newState) { + this.towerState = newState; + } + /** * stops the current animation and switches back the state of the tower to IDLE. */ + @Override public void stop() { super.stop(); owner.getEntity().getEvents().trigger(IDLE); diff --git a/source/core/src/main/com/csse3200/game/components/tasks/SpawnWaveTask.java b/source/core/src/main/com/csse3200/game/components/tasks/SpawnWaveTask.java index d6c4a3d85..912a2451b 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/SpawnWaveTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/SpawnWaveTask.java @@ -8,7 +8,7 @@ import org.slf4j.LoggerFactory; public class SpawnWaveTask extends DefaultTask implements PriorityTask { - private static final Logger logger = LoggerFactory.getLogger(SpawnWaveTask.class); + private final GameTime globalTime; private long endTime = 0; private final int SPAWNING_INTERVAL = 10; diff --git a/source/core/src/main/com/csse3200/game/components/tasks/StunTowerCombatTask.java b/source/core/src/main/com/csse3200/game/components/tasks/StunTowerCombatTask.java index ec469b269..03abc3552 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/StunTowerCombatTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/StunTowerCombatTask.java @@ -46,7 +46,7 @@ public class StunTowerCombatTask extends DefaultTask implements PriorityTask { public enum STATE { IDLE, ATTACK, DIE } - public STATE towerState = STATE.IDLE; + private STATE towerState = STATE.IDLE; /** * @param priority Task priority when targets are detected (0 when nothing is present) @@ -67,7 +67,7 @@ public StunTowerCombatTask(int priority, float maxRange) { public void start() { super.start(); //get the tower coordinates - this.towerPosition = owner.getEntity().getCenterPosition(); + this.towerPosition = owner.getEntity().getCenterPosition().sub(0.25f, 0.25f); this.maxRangePosition.set(towerPosition.x + maxRange, towerPosition.y); owner.getEntity().getEvents().addListener("addFireRate",this::changeFireRateInterval); //set the default state to IDLE state @@ -80,6 +80,7 @@ public void start() { * updates the current state of the tower based on the current state of the game. If enemies are detected, attack * state is activated and otherwise idle state remains. */ + @Override public void update() { if (timeSource.getTime() >= endTime) { updateTowerState(); @@ -96,7 +97,6 @@ public void update() { * of the game. If enemies are detected, state of the tower is changed to attack state. */ public void updateTowerState() { - if (owner.getEntity().getComponent(CombatStatsComponent.class).getHealth() <= 0 && towerState != STATE.DIE) { owner.getEntity().getEvents().trigger(DEATH); @@ -124,15 +124,16 @@ public void updateTowerState() { new Vector2(100, owner.getEntity().getPosition().y), new Vector2(2f, 2f), ProjectileEffects.STUN, false); newProjectile.setPosition((float) (owner.getEntity().getPosition().x + 0.25), - (float) (owner.getEntity().getPosition().y)); + (owner.getEntity().getPosition().y)); ServiceLocator.getEntityService().register(newProjectile); owner.getEntity().getEvents().trigger(IDLE); towerState = STATE.IDLE; } } + shoot = !shoot; } - case DIE -> { + default -> { // DIE if (owner.getEntity().getComponent(AnimationRenderComponent.class).isFinished()) { owner.getEntity().setFlagForDelete(true); } @@ -140,13 +141,27 @@ public void updateTowerState() { } } + /** + * Function for getting the tower's state + * + * @return The state of this tower + */ public STATE getState() { return this.towerState; } + /** + * Function for setting the tower's state + * @param newState The new state of this tower + */ + public void setState(STATE newState) { + this.towerState = newState; + } + /** * stops the current animation and switches back the state of the tower to IDLE. */ + @Override public void stop() { super.stop(); owner.getEntity().getEvents().trigger(IDLE); diff --git a/source/core/src/main/com/csse3200/game/components/tasks/TNTTowerCombatTask.java b/source/core/src/main/com/csse3200/game/components/tasks/TNTTowerCombatTask.java index 48e28fdd9..4c8016d24 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/TNTTowerCombatTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/TNTTowerCombatTask.java @@ -25,7 +25,6 @@ public class TNTTowerCombatTask extends DefaultTask implements PriorityTask { public static final String DEFAULT = "defaultStart"; public static final String DAMAGE = "TNTDamageStart"; - // class attributes private final int priority; // The active priority this task will have private final float maxRange; @@ -51,7 +50,6 @@ public TNTTowerCombatTask(int priority, float maxRange) { this.maxRange = maxRange; physics = ServiceLocator.getPhysicsService().getPhysics(); timeSource = ServiceLocator.getTimeSource(); - } /** @@ -87,7 +85,6 @@ public void update() { */ public void updateTowerState() { // configure tower state depending on target visibility - switch (towerState) { case IDLE -> { // targets detected in idle mode - start deployment @@ -103,7 +100,7 @@ public void updateTowerState() { owner.getEntity().getEvents().trigger(DAMAGE); towerState = STATE.REMOVE; } - case REMOVE -> readToDelete = true; + default -> readToDelete = true; // REMOVE } } @@ -140,13 +137,6 @@ public boolean isTargetVisible() { } public boolean isReadyToDelete() { - return readToDelete; } - - -} - - - - +} \ No newline at end of file diff --git a/source/core/src/main/com/csse3200/game/components/tasks/TowerCombatTask.java b/source/core/src/main/com/csse3200/game/components/tasks/TowerCombatTask.java index 6ea6dd9d3..b5dd8f45c 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/TowerCombatTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/TowerCombatTask.java @@ -123,61 +123,16 @@ public void updateTowerState() { towerState = STATE.DEATH; return; } + switch (towerState) { - case IDLE -> { - // targets detected in idle mode - start deployment - if (isTargetVisible()) { - owner.getEntity().getEvents().trigger(DEPLOY); - towerState = STATE.DEPLOY; - } - } - case DEPLOY -> { - // currently deploying, - if (isTargetVisible()) { - owner.getEntity().getEvents().trigger(FIRING); - towerState = STATE.FIRING; - } else { - owner.getEntity().getEvents().trigger(STOW); - towerState = STATE.STOW; - } - } - case FIRING -> { - if (shoot) { - // targets gone - stop firing - if (!isTargetVisible()) { - - owner.getEntity().getEvents().trigger(STOW); - towerState = STATE.STOW; - } else { - owner.getEntity().getEvents().trigger(FIRING); - // this might be changed to an event which gets triggered everytime the tower enters the firing state - - Entity newProjectile = ProjectileFactory.createFireBall(PhysicsLayer.NPC, new Vector2(100, owner.getEntity().getPosition().y), new Vector2(2f, 2f)); - newProjectile.setScale(1.1f, 0.8f); - newProjectile.setPosition((float) (owner.getEntity().getPosition().x + 0.5), (owner.getEntity().getPosition().y)); - ServiceLocator.getEntityService().register(newProjectile); - } - } - shoot = !shoot; - } - case STOW -> { - // currently stowing - if (isTargetVisible()) { - - owner.getEntity().getEvents().trigger(DEPLOY); - towerState = STATE.DEPLOY; - } else { - owner.getEntity().getEvents().trigger(IDLE); - towerState = STATE.IDLE; - } - } - case DEATH -> { - if (owner.getEntity().getComponent(AnimationRenderComponent.class).isFinished()) { - owner.getEntity().setFlagForDelete(true); - } - } + case IDLE -> handleIdleState(); + case DEPLOY -> handleDeployState(); + case FIRING -> handleFiringState(); + case STOW -> handleStowState(); + default -> handleDeathState(); // DEATH } } + /** * For stopping the running task */ @@ -227,7 +182,7 @@ private boolean isTargetVisible() { * @param newInterval The rate at which the tower should fire projectiles in shots per second. */ private void changeFireRateInterval(int newInterval) { - logger.info("Changing fire rate to: " + newInterval); + logger.info("Changing fire rate to: %d", newInterval); fireRateInterval = 1 / ((float) newInterval / 5); } @@ -240,4 +195,74 @@ public float getFireRateInterval() { return fireRateInterval; } -} + /** + * Function triggers actions at IDLE state, then switch to DEPLOY + */ + private void handleIdleState() { + // targets detected in idle mode - start deployment + if (isTargetVisible()) { + owner.getEntity().getEvents().trigger(DEPLOY); + towerState = STATE.DEPLOY; + } + } + + /** + * Function triggers actions at DEPLOY state, then switch to FIRING or STOW + */ + private void handleDeployState() { + // currently deploying, + if (isTargetVisible()) { + owner.getEntity().getEvents().trigger(FIRING); + towerState = STATE.FIRING; + } else { + owner.getEntity().getEvents().trigger(STOW); + towerState = STATE.STOW; + } + } + + /** + * Function triggers actions at FIRING state + */ + private void handleFiringState() { + if (shoot) { + // targets gone - stop firing + if (!isTargetVisible()) { + owner.getEntity().getEvents().trigger(STOW); + towerState = STATE.STOW; + } else { + owner.getEntity().getEvents().trigger(FIRING); + // this might be changed to an event which gets triggered everytime the tower enters the firing state + + Entity newProjectile = ProjectileFactory.createFireBall(PhysicsLayer.NPC, new Vector2(100, owner.getEntity().getPosition().y), new Vector2(2f, 2f)); + newProjectile.setScale(1.1f, 0.8f); + newProjectile.setPosition((float) (owner.getEntity().getPosition().x + 0.5), (owner.getEntity().getPosition().y)); + ServiceLocator.getEntityService().register(newProjectile); + } + } + + shoot = !shoot; + } + + /** + * Function triggers actions at STOW state, then switch to DEPLOY or IDLE + */ + private void handleStowState() { + // currently stowing + if (isTargetVisible()) { + owner.getEntity().getEvents().trigger(DEPLOY); + towerState = STATE.DEPLOY; + } else { + owner.getEntity().getEvents().trigger(IDLE); + towerState = STATE.IDLE; + } + } + + /** + * Function handle DEATH state + */ + private void handleDeathState() { + if (owner.getEntity().getComponent(AnimationRenderComponent.class).isFinished()) { + owner.getEntity().setFlagForDelete(true); + } + } +} \ No newline at end of file diff --git a/source/core/src/main/com/csse3200/game/components/tasks/waves/WaveClass.java b/source/core/src/main/com/csse3200/game/components/tasks/waves/WaveClass.java index 41f031858..3e197601e 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/waves/WaveClass.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/waves/WaveClass.java @@ -1,18 +1,14 @@ package com.csse3200.game.components.tasks.waves; -import com.badlogic.gdx.math.GridPoint2; -import com.csse3200.game.entities.Entity; + import com.csse3200.game.services.GameTime; -import com.csse3200.game.services.ServiceLocator; + import java.util.*; public class WaveClass { private HashMap entities; - private GameTime gameTime; - private long startTime; private List wave; - private Random rand = new Random(); private int mobIndex; /** diff --git a/source/core/src/main/com/csse3200/game/components/tasks/waves/WaveTask.java b/source/core/src/main/com/csse3200/game/components/tasks/waves/WaveTask.java index 2b04e4bc0..d49816692 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/waves/WaveTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/waves/WaveTask.java @@ -83,7 +83,6 @@ public void start() { this.currentWave = level.getWave(currentWaveIndex); ServiceLocator.getWaveService().setEnemyCount(currentWave.getSize()); logger.info("Wave {} starting with {} enemies", currentWaveIndex, ServiceLocator.getWaveService().getEnemyCount()); - this.waveStart.play(); // endTime = globalTime.getTime() + (SPAWNING_INTERVAL * 1000); } @@ -105,15 +104,16 @@ public void update() { // logger.info("No enemies remaining, begin next wave"); if (nextWaveAt == 0) { logger.info("Next wave in 10 seconds"); + this.waveEnd.play(); nextWaveAt = globalTime.getTime() + 10000; ServiceLocator.getWaveService().setNextWaveTime(nextWaveAt); } else { if (globalTime.getTime() >= nextWaveAt || ServiceLocator.getWaveService().shouldSkip()) { + this.waveStart.play(); ServiceLocator.getWaveService().toggleDelay(); currentWaveIndex++; ServiceLocator.getWaveService().setNextWaveTime(0); nextWaveAt = 0; - this.waveEnd.play(); this.waveInProgress = true; this.level.setWaveIndex(currentWaveIndex); // Set the service wave count to the current wave index. diff --git a/source/core/src/main/com/csse3200/game/entities/factories/WaveFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/WaveFactory.java index 20d1781f2..53ea2007a 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/WaveFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/WaveFactory.java @@ -27,25 +27,23 @@ public class WaveFactory { private static final Logger logger = LoggerFactory.getLogger(WaveFactory.class); private static Random rand = new Random(); - - // TODO: include necromancer private static final ArrayList MELEE_MOBS = new ArrayList<>(Arrays.asList( - "Skeleton", "Coat", "DragonKnight" + "Skeleton", "Coat", "DragonKnight", "Necromancer" )); private static final ArrayList> lvl1Structure = new ArrayList<>(Arrays.asList( new ArrayList<>(Arrays.asList("Coat" )), new ArrayList<>(Arrays.asList("Coat", "WaterQueen" - )), new ArrayList<>(Arrays.asList("WaterQueen", "WaterQueen" - )), new ArrayList<>(Arrays.asList("Coat", "WaterQueen", "Coat" + )), new ArrayList<>(Arrays.asList("WaterQueen", "SplittingWaterSlime" + )), new ArrayList<>(Arrays.asList("Coat", "WaterQueen", "SplittingWaterSlime" )) )); private static final ArrayList> lvl2Structure = new ArrayList<>(Arrays.asList( new ArrayList<>(Arrays.asList("Skeleton" - )), new ArrayList<>(Arrays.asList("Skeleton", "SplittingNightBorne" - )), new ArrayList<>(Arrays.asList("Skeleton", "Wizard" )), new ArrayList<>(Arrays.asList("Skeleton", "ArcaneArcher" + )), new ArrayList<>(Arrays.asList("Skeleton", "Wizard" + )), new ArrayList<>(Arrays.asList("Skeleton", "SplittingNightBorne" )), new ArrayList<>(Arrays.asList("Wizard", "SplittingNightBorne" )), new ArrayList<>(Arrays.asList("SplittingNightBorne", "Skeleton" )), new ArrayList<>(Arrays.asList("Wizard", "SplittingNightBorne" @@ -58,28 +56,20 @@ public class WaveFactory { new ArrayList<>(Arrays.asList("Necromancer" )), new ArrayList<>(Arrays.asList("Necromancer", "DodgingDragon" )), new ArrayList<>(Arrays.asList("Necromancer", "FireWorm" - )), new ArrayList<>(Arrays.asList("Necromancer", "FireWorm" - )), new ArrayList<>(Arrays.asList("SplittingRocky", "FireWorm" + )), new ArrayList<>(Arrays.asList("Necromancer", "DeflectFireWizard" + )), new ArrayList<>(Arrays.asList("DeflectFireWizard", "FireWorm" )), new ArrayList<>(Arrays.asList("DodgingDragon", "FireWorm" )), new ArrayList<>(Arrays.asList("DodgingDragon", "Necromancer" )), new ArrayList<>(Arrays.asList("FireWorm", "Necromancer" - )), new ArrayList<>(Arrays.asList("DeflectFireWiza","SplittingRocky", "Necromancer" - )), new ArrayList<>(Arrays.asList("DodgingDragon", "DeflectFireWizard", "SplittingRocky", "Necromancer" - )), new ArrayList<>(Arrays.asList("FireWorm", "DeflectWizard", "DodgingDragon" - )), new ArrayList<>(Arrays.asList("FireWorm", "DeflectWizard", "Necromancer" - )), new ArrayList<>(Arrays.asList("Necromancer", "DeflectFireWizard", "SplittingRocky", "DodgingDragon", "FireWorm" + )), new ArrayList<>(Arrays.asList("DeflectFireWizard", "Necromancer" + )), new ArrayList<>(Arrays.asList("DodgingDragon", "DeflectFireWizard", "Necromancer" + )), new ArrayList<>(Arrays.asList("FireWorm", "Necromancer", "DodgingDragon" + )), new ArrayList<>(Arrays.asList("FireWorm", "SplittingRocky", "Necromancer" + )), new ArrayList<>(Arrays.asList("SplittingRocky", "DeflectFireWizard", "FireWorm" + )), new ArrayList<>(Arrays.asList("DeflectFireWizard", "SplittingRocky", "Necromancer", "DodgingDragon", "FireWorm" )) )); - // The base health for the different mobs - private static int MELEE_BASE_HEALTH = 80; - private static int RANGE_BASE_HEALTH = 60; - - // Base health of the bosses - private static int LVL1_BOSS_BASE_HEALTH = 500; - private static int LVL2_BOSS_BASE_HEALTH = 1000; - private static int LVL3_BOSS_BASE_HEALTH = 2000; - private static final String BOSS_1 = "IceBoss"; private static final String BOSS_2 = "PatrickBoss"; private static final String BOSS_3 = "FireBoss"; @@ -139,6 +129,11 @@ public static LevelWaves createLevel(int chosenLevel) { String boss = ""; int bossHealth; int minMobs; + // Base health of the bosses + int LVL1_BOSS_BASE_HEALTH = 500; + int LVL2_BOSS_BASE_HEALTH = 1000; + int LVL3_BOSS_BASE_HEALTH = 2000; + switch (chosenLevel) { case 2: boss = BOSS_2; @@ -176,14 +171,19 @@ public static LevelWaves createLevel(int chosenLevel) { // Calculate the number of mobs for the wave if (leftToSort == 0) { num = minMobs - currentMobs; + System.out.println(num + " for " + mob + " at wave " + atWave); } else { - num = rand.nextInt(minMobs - currentMobs - (2 * leftToSort)) + 2; + num = rand.nextInt(minMobs - currentMobs - (2 * leftToSort) - 2) + 2; + System.out.println(num + " for " + mob + " at wave " + atWave); currentMobs += num; } // Calculate the health + int RANGE_BASE_HEALTH = 60; int health = RANGE_BASE_HEALTH; if (MELEE_MOBS.contains(mob)) { + // The base health for the different mobs + int MELEE_BASE_HEALTH = 80; health = MELEE_BASE_HEALTH; } int[] mobStats = {num, health + (atWave * chosenLevel)}; diff --git a/source/core/src/main/com/csse3200/game/input/BuildInputComponent.java b/source/core/src/main/com/csse3200/game/input/BuildInputComponent.java index d19eaa60c..30f26eb59 100644 --- a/source/core/src/main/com/csse3200/game/input/BuildInputComponent.java +++ b/source/core/src/main/com/csse3200/game/input/BuildInputComponent.java @@ -166,6 +166,7 @@ public boolean buildTower(int x, int y) { // fetch the price of the selected tower and attempt to instantiate int cost = Integer.parseInt(currencyService.getTower().getPrice()); + if (canAfford(cost)) { createTower(tower, x, y, cost); @@ -203,6 +204,9 @@ private void createTower(TowerType tower, int x, int y, int cost) { case WALL -> TowerFactory.createWallTower(); case FIRE -> TowerFactory.createFireTower(); case STUN -> TowerFactory.createStunTower(); + case PIERCE -> TowerFactory.createPierceTower(); + case FIREWORK -> TowerFactory.createFireworksTower(); + case RICOCHET -> TowerFactory.createRicochetTower(); }; // build the selected tower newTower.setPosition(x, y); diff --git a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java index f21db90fb..9d4c42f50 100644 --- a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java +++ b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java @@ -288,7 +288,6 @@ public void clicked(InputEvent event, float x, float y) { float fireRate = turretEntity.getComponent(UpgradableStatsComponent.class).getAttackRate(); fireRateLabel.setText(String.format("%.2f", fireRate)); } - } @@ -304,7 +303,7 @@ public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) }); // Repair button - Drawable repair = new TextureRegionDrawable(new TextureRegion(new Texture("images/hammer.png"))); + Drawable repair = new TextureRegionDrawable(new TextureRegion(new Texture("images/spanner.png"))); ImageButton repairButton = new ImageButton(repair); repairButton.addListener(new ClickListener() { @Override diff --git a/source/core/src/main/com/csse3200/game/screens/MainGameScreen.java b/source/core/src/main/com/csse3200/game/screens/MainGameScreen.java index e21cec99c..93471edd3 100644 --- a/source/core/src/main/com/csse3200/game/screens/MainGameScreen.java +++ b/source/core/src/main/com/csse3200/game/screens/MainGameScreen.java @@ -220,7 +220,7 @@ public void render(float delta) { } else if (ServiceLocator.getWaveService().isLevelCompleted()) { // Check if all waves are completed and the level has been completed logger.info("Main game level completed detected, go to win screen"); - ui.getEvents().trigger("lose"); // needs to change to: ui.getEvents().trigger("win"); + ui.getEvents().trigger("win"); // needs to change to: ui.getEvents().trigger("win"); // Add something in to unlock the next planet/level? } } diff --git a/source/core/src/main/com/csse3200/game/screens/TowerType.java b/source/core/src/main/com/csse3200/game/screens/TowerType.java index 78ee04192..602409bcf 100644 --- a/source/core/src/main/com/csse3200/game/screens/TowerType.java +++ b/source/core/src/main/com/csse3200/game/screens/TowerType.java @@ -2,20 +2,26 @@ public enum TowerType { WEAPON("Weapon Tower", "weapon_tower", "The Weapon Tower is a simple and basic turret that fires rapid shots at enemies dealing damage over time.", - 0, "15", "images/turret-select/Weapon-Tower-Default.png", "images/turret-select/Weapon-Tower-Clicked.png"), + 0, "15", "images/turret-select/Weapon-Tower-Default.png", "images/turret-select/weapon-tower-selected.png"), TNT("TNT Tower", "tnt_tower", "The TNT Tower launches explosive projectiles, dealing area damage to groups of enemies.", - 1, "30", "images/turret-select/tnt-tower-default.png", "images/turret-select/tnt-tower-clicked.png"), + 1, "30", "images/turret-select/tnt-tower-default.png", "images/turret-select/tnt-tower-selected.png"), DROID("Droid Tower", "droid_tower", "Droid Towers deploy robotic helpers that assist in combat and provide support to nearby turrets.", - 2, "45", "images/turret-select/droid-tower-default.png", "images/turret-select/droid-tower-clicked.png"), + 2, "45", "images/turret-select/droid-tower-default.png", "images/turret-select/droid-tower-selected.png"), WALL("Wall Tower", "wall", "The Wall Tower creates barriers to block enemy paths, slowing down their progress.", - 3, "45", "images/turret-select/wall-tower-default.png", "images/turret-select/wall-tower-clicked.png"), + 3, "45", "images/turret-select/wall-tower-default.png", "images/turret-select/wall-tower-selected.png"), FIRE("Fire Tower", "fire_tower", "The Fire Tower emits flames, causing damage over time to enemies caught in its fiery radius.", - 4, "45", "images/turret-select/fire-tower-default.png", "images/turret-select/fire-tower-clicked.png"), + 4, "45", "images/turret-select/fire-tower-default.png", "images/turret-select/fire-tower-selected.png"), STUN("Stun Tower", "stun_tower", "The Stun Tower releases electric shocks that temporarily immobilize and damage enemies.", - 5, "45", "images/turret-select/stun-tower-default.png", "images/turret-select/stun-tower-clicked.png"), + 5, "45", "images/turret-select/stun-tower-default.png", "images/turret-select/stun-tower-selected.png"), INCOME("Income Tower", "income_tower", "The Income Tower generates additional in-game currency over time.", - 6, "10", "images/turret-select/mine-tower-default.png", "images/turret-select/mine-tower-clicked.png"); - + 6, "10", "images/turret-select/mine-tower-default.png", "images/turret-select/mine-tower-selected.png"), + PIERCE("Pierce Tower", "pierce_tower", "The Pierce Tower fires a projectile that pierces through targets and does not dissipate upon contact.", + 6, "0", "images/turret-select/pierce-tower-default.png", "images/turret-select/pierce-tower-selected.png"), + RICOCHET("Ricochet Tower", "ricochet_tower", "The Ricochet Tower fires a projectile that upon contact does damage and changes direction", + 7, "0", "images/turret-select/ricochet-tower-default.png", "images/turret-select/ricochet-tower-selected.png"), + FIREWORK("Firework Tower", "fireworks_tower", "The Firework Tower fires a projectile that splits on contact with its target", + 8, "0", "images/turret-select/firework-tower-default.png", "images/turret-select/firework-tower-selected.png"); + private final String towerName; private final String skinName; private final String description; diff --git a/source/core/src/main/com/csse3200/game/screens/TurretSelectionScreen.java b/source/core/src/main/com/csse3200/game/screens/TurretSelectionScreen.java index e154ac08d..1b500d615 100644 --- a/source/core/src/main/com/csse3200/game/screens/TurretSelectionScreen.java +++ b/source/core/src/main/com/csse3200/game/screens/TurretSelectionScreen.java @@ -161,10 +161,6 @@ public void clicked(InputEvent event, float x, float y) { descriptionLabel = createButton("images/turret-select/imageedit_15_5627113584.png", "images/turret-select/imageedit_15_5627113584.png", "Description: ", turretName, ""); - //turretDescriptionText = createButton("images/turret-select/imageedit_20_9050213399.png", - // "images/turret-select/imageedit_20_9050213399.png", ) - - TextButton button = createButton(turret.getDefaultImage(), turret.getClickedImage(), turret.getPrice(), turret.getTowerName(), turret.getDescription()); diff --git a/source/core/src/test/com/csse3200/game/components/tasks/DroidCombatTaskTest.java b/source/core/src/test/com/csse3200/game/components/tasks/DroidCombatTaskTest.java index c7f71512e..d31f3505d 100644 --- a/source/core/src/test/com/csse3200/game/components/tasks/DroidCombatTaskTest.java +++ b/source/core/src/test/com/csse3200/game/components/tasks/DroidCombatTaskTest.java @@ -122,7 +122,6 @@ public void testUpdateTowerStateWithTargetNotInRange() { verify(idle).handle(); verifyNoInteractions(attackUp); assertEquals(DroidCombatTask.STATE.IDLE, droidCombatTask.getState()); - } diff --git a/source/core/src/test/com/csse3200/game/components/tasks/FireTowerCombatTaskTest.java b/source/core/src/test/com/csse3200/game/components/tasks/FireTowerCombatTaskTest.java index a2b92d857..ec0cbe0ef 100644 --- a/source/core/src/test/com/csse3200/game/components/tasks/FireTowerCombatTaskTest.java +++ b/source/core/src/test/com/csse3200/game/components/tasks/FireTowerCombatTaskTest.java @@ -66,7 +66,7 @@ public void testUpdateTowerStateWithTargetInRange() { entity.getEvents().addListener(FireTowerCombatTask.ATTACK, attack); //Jump to IDLE state fireTowerCombatTask.start(); - fireTowerCombatTask.towerState = FireTowerCombatTask.STATE.IDLE; + fireTowerCombatTask.setTowerState(FireTowerCombatTask.STATE.IDLE); ServiceLocator.getPhysicsService().getPhysics().update(); entity.update(); @@ -103,7 +103,7 @@ public void testUpdateTowerStateWithTargetNotInRange() { entity.getEvents().addListener(FireTowerCombatTask.IDLE, idle); entity.getEvents().addListener(FireTowerCombatTask.PREP_ATTACK, prepAttack); - fireTowerCombatTask.towerState = FireTowerCombatTask.STATE.IDLE; + fireTowerCombatTask.setTowerState(FireTowerCombatTask.STATE.IDLE); ServiceLocator.getPhysicsService().getPhysics().update(); entity.update(); diff --git a/source/core/src/test/com/csse3200/game/components/tasks/FireworksTowerCombatTaskTest.java b/source/core/src/test/com/csse3200/game/components/tasks/FireworksTowerCombatTaskTest.java index 9310e8229..e7addd508 100644 --- a/source/core/src/test/com/csse3200/game/components/tasks/FireworksTowerCombatTaskTest.java +++ b/source/core/src/test/com/csse3200/game/components/tasks/FireworksTowerCombatTaskTest.java @@ -64,7 +64,7 @@ public void testUpdateTowerStateWithTargetInRange() { entity.getEvents().addListener(FireworksTowerCombatTask.ATTACK, attack); //Jump to IDLE state fireworksTowerCombatTask.start(); - fireworksTowerCombatTask.towerState = FireworksTowerCombatTask.STATE.IDLE; + fireworksTowerCombatTask.setTowerState(FireworksTowerCombatTask.STATE.IDLE); ServiceLocator.getPhysicsService().getPhysics().update(); entity.update(); @@ -92,7 +92,7 @@ public void testUpdateTowerStateWithTargetNotInRange() { entity.getEvents().addListener(FireworksTowerCombatTask.IDLE, idle); entity.getEvents().addListener(FireworksTowerCombatTask.ATTACK, attack); - fireworksTowerCombatTask.towerState = FireworksTowerCombatTask.STATE.IDLE; + fireworksTowerCombatTask.setTowerState(FireworksTowerCombatTask.STATE.IDLE); ServiceLocator.getPhysicsService().getPhysics().update(); entity.update(); diff --git a/source/core/src/test/com/csse3200/game/components/tasks/PierceTowerCombatTaskTest.java b/source/core/src/test/com/csse3200/game/components/tasks/PierceTowerCombatTaskTest.java index a1a6ff11c..f8d060992 100644 --- a/source/core/src/test/com/csse3200/game/components/tasks/PierceTowerCombatTaskTest.java +++ b/source/core/src/test/com/csse3200/game/components/tasks/PierceTowerCombatTaskTest.java @@ -64,7 +64,7 @@ public void testUpdateTowerStateWithTargetInRange() { entity.getEvents().addListener(PierceTowerCombatTask.ATTACK, attack); //Jump to IDLE state pierceTowerCombatTask.start(); - pierceTowerCombatTask.towerState = PierceTowerCombatTask.STATE.IDLE; + pierceTowerCombatTask.setTowerState(PierceTowerCombatTask.STATE.IDLE); ServiceLocator.getPhysicsService().getPhysics().update(); entity.update(); @@ -93,7 +93,7 @@ public void testUpdateTowerStateWithTargetNotInRange() { entity.getEvents().addListener(PierceTowerCombatTask.IDLE, idle); entity.getEvents().addListener(PierceTowerCombatTask.ATTACK, attack); - pierceTowerCombatTask.towerState = PierceTowerCombatTask.STATE.IDLE; + pierceTowerCombatTask.setTowerState(PierceTowerCombatTask.STATE.IDLE); ServiceLocator.getPhysicsService().getPhysics().update(); entity.update(); diff --git a/source/core/src/test/com/csse3200/game/components/tasks/RicochetTowerCombatTaskTest.java b/source/core/src/test/com/csse3200/game/components/tasks/RicochetTowerCombatTaskTest.java index 7f78761c8..e64d534cf 100644 --- a/source/core/src/test/com/csse3200/game/components/tasks/RicochetTowerCombatTaskTest.java +++ b/source/core/src/test/com/csse3200/game/components/tasks/RicochetTowerCombatTaskTest.java @@ -64,7 +64,7 @@ public void testUpdateTowerStateWithTargetInRange() { entity.getEvents().addListener(RicochetTowerCombatTask.ATTACK, attack); //Jump to IDLE state ricochetTowerCombatTask.start(); - ricochetTowerCombatTask.towerState = RicochetTowerCombatTask.STATE.IDLE; + ricochetTowerCombatTask.setState(RicochetTowerCombatTask.STATE.IDLE); ServiceLocator.getPhysicsService().getPhysics().update(); entity.update(); @@ -92,7 +92,7 @@ public void testUpdateTowerStateWithTargetNotInRange() { entity.getEvents().addListener(RicochetTowerCombatTask.IDLE, idle); entity.getEvents().addListener(RicochetTowerCombatTask.ATTACK, attack); - ricochetTowerCombatTask.towerState = RicochetTowerCombatTask.STATE.IDLE; + ricochetTowerCombatTask.setState(RicochetTowerCombatTask.STATE.IDLE); ServiceLocator.getPhysicsService().getPhysics().update(); entity.update(); diff --git a/source/core/src/test/com/csse3200/game/components/tasks/StunTowerCombatTaskTest.java b/source/core/src/test/com/csse3200/game/components/tasks/StunTowerCombatTaskTest.java index dcd668fc0..30f490340 100644 --- a/source/core/src/test/com/csse3200/game/components/tasks/StunTowerCombatTaskTest.java +++ b/source/core/src/test/com/csse3200/game/components/tasks/StunTowerCombatTaskTest.java @@ -64,7 +64,7 @@ public void testUpdateTowerStateWithTargetInRange() { entity.getEvents().addListener(StunTowerCombatTask.ATTACK, attack); //Jump to IDLE state stunTowerCombatTask.start(); - stunTowerCombatTask.towerState = StunTowerCombatTask.STATE.IDLE; + stunTowerCombatTask.setState(StunTowerCombatTask.STATE.IDLE); ServiceLocator.getPhysicsService().getPhysics().update(); entity.update(); @@ -93,7 +93,7 @@ public void testUpdateTowerStateWithTargetNotInRange() { entity.getEvents().addListener(StunTowerCombatTask.IDLE, idle); entity.getEvents().addListener(StunTowerCombatTask.ATTACK, attack); - stunTowerCombatTask.towerState = StunTowerCombatTask.STATE.IDLE; + stunTowerCombatTask.setState(StunTowerCombatTask.STATE.IDLE); ServiceLocator.getPhysicsService().getPhysics().update(); entity.update(); diff --git a/source/core/src/test/com/csse3200/game/components/tasks/TNTTowerCombatTaskTest.java b/source/core/src/test/com/csse3200/game/components/tasks/TNTTowerCombatTaskTest.java index 65a0e4724..74ff509f7 100644 --- a/source/core/src/test/com/csse3200/game/components/tasks/TNTTowerCombatTaskTest.java +++ b/source/core/src/test/com/csse3200/game/components/tasks/TNTTowerCombatTaskTest.java @@ -20,8 +20,6 @@ @ExtendWith(MockitoExtension.class) public class TNTTowerCombatTaskTest { - - TNTTowerCombatTask tntTowerCombatTask; @BeforeEach @@ -37,7 +35,6 @@ void setUp() { @Test public void testStartTriggersDefaultEvent() { - Entity entity = createTNT(); EventListener0 defaultStartListener = mock(EventListener0.class); @@ -50,7 +47,6 @@ public void testStartTriggersDefaultEvent() { @Test public void testUpdateTowerStateWithTargetInRange() { - Entity entity = createTNT(); entity.setPosition(10,10); @@ -90,12 +86,10 @@ public void testUpdateTowerStateWithTargetInRange() { tntTowerCombatTask.updateTowerState(); // Set flag to dispose assertTrue(tntTowerCombatTask.isReadyToDelete()); - } @Test public void testStayAtIdleWhenNoTargetInRange() { - Entity entity = createTNT(); entity.setPosition(10,10); @@ -117,7 +111,6 @@ public void testStayAtIdleWhenNoTargetInRange() { verifyNoInteractions(defaultStartListener); // still in idle assertEquals(TNTTowerCombatTask.STATE.IDLE, tntTowerCombatTask.getState()); - } Entity createTNT() { @@ -128,7 +121,6 @@ Entity createTNT() { .addComponent(new ColliderComponent()); entity.create(); return entity; - } Entity createNPC() { @@ -139,6 +131,4 @@ Entity createNPC() { Target.create(); return Target; } - - } diff --git a/source/core/src/test/com/csse3200/game/entities/factories/WaveFactoryTest.java b/source/core/src/test/com/csse3200/game/entities/factories/WaveFactoryTest.java index 6abe8ec1a..eca488c8f 100644 --- a/source/core/src/test/com/csse3200/game/entities/factories/WaveFactoryTest.java +++ b/source/core/src/test/com/csse3200/game/entities/factories/WaveFactoryTest.java @@ -1,232 +1,298 @@ -//package com.csse3200.game.entities.factories; -// -//import com.csse3200.game.components.tasks.waves.LevelWaves; -//import com.badlogic.gdx.assets.AssetManager; -//import com.csse3200.game.components.tasks.waves.LevelWaves; -//import com.csse3200.game.components.tasks.waves.WaveClass; -//import com.csse3200.game.extensions.GameExtension; -//import com.csse3200.game.physics.PhysicsService; -//import com.csse3200.game.rendering.DebugRenderer; -//import com.csse3200.game.rendering.RenderService; -//import com.csse3200.game.screens.GameLevelData; -//import com.csse3200.game.services.GameTime; -//import com.csse3200.game.services.ResourceService; -//import com.csse3200.game.services.ServiceLocator; -//import com.csse3200.game.services.WaveService; -//import org.junit.jupiter.api.BeforeEach; -//import org.junit.jupiter.api.Disabled; -//import org.junit.jupiter.api.Test; -//import org.junit.jupiter.api.extension.ExtendWith; -//import org.mockito.junit.jupiter.MockitoExtension; -// -//import static org.junit.jupiter.api.Assertions.*; -//import static org.mockito.Mockito.*; -// -//import com.csse3200.game.entities.Entity; -// -//import java.security.Provider; -//import java.util.ArrayList; -//import java.util.Arrays; -//import java.util.List; -//import java.util.Map; -// -//@ExtendWith(GameExtension.class) -//@ExtendWith(MockitoExtension.class) -//class WaveFactoryTest { -// -// private LevelWaves lvl1; -// private LevelWaves lvl2; -// private LevelWaves lvl3; -// -// private final int MIN_HEALTH = 60; -// private final int MIN_BOSS_HEALTH = 80; -// -// // level stats for level 1 - water planet -// private final int LVL1_DIFF = 2; -// private final int LVL1_WAVES = 5; -// private final int LVL1_CHOSEN_LVL = 1; -// private final ArrayList LVL1_MOBS = new ArrayList<>(Arrays.asList("Coat", "SplittingWaterSlime", "WaterQueen")); -// private final String LVL1_BOSS = "IceBoss"; -// -// // level stats for level 2 - magic planet -// private final int LVL2_DIFF = 3; -// private final int LVL2_WAVES = 10; -// private final int LVL2_CHOSEN_LVL = 0; -// private final ArrayList LVL2_MOBS = new ArrayList<>(Arrays.asList("ArcaneArcher", "SplittingNightBorne", "Skeleton", "DeflectWizard")); -// private final String LVL2_BOSS = "PatrickBoss"; -// -// // level stats for level 3 - fire planet -// private final int LVL3_DIFF = 5; -// private final int LVL3_WAVES = 15; -// private final int LVL3_CHOSEN_LVL = 2; -// private final ArrayList LVL3_MOBS = new ArrayList<>(Arrays.asList("Xeno", "DodgingDragon", "FireWorm")); -// private final String LVL3_BOSS = "FireBoss"; -//// private final String LVL3_BOSS = "FireBoss"; -// //TODO: make this a fire boss in sprint 4 -// -// private static final String[] waveSounds = { -// "sounds/waves/wave-start/Wave_Start_Alarm.ogg", -// "sounds/waves/wave-end/Wave_Over_01.ogg" -// }; -// -// @BeforeEach -// void setUp() { -// GameTime gameTime = mock(GameTime.class); -// ServiceLocator.registerTimeSource(gameTime); -// ServiceLocator.registerPhysicsService(new PhysicsService()); -// RenderService render = new RenderService(); -// render.setDebug(mock(DebugRenderer.class)); -// ServiceLocator.registerRenderService(render); -// ResourceService resourceService = mock(ResourceService.class); -// ServiceLocator.registerResourceService(resourceService); -// WaveService waveService = new WaveService(); -// ServiceLocator.registerWaveService(waveService); -// ServiceLocator.getResourceService().loadSounds(waveSounds); -// -// lvl1 = WaveFactory.createLevel(LVL1_DIFF, LVL1_WAVES, LVL1_CHOSEN_LVL); -// lvl2 = WaveFactory.createLevel(LVL2_DIFF, LVL2_WAVES, LVL2_CHOSEN_LVL); -// lvl3 = WaveFactory.createLevel(LVL3_DIFF, LVL3_WAVES, LVL3_CHOSEN_LVL); -// } -// -// @Test -// void createBaseWaves() { -// GameLevelData.setSelectedLevel(0); -// Entity level1 = WaveFactory.createWaves(); -// assertNotNull(level1); -// -// GameLevelData.setSelectedLevel(1); -// Entity level2 = WaveFactory.createWaves(); -// assertNotNull(level2); -// -// GameLevelData.setSelectedLevel(2); -// Entity level3 = WaveFactory.createWaves(); -// assertNotNull(level3); -// } -// -// @Test -// void testCreateLevel() { -// assertNotNull(lvl1); -// assertNotNull(lvl2); -// assertNotNull(lvl3); -// } -// -// /** -// * The three following tests ensure that every wave in the level is created correctly -// * Since the waves are stored in a hashmap, by definition the mobs are unique and this -// * quality does not have to be checked. -// * */ -// @Test -// void testLevel1Creation() { -// List lvl1Mobs = lvl1.getWaves(); -// -// int waveNum = 1; -// for (WaveClass wave : lvl1Mobs) { -// -// // check the number of mobs in a wave -// if (waveNum % 5 != 0) { -// assertEquals(2, wave.getEntities().size(), "Wave should contain 2 mobs."); -// } else { -// assertEquals(3, wave.getEntities().size(), "Wave should contain 3 mobs: 2 general and 1 boss."); -// } -// -// // check if the boss is in the wave if it is a boss wave -// if (waveNum % 5 == 0) { -// assertTrue(wave.getEntities().containsKey(LVL1_BOSS), "This wave should contain a boss."); -// } -// -// // check the health of the mobs and ensure the mobs are the correct type -// for (Map.Entry entry : wave.getEntities().entrySet()) { -// String mob = entry.getKey(); -// int[] spawn = entry.getValue(); -// -// if (waveNum % 5 != 0) { -// assertTrue(LVL1_MOBS.contains(mob), "This mob is not assigned to this level."); -// assertEquals(MIN_HEALTH + waveNum, spawn[1], "The health of the mob should be " + MIN_HEALTH + waveNum + " ."); -// } else { -// if (mob == LVL1_BOSS) { -// assertEquals(MIN_BOSS_HEALTH + waveNum, spawn[1], "The health of the boss should be " + MIN_BOSS_HEALTH + waveNum + " ."); -// } -// } -// } -// -// waveNum++; -// } -// assertEquals(6, waveNum, "The should be 5 waves making numWave 6."); -// } -// @Test -// void testLevel2Creation() { -// -// List lvl1Mobs = lvl2.getWaves(); -// -// int waveNum = 1; -// for (WaveClass wave : lvl1Mobs) { -// -// // check the number of mobs in a wave -// if (waveNum % 5 != 0) { -// assertEquals(2, wave.getEntities().size(), "Wave should contain 2 mobs."); -// } else { -// assertEquals(3, wave.getEntities().size(), "Wave should contain 3 mobs: 2 general and 1 boss."); -// } -// -// // check if the boss is in the wave if it is a boss wave -// if (waveNum % 5 == 0) { -// assertTrue(wave.getEntities().containsKey(LVL2_BOSS), "This wave should contain a boss."); -// } -// -// for (Map.Entry entry : wave.getEntities().entrySet()) { -// String mob = entry.getKey(); -// int[] spawn = entry.getValue(); -// -// if (waveNum % 5 != 0) { -// assertTrue(LVL2_MOBS.contains(mob)); -// assertEquals(MIN_HEALTH + (waveNum * 2), spawn[1], "The health of the mob should be " + MIN_HEALTH + (waveNum * 2) + " ."); -// } else { -// if (mob == LVL2_BOSS) { -// assertEquals(MIN_BOSS_HEALTH + (waveNum * 2), spawn[1], "The health of the boss should be " + MIN_BOSS_HEALTH + (waveNum * 2) + " ."); -// } -// } -// } -// -// waveNum++; -// } -// assertEquals(11, waveNum, "There should be 10 waves making numWave 11."); -// } -// @Test -// void testLevel3Creation() { -// -// List lvl1Mobs = lvl3.getWaves(); -// -// int waveNum = 1; -// for (WaveClass wave : lvl1Mobs) { -// // check the number of mobs in a wave -// if (waveNum % 5 != 0) { -// assertEquals(2, wave.getEntities().size(), "Wave should contain 2 mobs."); -// } else { -// assertEquals(3, wave.getEntities().size(), "Wave should contain 3 mobs: 2 general and 1 boss."); -// } -// -// // check if the boss is in the wave if it is a boss wave -// if (waveNum % 5 == 0) { -// assertTrue(wave.getEntities().containsKey(LVL3_BOSS), "This wave should contain a boss."); -// } -// -// // check the health of the mobs and ensure the mobs are the correct type -// for (Map.Entry entry : wave.getEntities().entrySet()) { -// String mob = entry.getKey(); -// int[] spawn = entry.getValue(); -// -// if (waveNum % 5 != 0) { -// assertTrue(LVL3_MOBS.contains(mob)); -// assertEquals(MIN_HEALTH + (waveNum * 3), spawn[1], "The health of the mob should be " + MIN_HEALTH + (waveNum * 3) + " ."); -// } else { -// if (mob == LVL3_BOSS) { -// assertEquals(MIN_BOSS_HEALTH + (waveNum * 3), spawn[1], "The health of the boss should be " + MIN_BOSS_HEALTH + (waveNum * 3) + " ."); -// } -// } -// } -// waveNum++; -// } -// assertEquals(16, waveNum, "There should be 15 waves making numWave 16."); -// } -// -//} +package com.csse3200.game.entities.factories; + +import com.csse3200.game.components.tasks.waves.LevelWaves; +import com.csse3200.game.components.tasks.waves.WaveClass; +import com.csse3200.game.extensions.GameExtension; +import com.csse3200.game.physics.PhysicsService; +import com.csse3200.game.rendering.DebugRenderer; +import com.csse3200.game.rendering.RenderService; +import com.csse3200.game.screens.GameLevelData; +import com.csse3200.game.services.GameTime; +import com.csse3200.game.services.ResourceService; +import com.csse3200.game.services.ServiceLocator; +import com.csse3200.game.services.WaveService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; +import com.csse3200.game.entities.Entity; +import java.util.*; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + + + +@ExtendWith(GameExtension.class) +@ExtendWith(MockitoExtension.class) +class WaveFactoryTest { + + private LevelWaves lvl1; + private LevelWaves lvl2; + private LevelWaves lvl3; + + private final int MIN_MELEE_HEALTH = 80; + private final int MIN_RANGE_HEALTH = 60; + private final int MIN_BOSS_HEALTH = 80; + private final int LVL1_LVL = 1; + private final int LVL2_LVL = 2; + private final int LVL3_LVL = 3; + private static final ArrayList MELEE_MOBS = new ArrayList<>(Arrays.asList( + "Skeleton", "Coat", "DragonKnight", "Necromancer" + )); + + private static final ArrayList> LVL1_WAVES_STRUC = new ArrayList<>(Arrays.asList( + new ArrayList<>(Arrays.asList("Coat" + )), new ArrayList<>(Arrays.asList("Coat", "WaterQueen" + )), new ArrayList<>(Arrays.asList("WaterQueen", "SplittingWaterSlime" + )), new ArrayList<>(Arrays.asList("Coat", "WaterQueen", "SplittingWaterSlime" + )) + )); + + private static final ArrayList> LVL2_WAVES_STRUC = new ArrayList<>(Arrays.asList( + new ArrayList<>(Arrays.asList("Skeleton" + )), new ArrayList<>(Arrays.asList("Skeleton", "ArcaneArcher" + )), new ArrayList<>(Arrays.asList("Skeleton", "Wizard" + )), new ArrayList<>(Arrays.asList("Skeleton", "SplittingNightBorne" + )), new ArrayList<>(Arrays.asList("Wizard", "SplittingNightBorne" + )), new ArrayList<>(Arrays.asList("SplittingNightBorne", "Skeleton" + )), new ArrayList<>(Arrays.asList("Wizard", "SplittingNightBorne" + )), new ArrayList<>(Arrays.asList("ArcaneArcher", "SplittingNightBorne", "Wizard" + )), new ArrayList<>(Arrays.asList("Skeleton", "ArcaneArcher", "Wizard", "SplittingNightBorne" + )) + )); + + private static final ArrayList> LVL3_WAVES_STRUC = new ArrayList<>(Arrays.asList( + new ArrayList<>(Arrays.asList("Necromancer" + )), new ArrayList<>(Arrays.asList("Necromancer", "DodgingDragon" + )), new ArrayList<>(Arrays.asList("Necromancer", "FireWorm" + )), new ArrayList<>(Arrays.asList("Necromancer", "DeflectFireWizard" + )), new ArrayList<>(Arrays.asList("DeflectFireWizard", "FireWorm" + )), new ArrayList<>(Arrays.asList("DodgingDragon", "FireWorm" + )), new ArrayList<>(Arrays.asList("DodgingDragon", "Necromancer" + )), new ArrayList<>(Arrays.asList("FireWorm", "Necromancer" + )), new ArrayList<>(Arrays.asList("DeflectFireWizard", "Necromancer" + )), new ArrayList<>(Arrays.asList("DodgingDragon", "DeflectFireWizard", "Necromancer" + )), new ArrayList<>(Arrays.asList("FireWorm", "Necromancer", "DodgingDragon" + )), new ArrayList<>(Arrays.asList("FireWorm", "SplittingRocky", "Necromancer" + )), new ArrayList<>(Arrays.asList("SplittingRocky", "DeflectFireWizard", "FireWorm" + )), new ArrayList<>(Arrays.asList("DeflectFireWizard", "SplittingRocky", "Necromancer", "DodgingDragon", "FireWorm" + )) + )); + + private static final String[] waveSounds = { + "sounds/waves/wave-start/Wave_Start_Alarm.ogg", + "sounds/waves/wave-end/Wave_Over_01.ogg" + }; + + @BeforeEach + void setUp() { + GameTime gameTime = mock(GameTime.class); + ServiceLocator.registerTimeSource(gameTime); + ServiceLocator.registerPhysicsService(new PhysicsService()); + RenderService render = new RenderService(); + render.setDebug(mock(DebugRenderer.class)); + ServiceLocator.registerRenderService(render); + ResourceService resourceService = mock(ResourceService.class); + ServiceLocator.registerResourceService(resourceService); + WaveService waveService = new WaveService(); + ServiceLocator.registerWaveService(waveService); + ServiceLocator.getResourceService().loadSounds(waveSounds); + + lvl1 = WaveFactory.createLevel(LVL1_LVL); + lvl2 = WaveFactory.createLevel(LVL2_LVL); + lvl3 = WaveFactory.createLevel(LVL3_LVL); + } + + @Test + void createBaseWaves() { + GameLevelData.setSelectedLevel(0); + Entity level1 = WaveFactory.createWaves(); + assertNotNull(level1); + + GameLevelData.setSelectedLevel(1); + Entity level2 = WaveFactory.createWaves(); + assertNotNull(level2); + + GameLevelData.setSelectedLevel(2); + Entity level3 = WaveFactory.createWaves(); + assertNotNull(level3); + } + + @Test + void testCreateLevel() { + assertNotNull(lvl1); + assertNotNull(lvl2); + assertNotNull(lvl3); + } + + /** + * The three following tests ensure that every wave in the level is created correctly + * Since the waves are stored in a hashmap, by definition the mobs are unique and this + * quality does not have to be checked. + * */ + @Test + void testLevel1Creation() { + List lvl1Mobs = lvl1.getWaves(); + int bossHealth = 500; + int mobCount = 5; + + int waveNum = 1; + for (WaveClass wave : lvl1Mobs) { + int mobsRemaining = wave.getEntities().size() - 1; + int totalMobsSpawned = 0; + + // check the number of mobs in a wave + if (waveNum == 5 || waveNum == 1) { + assertEquals(1, wave.getEntities().size(), "Wave should contain 1 mob."); + } else if (waveNum == 2 || waveNum == 3) { + assertEquals(2, wave.getEntities().size(), "Wave should contain 2 mobs."); + } else { + assertEquals(3, wave.getEntities().size(), "Wave should contain 3 mobs."); + } + + + if (waveNum != 5) { + Set mobNames = new HashSet<>(wave.getEntities().keySet()); + Set expectedMobNames = new HashSet<>(LVL1_WAVES_STRUC.get(waveNum - 1)); + assertTrue(mobNames.equals(expectedMobNames), "The mobs in the wave should be " + expectedMobNames + " ."); + + for (String key: wave.getEntities().keySet()) { + int[] values = wave.getEntities().get(key); + assertTrue(values[0] > 1 && values[0] <= (mobCount - totalMobsSpawned - (2 * mobsRemaining))); + totalMobsSpawned += values[0]; + mobsRemaining --; + + if (MELEE_MOBS.contains(key)) { + assertTrue(values[1] == MIN_MELEE_HEALTH + waveNum, "The health of the mob should be " + MIN_MELEE_HEALTH + waveNum + " ."); + } else { + assertTrue(values[1] == MIN_RANGE_HEALTH + waveNum, "The health of the mob should be " + MIN_RANGE_HEALTH + waveNum + " ."); + } + } + } else { + assertTrue(wave.getEntities().keySet().size() == 1); + for (String key: wave.getEntities().keySet()) { + int[] values = wave.getEntities().get(key); + assertTrue(values[1] == bossHealth, "The health of the boss should be " + MIN_BOSS_HEALTH); + } + } + mobCount ++; + waveNum++; + } + assertEquals(6, waveNum, "The should be 5 waves making numWave 6."); + } + @Test + void testLevel2Creation() { + + List lvl2Mobs = lvl2.getWaves(); + int bossHealth = 1000; + int mobCount = 6; + + int waveNum = 1; + for (WaveClass wave : lvl2Mobs) { + int mobsRemaining = wave.getEntities().size() - 1; + int totalMobsSpawned = 0; + + // check the number of mobs in a wave + if (waveNum == 1 || waveNum == 10) { + assertEquals(1, wave.getEntities().size(), "Wave should contain 1 mob."); + } else if (1 < waveNum && waveNum < 8) { + assertEquals(2, wave.getEntities().size(), "Wave should contain 2 mobs."); + } else if (waveNum == 8){ + assertEquals(3, wave.getEntities().size(), "Wave should contain 3 mobs."); + } else { + assertEquals(4, wave.getEntities().size(), "Wave should contain 4 mobs."); + } + + if (waveNum != 10) { + Set mobNames = new HashSet<>(wave.getEntities().keySet()); + Set expectedMobNames = new HashSet<>(LVL2_WAVES_STRUC.get(waveNum - 1)); + assertTrue(mobNames.equals(expectedMobNames), "The mobs in the wave should be " + expectedMobNames + " ."); + + for (String key: wave.getEntities().keySet()) { + int[] values = wave.getEntities().get(key); + + assertTrue(values[0] > 1 && values[0] <= (mobCount - totalMobsSpawned - (2 * mobsRemaining))); + totalMobsSpawned += values[0]; + mobsRemaining --; + System.out.println("wave is: "+ wave); + + if (MELEE_MOBS.contains(key)) { + System.out.println("the health is: " + values[1]); + System.out.println("I want it to be: " + (MIN_MELEE_HEALTH + (waveNum * 2))); + + assertEquals(values[1], (MIN_MELEE_HEALTH + (waveNum * 2)), "The health of the mob should be " + (MIN_MELEE_HEALTH + (waveNum * 2)) + " ."); + } else { + assertEquals(values[1], (MIN_RANGE_HEALTH + (waveNum * 2)), "The health of the mob should be " + (MIN_RANGE_HEALTH + (waveNum * 2)) + " ."); + } + } + + } else { + assertTrue(wave.getEntities().keySet().size() == 1); + for (String key: wave.getEntities().keySet()) { + int[] values = wave.getEntities().get(key); + assertTrue(values[1] == bossHealth, "The health of the boss should be " + MIN_BOSS_HEALTH); + } + } + mobCount ++; + waveNum++; + } + assertEquals(11, waveNum, "There should be 10 waves making numWave 11."); + } + @Test + void testLevel3Creation() { + + List lvl3Mobs = lvl3.getWaves(); + + int bossHealth = 2000; + int mobCount = 8; + + int waveNum = 1; + for (WaveClass wave : lvl3Mobs) { + int mobsRemaining = wave.getEntities().size() - 1; + int totalMobsSpawned = 0; + + // check the number of mobs in a wave + if (waveNum == 1 || waveNum == 15) { + assertEquals(1, wave.getEntities().size(), "Wave should contain 1 mob."); + } else if (1 < waveNum && waveNum < 10) { + assertEquals(2, wave.getEntities().size(), "Wave should contain 2 mobs."); + } else if (9 < waveNum && waveNum < 14){ + assertEquals(3, wave.getEntities().size(), "Wave should contain 3 mobs."); + } else if (waveNum == 14){ + assertEquals(5, wave.getEntities().size(), "Wave should contain 4 mobs."); + } + + if (waveNum != 15) { + Set mobNames = new HashSet<>(wave.getEntities().keySet()); + Set expectedMobNames = new HashSet<>(LVL3_WAVES_STRUC.get(waveNum - 1)); + assertTrue(mobNames.equals(expectedMobNames), "The mobs in the wave should be " + expectedMobNames + " ."); + + for (String key: wave.getEntities().keySet()) { + int[] values = wave.getEntities().get(key); + + assertTrue(values[0] > 1 && values[0] <= (mobCount - totalMobsSpawned - (2 * mobsRemaining))); + totalMobsSpawned += values[0]; + mobsRemaining --; + + if (MELEE_MOBS.contains(key)) { + assertEquals(values[1], (MIN_MELEE_HEALTH + (waveNum * 3)), "The health of the mob should be " + (MIN_MELEE_HEALTH + (waveNum * 2)) + " ."); + } else { + assertEquals(values[1], (MIN_RANGE_HEALTH + (waveNum * 3)), "The health of the mob should be " + (MIN_RANGE_HEALTH + (waveNum * 2)) + " ."); + } + } + + } else { + assertTrue(wave.getEntities().keySet().size() == 1); + for (String key: wave.getEntities().keySet()) { + int[] values = wave.getEntities().get(key); + assertTrue(values[1] == bossHealth, "The health of the boss should be " + MIN_BOSS_HEALTH); + } + } + mobCount ++; + waveNum++; + } + assertEquals(16, waveNum, "There should be 15 waves making numWave 16."); + } + +}