diff --git a/source/core/assets/images/mobs/skeleton.atlas b/source/core/assets/images/mobs/skeleton.atlas index f0117d879..9e1c78e17 100644 --- a/source/core/assets/images/mobs/skeleton.atlas +++ b/source/core/assets/images/mobs/skeleton.atlas @@ -69,7 +69,7 @@ skeleton_attack index: -1 skeleton_attack rotate: false - xy: 514, 2 + xy: 578, 52 size: 62, 48 orig: 62, 48 offset: 0, 0 @@ -83,7 +83,7 @@ skeleton_attack index: -1 skeleton_attack rotate: false - xy: 770, 2 + xy: 834, 52 size: 62, 48 orig: 62, 48 offset: 0, 0 @@ -95,41 +95,6 @@ skeleton_attack orig: 62, 48 offset: 0, 0 index: -1 -skeleton_death - rotate: false - xy: 1026, 2 - size: 62, 48 - orig: 62, 48 - offset: 0, 0 - index: -1 -skeleton_death - rotate: false - xy: 66, 52 - size: 62, 48 - orig: 62, 48 - offset: 0, 0 - index: -1 -skeleton_death - rotate: false - xy: 834, 52 - size: 62, 48 - orig: 62, 48 - offset: 0, 0 - index: -1 -skeleton_death - rotate: false - xy: 1154, 55 - size: 62, 45 - orig: 62, 45 - offset: 0, 0 - index: -1 -skeleton_death - rotate: false - xy: 578, 2 - size: 62, 48 - orig: 62, 48 - offset: 0, 0 - index: -1 skeleton_death rotate: false xy: 194, 52 @@ -188,7 +153,7 @@ skeleton_walk index: -1 skeleton_walk rotate: false - xy: 514, 52 + xy: 514, 2 size: 62, 48 orig: 62, 48 offset: 0, 0 @@ -202,7 +167,7 @@ skeleton_walk index: -1 skeleton_walk rotate: false - xy: 770, 52 + xy: 770, 2 size: 62, 48 orig: 62, 48 offset: 0, 0 @@ -237,21 +202,21 @@ skeleton_walk index: -1 skeleton_walk rotate: false - xy: 578, 52 + xy: 514, 52 size: 62, 48 orig: 62, 48 offset: 0, 0 index: -1 skeleton_walk rotate: false - xy: 130, 2 + xy: 66, 52 size: 62, 48 orig: 62, 48 offset: 0, 0 index: -1 skeleton_walk rotate: false - xy: 834, 2 + xy: 770, 52 size: 62, 48 orig: 62, 48 offset: 0, 0 diff --git a/source/core/assets/images/mobs/skeleton.png b/source/core/assets/images/mobs/skeleton.png index cbcbd1ed1..9d75bb066 100644 Binary files a/source/core/assets/images/mobs/skeleton.png and b/source/core/assets/images/mobs/skeleton.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..7e4dc5eb1 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,33 @@ 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 + imageChecked: pierce_tower_selected + imageCheckedDown: pierce_tower_selected + imageCheckedOver: pierce_tower_over + } + ricochet_tower: { + imageUp: ricochet-tower-default + imageDown: ricochet_tower_selected + imageOver: ricochet_tower_over + imageDisabled: ricochet_tower_disabled + imageChecked: ricochet_tower_selected + imageCheckedDown: ricochet_tower_selected + imageCheckedOver: ricochet_tower_over + } + fireworks_tower: { + imageUp: firework-tower-default + imageDown: firework_tower_selected + imageOver: firework_tower_over + imageDisabled: firework_tower_disabled + imageChecked: firework_tower_selected + imageCheckedDown: firework_tower_selected + imageCheckedOver: firework_tower_over + } } 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/assets/sounds/towers/12-Gauge-Pump-Action-Shotgun-Close-Gunshot.mp3 b/source/core/assets/sounds/towers/12-Gauge-Pump-Action-Shotgun-Close-Gunshot.mp3 new file mode 100644 index 000000000..61bc03e66 Binary files /dev/null and b/source/core/assets/sounds/towers/12-Gauge-Pump-Action-Shotgun-Close-Gunshot.mp3 differ diff --git a/source/core/assets/sounds/towers/5.56_single_shot.mp3 b/source/core/assets/sounds/towers/5.56_single_shot.mp3 new file mode 100644 index 000000000..0611f722a Binary files /dev/null and b/source/core/assets/sounds/towers/5.56_single_shot.mp3 differ diff --git a/source/core/assets/sounds/towers/Desert-Eagle-Far-Single-Gunshot.mp3 b/source/core/assets/sounds/towers/Desert-Eagle-Far-Single-Gunshot.mp3 new file mode 100644 index 000000000..5e39881ce Binary files /dev/null and b/source/core/assets/sounds/towers/Desert-Eagle-Far-Single-Gunshot.mp3 differ diff --git a/source/core/assets/sounds/towers/ar15_single_shot_far.mp3 b/source/core/assets/sounds/towers/ar15_single_shot_far.mp3 new file mode 100644 index 000000000..34ef353ee Binary files /dev/null and b/source/core/assets/sounds/towers/ar15_single_shot_far.mp3 differ diff --git a/source/core/assets/sounds/towers/eco_tower_ping.mp3 b/source/core/assets/sounds/towers/eco_tower_ping.mp3 new file mode 100644 index 000000000..1553f6001 Binary files /dev/null and b/source/core/assets/sounds/towers/eco_tower_ping.mp3 differ diff --git a/source/core/assets/sounds/towers/explosion.mp3 b/source/core/assets/sounds/towers/explosion.mp3 new file mode 100644 index 000000000..ab19a2947 Binary files /dev/null and b/source/core/assets/sounds/towers/explosion.mp3 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 8fccaf74b..678301e15 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -201,10 +201,14 @@ public class ForestGameArea extends GameArea { "sounds/mobBoss/patrickThunder.mp3", "sounds/mobBoss/patrickHit.mp3", "sounds/mobBoss/spawnDemonSlime.mp3", + "sounds/towers/Desert-Eagle-Far-Single-Gunshot.mp3", + "sounds/towers/5.56_single_shot.mp3", + "sounds/towers/explosion.mp3", + "sounds/towers/eco_tower_ping.mp3", + "sounds/towers/ar15_single_shot_far.mp3", "sounds/mobs/skeletonHit.mp3", "sounds/mobs/coatAttack.mp3", "sounds/mobs/archerArrow.mp3" - }; private static final String BACKGROUND_MUSIC = "sounds/background/Sci-Fi1.ogg"; @@ -243,6 +247,37 @@ private void stopWaveTimer() { } } + /** + * Cases to spawn a wave + */ +// private void spawnWave() { +// wave++; +// switch (wave) { +// case 1: +// case 2: +// spawnFireWorm(); +// spawnDragonKnight(); +// +// break; +// case 3: +// spawnSkeleton(); +// spawnWizard(); +// // mobBoss2 = spawnMobBoss2(); +// break; +// case 4: +// spawnWaterQueen(); +// spawnWaterSlime(); +// // mobBoss2 = spawnMobBoss2(); +// +// break; +// case 5: +// spawnDemonBoss(); +// default: +// // Handle other wave scenarios if needed +// break; +// } +// } + /** * Create the game area, including terrain, static entities (trees), dynamic entities (player) */ @@ -263,34 +298,14 @@ public void create() { waves = WaveFactory.createWaves(); spawnEntity(waves); waves.getEvents().addListener("spawnWave", this::spawnMob); - // spawnCoat(); -// spawnDodgingDragonKnight(17,4); -// spawnDeflectWizard(17, 3); -// spawnSplittingXenoGrunt(17, 2); -// spawnPatrick(); -// spawnDemonBoss(); - // spawnSplittingRocky(17, 4); - // spawnFireWizard(17, 3); - // spawnNecromancer(17, 2); - - - spawnScrap(); spawnGapScanners(); - -// spawnTNTTower(); -// spawnWeaponTower(); -// spawnGapScanners(); -// spawnDroidTower(); -// spawnFireWorksTower(); // Commented these out until they are needed for Demonstration -// spawnPierceTower(); -// spawnRicochetTower(); -// spawnBombship(); } - + private void displayUI() { Entity ui = new Entity(); +// ui.addComponent(new GameAreaDisplay("Box Forest")); TODO: This should be the level name? ui.addComponent(ServiceLocator.getGameEndService().getDisplay()); ui.addComponent(ServiceLocator.getCurrencyService().getDisplay()); spawnEntity(ui); @@ -344,90 +359,6 @@ private Entity spawnPlayer(GridPoint2 position) { return newPlayer; } - // commented 383 - 386 out as there was a missing arg? - private void spawnDemonBoss() { - Entity demon = MobBossFactory.createDemonBoss(5000); - spawnEntityAt(demon, new GridPoint2(19, 5), true, false); - } - - private void spawnPatrick() { - Entity patrick = MobBossFactory.createPatrickBoss(3000); - spawnEntityAt(patrick, new GridPoint2(18, 5), true, false); - } - - private void spawnPatrickDeath() { - Entity patrickDeath = MobBossFactory.patrickDead(); - spawnEntityAt(patrickDeath, new GridPoint2(18, 5), true, false); - } - // commented 398 - 401 out as there was a missing arg? -// private void spawnIceBaby() { -// Entity iceBaby = MobBossFactory.createIceBoss(); -// spawnEntityAt(iceBaby, new GridPoint2(19, 5), true, false); -// } - -// private void spawnDemonBoss() { -// Entity demon = MobBossFactory.createDemonBoss(); -// spawnEntityAt(demon, new GridPoint2(19, 5), true, false); -// } - -// private void spawnPatrick() { -// Entity patrick = MobBossFactory.createPatrickBoss(3000); -// spawnEntityAt(patrick, new GridPoint2(18, 5), true, false); -// } -// -// private void spawnPatrickDeath() { -// Entity patrickDeath = MobBossFactory.patrickDead(); -// spawnEntityAt(patrickDeath, new GridPoint2(18, 5), true, false); -// } -// -// private void spawnIceBaby() { -// Entity iceBaby = MobBossFactory.createIceBoss(); -// spawnEntityAt(iceBaby, new GridPoint2(19, 5), true, false); -// } - - /** - * Spawns a projectile that only heads towards the enemies in its lane. - * - * @param position The position of the Entity that's shooting the projectile. - * @param targetLayer The enemy layer of the "shooter". - * @param direction The direction the projectile should head towards. - * @param speed The speed of the projectiles. - */ - private void spawnProjectile(Vector2 position, short targetLayer, int direction, Vector2 speed) { - Entity Projectile = ProjectileFactory.createFireBall(targetLayer, new Vector2(direction, position.y), speed); - Projectile.setPosition(position); - spawnEntity(Projectile); - } - - /** - * Spawns a projectile specifically for general mobs/xenohunters - * - * @param position The position of the Entity that's shooting the projectile. - * @param targetLayer The enemy layer of the "shooter". - * @param direction The direction the projectile should head towards. - * @param speed The speed of the projectiles. - */ - private void spawnProjectileTest(Vector2 position, short targetLayer, int direction, Vector2 speed) { - Entity Projectile = ProjectileFactory.createEngineerBullet(targetLayer, new Vector2(direction, position.y), speed); - Projectile.setPosition(position); - spawnEntity(Projectile); - } - - /** - * Spawns a projectile to be used for multiple projectile function. - * - * @param position The position of the Entity that's shooting the projectile. - * @param targetLayer The enemy layer of the "shooter". - * @param space The space between the projectiles' destination. - * @param direction The direction the projectile should head towards. - * @param speed The speed of the projectiles. - */ - private void spawnProjectile(Vector2 position, short targetLayer, int space, int direction, Vector2 speed) { - Entity Projectile = ProjectileFactory.createFireBall(targetLayer, new Vector2(direction, position.y + space), speed); - Projectile.setPosition(position); - spawnEntity(Projectile); - } - /** * Spawn an entity on the map. Is called during a wave. Add cases here for each mob type * @param entity mob to be spawned @@ -437,6 +368,9 @@ private void spawnProjectile(Vector2 position, short targetLayer, int space, int public void spawnMob(String entity, GridPoint2 randomPos, int health) { Entity mob; switch (entity) { + case "Xeno": + mob = NPCFactory.createXenoGrunt(health); + break; case "SplittingWaterSlime": mob = NPCFactory.createSplittingWaterSlime(health); break; @@ -449,7 +383,7 @@ public void spawnMob(String entity, GridPoint2 randomPos, int health) { case "Skeleton": mob = NPCFactory.createSkeleton(health); break; - case "DeflectWizard": + case "Wizard": mob = NPCFactory.createWizard(health); break; case "WaterQueen": @@ -461,6 +395,7 @@ public void spawnMob(String entity, GridPoint2 randomPos, int health) { case "IceBoss": mob = MobBossFactory.createIceBoss(health); break; + case "Coat": mob = NPCFactory.createCoat(health); break; @@ -473,15 +408,7 @@ public void spawnMob(String entity, GridPoint2 randomPos, int health) { case "ArcaneArcher": mob = NPCFactory.createDodgingArcaneArcher(health); break; - case "SplittingRocky": - mob = NPCFactory.createSplittingRocky(health); - break; - case "Necromancer": - mob = NPCFactory.createNecromancer(health); - break; - case "DeflectFireWizard": - mob = NPCFactory.createDeflectFireWizard(health); - break; + case "PatrickBoss": mob = MobBossFactory.createPatrickBoss(health); break; @@ -499,400 +426,6 @@ public void spawnMob(String entity, GridPoint2 randomPos, int health) { spawnEntityAt(mob, randomPos, true, false); } - // * TEMPORARY FOR TESTING -// private void spawnSplittingXenoGrunt(int x, int y) { -// GridPoint2 pos = new GridPoint2(x, y); -// Entity xenoGrunt = NPCFactory.createSplittingXenoGrunt(); -// xenoGrunt.setScale(1.5f, 1.5f); -// spawnEntityAt(xenoGrunt, pos, true, true); -// } - // * TEMPORARY FOR TESTING - private void spawnSplittingRocky(int x, int y) { - GridPoint2 pos = new GridPoint2(x, y); - Entity rocky = NPCFactory.createSplittingRocky(60); - rocky.setScale(1.5f, 1.5f); - spawnEntityAt(rocky, pos, true, true); - } - - private void spawnFireWizard(int x, int y) { - GridPoint2 pos = new GridPoint2(x, y); - Entity firewiz = NPCFactory.createDeflectFireWizard(60); - firewiz.setScale(1.5f, 1.5f); - spawnEntityAt(firewiz, pos, true, true); - } - - private void spawnNecromancer(int x, int y) { - GridPoint2 pos = new GridPoint2(x, y); - Entity Necromancer = NPCFactory.createNecromancer(60); - Necromancer.setScale(1.5f, 1.5f); - spawnEntityAt(Necromancer, pos, true, true); - } - - // * TEMPORARY FOR TESTING -// private void spawnDodgingDragonKnight(int x, int y) { -// GridPoint2 pos = new GridPoint2(x, y); -// Entity fireworm = NPCFactory.createDodgingDragonKnight(); -// fireworm.setScale(1.5f, 1.5f); -// spawnEntityAt(fireworm, pos, true, true); -// } -// -// // * TEMPORARY FOR TESTING -// private void spawnDeflectXenoGrunt(int x, int y) { -// GridPoint2 pos = new GridPoint2(x, y); -// Entity xenoGrunt = NPCFactory.createDeflectXenoGrunt(); -// xenoGrunt.setScale(1.5f, 1.5f); -// spawnEntityAt(xenoGrunt, pos, true, true); -// } -// -// private void spawnFireWorm() { -// int[] pickedLanes = random.ints(1, 7) -// .distinct().limit(5).toArray(); -// for (int i = 0; i < NUM_GRUNTS; i++) { -// GridPoint2 randomPos = new GridPoint2(19, pickedLanes[i]); -// Entity fireWorm = NPCFactory.createFireWorm(); -// fireWorm.setScale(1.5f, 1.5f); -// spawnEntityAt(fireWorm, randomPos, true, false); -// } -// } -// -// private void spawnSkeleton() { -// int[] pickedLanes = new Random().ints(1, 7) -// .distinct().limit(5).toArray(); -// for (int i = 0; i < NUM_GRUNTS; i++) { -// GridPoint2 randomPos = new GridPoint2(19, pickedLanes[i]); -// Entity skeleton = NPCFactory.createSkeleton(); -// skeleton.setScale(1.5f, 1.5f); -// spawnEntityAt(skeleton, randomPos, true, false); -// } -// } - -// private void spawnDragonKnight() { -// int[] pickedLanes = random.ints(1, 7) -// .distinct().limit(5).toArray(); -// for (int i = 0; i < NUM_GRUNTS; i++) { -// GridPoint2 randomPos = new GridPoint2(19, pickedLanes[i]); -// Entity fireWorm = NPCFactory.createDragonKnight(); -// fireWorm.setScale(1.5f, 1.5f); -// spawnEntityAt(fireWorm, randomPos, true, false); -// } -// } -// -// private void spawnWizard() { -// int[] pickedLanes = new Random().ints(1, 7) -// .distinct().limit(5).toArray(); -// for (int i = 0; i < NUM_GRUNTS; i++) { -// GridPoint2 randomPos = new GridPoint2(19, pickedLanes[i]); -// Entity wizard = NPCFactory.createWizard(); -// wizard.setScale(1.5f, 1.5f); -// spawnEntityAt(wizard, randomPos, true, false); -// } -// } -// -// private void spawnWaterQueen() { -// int[] pickedLanes = new Random().ints(1, 7) -// .distinct().limit(5).toArray(); -// for (int i = 0; i < NUM_GRUNTS; i++) { -// GridPoint2 randomPos = new GridPoint2(19, pickedLanes[i]); -// Entity waterQueen = NPCFactory.createWaterQueen(); -// waterQueen.setScale(1.5f, 1.5f); -// spawnEntityAt(waterQueen, randomPos, true, false); -// } -// } -// -// private void spawnWaterSlime() { -// int[] pickedLanes = new Random().ints(1, 7) -// .distinct().limit(5).toArray(); -// for (int i = 0; i < NUM_GRUNTS; i++) { -// GridPoint2 randomPos = new GridPoint2(19, pickedLanes[i]); -// Entity waterSlime = NPCFactory.createWaterSlime(); -// waterSlime.setScale(1.5f, 1.5f); -// spawnEntityAt(waterSlime, randomPos, true, false); -// } -// } - - // * TEMPORARY FOR TESTING - private void spawnDodgingDragonKnight(int x, int y) { - GridPoint2 pos = new GridPoint2(x, y); - Entity fireworm = NPCFactory.createDodgingDragonKnight(100); - fireworm.setScale(1.5f, 1.5f); - spawnEntityAt(fireworm, pos, true, true); - } -// -// // * TEMPORARY FOR TESTING - private void spawnDeflectWizard(int x, int y) { - GridPoint2 pos = new GridPoint2(x, y); - Entity xenoGrunt = NPCFactory.createDeflectWizard(100); - xenoGrunt.setScale(1.5f, 1.5f); - spawnEntityAt(xenoGrunt, pos, true, true); - } -// -// private void spawnFireWorm() { -// -// int[] pickedLanes = rand.ints(0, ServiceLocator.getMapService().getHeight() ) -// -// .distinct().limit(5).toArray(); -// for (int i = 0; i < NUM_GRUNTS; i++) { -// GridPoint2 randomPos = new GridPoint2(19, pickedLanes[i]); -// Entity fireWorm = NPCFactory.createFireWorm(); -// fireWorm.setScale(1.5f, 1.5f); -// spawnEntityAt(fireWorm, randomPos, true, false); -// } -// } -// -// private void spawnSkeleton() { -// -// int[] pickedLanes = new Random().ints(0, ServiceLocator.getMapService().getHeight() ) -// .distinct().limit(5).toArray(); -// for (int i = 0; i < NUM_GRUNTS; i++) { -// GridPoint2 randomPos = new GridPoint2(19, pickedLanes[i]); -// Entity skeleton = NPCFactory.createSkeleton(); -// skeleton.setScale(1.5f, 1.5f); -// spawnEntityAt(skeleton, randomPos, true, false); -// } -// } -// -// private void spawnDragonKnight() { -// -// int[] pickedLanes = rand.ints(0, ServiceLocator.getMapService().getHeight() ) -// -// .distinct().limit(5).toArray(); -// for (int i = 0; i < NUM_GRUNTS; i++) { -// GridPoint2 randomPos = new GridPoint2(19, pickedLanes[i]); -// Entity fireWorm = NPCFactory.createDodgingDragonKnight(); -// fireWorm.setScale(1.5f, 1.5f); -// spawnEntityAt(fireWorm, randomPos, true, false); -// } -// } -// -// private void spawnWizard() { -// -// int[] pickedLanes = rand.ints(0, ServiceLocator.getMapService().getHeight() ) -// -// .distinct().limit(5).toArray(); -// for (int i = 0; i < NUM_GRUNTS; i++) { -// GridPoint2 randomPos = new GridPoint2(19, pickedLanes[i]); -// Entity wizard = NPCFactory.createDeflectWizard(); -// wizard.setScale(1.5f, 1.5f); -// spawnEntityAt(wizard, randomPos, true, false); -// } -// } -// -// private void spawnWaterQueen() { -// -// int[] pickedLanes = new Random().ints(0, ServiceLocator.getMapService().getHeight() ) -// -// .distinct().limit(5).toArray(); -// for (int i = 0; i < NUM_GRUNTS; i++) { -// GridPoint2 randomPos = new GridPoint2(19, pickedLanes[i]); -// Entity waterQueen = NPCFactory.createWaterQueen(); -// waterQueen.setScale(1.5f, 1.5f); -// spawnEntityAt(waterQueen, randomPos, true, false); -// } -// } -// -// private void spawnWaterSlime() { -// -// int[] pickedLanes = new Random().ints(0, ServiceLocator.getMapService().getHeight() ) -// -// .distinct().limit(5).toArray(); -// for (int i = 0; i < NUM_GRUNTS; i++) { -// GridPoint2 randomPos = new GridPoint2(19, pickedLanes[i]); -// Entity waterSlime = NPCFactory.createSplittingWaterSlime(); -// waterSlime.setScale(1.5f, 1.5f); -// spawnEntityAt(waterSlime, randomPos, true, false); -// } -// } - - private void spawnCoat() { - Entity gregMob = NPCFactory.createCoat(100); - gregMob.setScale(1.5f, 1.5f); - spawnEntityAt(gregMob, new GridPoint2(17, 4), false, false); - } - - /** - * Creates multiple projectiles that travel simultaneous. They all have same - * the starting point but different destinations. - * - * @param position The position of the Entity that's shooting the projectile. - * @param targetLayer The enemy layer of the "shooter". - * @param direction The direction the projectile should head towards. - * @param space The space between the projectiles' destination. - * @param speed The speed of the projectiles. - * @param quantity The amount of projectiles to spawn. - */ - private void spawnMultiProjectile(Vector2 position, short targetLayer, int direction, int space, Vector2 speed, int quantity) { - int half = quantity / 2; - for (int i = 0; i < quantity; i++) { - spawnProjectile(position, targetLayer, space * half, direction, speed); - --half; - } - } - - /** - * Returns projectile that can do an area of effect damage - * - * @param position The position of the Entity that's shooting the projectile. - * @param targetLayer The enemy layer of the "shooter". - * @param direction The direction the projectile should head towards. - * @param speed The speed of the projectiles. - * @param effect Type of effect. - * @param aoe Whether it is an aoe projectile. - */ - private void spawnEffectProjectile(Vector2 position, short targetLayer, int direction, Vector2 speed, - ProjectileEffects effect, boolean aoe) { - Entity Projectile = ProjectileFactory.createEffectProjectile(targetLayer, new Vector2(direction, position.y), speed, effect, aoe); - Projectile.setPosition(position); - spawnEntity(Projectile); - } - - /** - * Spawns a pierce fireball. - * Pierce fireball can go through targetlayers without disappearing but damage - * will still be applied. - * - * @param position The position of the Entity that's shooting the projectile. - * @param targetLayer The enemy layer of the "shooter". - * @param direction The direction the projectile should head towards. - * @param speed The speed of the projectiles. - */ - private void spawnPierceFireBall(Vector2 position, short targetLayer, int direction, Vector2 speed) { - Entity projectile = ProjectileFactory.createPierceFireBall(targetLayer, new Vector2(direction, position.y), speed); - projectile.setPosition(position); - spawnEntity(projectile); - } - - /** - * Spawns a ricochet fireball - * Ricochet fireballs bounce off targets with a specified maximum count of 3 - * Possible extensions: Make the bounce count flexible with a param. - * - * @param position The position of the Entity that's shooting the projectile. - * @param targetLayer The enemy layer of the "shooter". - * @param direction The direction the projectile should head towards. - * @param speed The speed of the projectiles. - */ - private void spawnRicochetFireball(Vector2 position, short targetLayer, int direction, Vector2 speed) { - // Bounce count set to 0. - Entity projectile = ProjectileFactory.createRicochetFireball(targetLayer, new Vector2(direction, position.y), speed, 0); - projectile.setPosition(position); - spawnEntity(projectile); - } - - /** - * Spawns a split firework fireball. - * Splits into mini projectiles that spreads out after collision. - * - * @param position The position of the Entity that's shooting the projectile. - * @param targetLayer The enemy layer of the "shooter". - * @param direction The direction the projectile should towards. - * @param speed The speed of the projectiles. - * @param amount The amount of projectiles appearing after collision. - */ - private void spawnSplitFireWorksFireBall(Vector2 position, short targetLayer, int direction, Vector2 speed, int amount) { - Entity projectile = ProjectileFactory.createSplitFireWorksFireball(targetLayer, new Vector2(direction, position.y), speed, amount); - projectile.setPosition(position); - spawnEntity(projectile); - } - - private void spawnWeaponTower() { - GridPoint2 minPos = new GridPoint2(0, 0); - GridPoint2 maxPos = terrain.getMapBounds(0).sub(5, 1); - - for (int i = 0; i < NUM_WEAPON_TOWERS + 7 ; i++) { - GridPoint2 randomPos1 = RandomUtils.random(minPos, maxPos); - GridPoint2 randomPos2 = RandomUtils.random(minPos, maxPos); - Entity wallTower = TowerFactory.createWallTower(); - Entity fireTower = TowerFactory.createFireTower(); - Entity stunTower = TowerFactory.createStunTower(); - spawnEntityAt(fireTower, randomPos1, true, true); - spawnEntityAt(stunTower, randomPos2, true, true); - spawnEntityAt(wallTower, randomPos2, true, true); - } - } - - // * TEMPORARY FOR TESTING - private void spawnFireTowerAt(int x, int y) { - GridPoint2 pos = new GridPoint2(x, y); - Entity fireTower = TowerFactory.createFireTower(); - - spawnEntityAt(fireTower, pos, true, true); - } - private void spawnDroidTowerAt(int x, int y) { - GridPoint2 pos = new GridPoint2(x, y); - Entity droidTower = TowerFactory.createDroidTower(); - - spawnEntityAt(droidTower, pos, true, true); - } - - private void spawnTNTTower() { - GridPoint2 minPos = new GridPoint2(0, 0); - GridPoint2 maxPos = terrain.getMapBounds(0).sub(5, 1); - - for (int i = 0; i < NUM_WEAPON_TOWERS + 5; i++) { - GridPoint2 randomPos = RandomUtils.random(minPos, maxPos); - Entity weaponTower = TowerFactory.createTNTTower(); - spawnEntityAt(weaponTower, randomPos, true, true); - } - - } - private void spawnFireWorksTower() { - GridPoint2 minPos = new GridPoint2(0, 2); - GridPoint2 maxPos = terrain.getMapBounds(0).sub(1, 1); - - for (int i = 0; i < NUM_WEAPON_TOWERS; i++) { - GridPoint2 randomPos = RandomUtils.random(minPos, maxPos); - Entity FireWorksTower = TowerFactory.createFireworksTower(); - spawnEntityAt(FireWorksTower, randomPos, true, true); - } - - } - private void spawnPierceTower() { - GridPoint2 minPos = new GridPoint2(0, 2); - GridPoint2 maxPos = terrain.getMapBounds(0).sub(3, 3); - - for (int i = 0; i < NUM_WEAPON_TOWERS; i++) { - GridPoint2 randomPos = RandomUtils.random(minPos, maxPos); - Entity PierceTower = TowerFactory.createPierceTower(); - spawnEntityAt(PierceTower, randomPos, true, true); - } - - } - private void spawnRicochetTower() { - GridPoint2 minPos = new GridPoint2(0, 2); - GridPoint2 maxPos = terrain.getMapBounds(0).sub(0, 3); - - for (int i = 0; i < NUM_WEAPON_TOWERS; i++) { - GridPoint2 randomPos = RandomUtils.random(minPos, maxPos); - Entity RicochetTower = TowerFactory.createRicochetTower(); - spawnEntityAt(RicochetTower, randomPos, true, true); - } - - } - - private void spawnBombship() { - GridPoint2 minPos = new GridPoint2(0, 0); - GridPoint2 maxPos = terrain.getMapBounds(0).sub(5, 1); - Entity bombship = BombshipFactory.createBombship(); - spawnEntityAt(bombship, minPos, true, true); - } - - private void spawnDroidTower() { - GridPoint2 minPos = new GridPoint2(0, 0); - GridPoint2 maxPos = terrain.getMapBounds(0).sub(5, 1); - - for (int i = 0; i < NUM_WEAPON_TOWERS + 5; i++) { - GridPoint2 randomPos = RandomUtils.random(minPos, maxPos); - Entity weaponTower = TowerFactory.createDroidTower(); - spawnEntityAt(weaponTower, randomPos, true, false); - } - } - - private void playMusic() { - Music music = ServiceLocator.getResourceService().getAsset(BACKGROUND_MUSIC, Music.class); - music.setLooping(true); - music.setVolume(0.3f); - music.play(); - } private void loadAssets() { logger.debug("Loading assets"); @@ -941,17 +474,6 @@ private void spawnScrap() { } } - private void spawnIncome() { - GridPoint2 minPos = new GridPoint2(0, 0); - GridPoint2 maxPos = terrain.getMapBounds(0).sub(2, 2); - - for (int i = 0; i < 50; i++) { - GridPoint2 randomPos = RandomUtils.random(minPos, maxPos); - Entity towerfactory = TowerFactory.createIncomeTower(); - spawnEntityAt(towerfactory, randomPos, true, true); - } - } - /** * Creates the scanners (one per lane) that detect absence of towers and presence of mobs, * and trigger engineer spawning diff --git a/source/core/src/main/com/csse3200/game/components/EffectsComponent.java b/source/core/src/main/com/csse3200/game/components/EffectsComponent.java index 596bb71f2..4fb249d6d 100644 --- a/source/core/src/main/com/csse3200/game/components/EffectsComponent.java +++ b/source/core/src/main/com/csse3200/game/components/EffectsComponent.java @@ -2,20 +2,13 @@ import java.util.ArrayList; -import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.physics.box2d.Fixture; -import com.csse3200.game.ai.tasks.AITaskComponent; -import com.csse3200.game.components.tower.TowerUpgraderComponent; import com.csse3200.game.entities.Entity; import com.csse3200.game.physics.BodyUserData; import com.csse3200.game.physics.PhysicsLayer; import com.csse3200.game.physics.components.HitboxComponent; -import com.csse3200.game.physics.components.PhysicsMovementComponent; import com.csse3200.game.services.ServiceLocator; -import com.badlogic.gdx.utils.Timer; -import com.badlogic.gdx.utils.Timer.Task; - import com.badlogic.gdx.utils.Array; /** @@ -102,6 +95,7 @@ public void applySingleEffect(ProjectileEffects effect, Entity targetEntity) { } effectComponent.applyEffect(effect, hostEntity, targetEntity); } + /** * Used for aoe projectiles to apply effects to all entities within the area of effect (radius). * @param effect effect to be applied to entities within radius @@ -136,132 +130,4 @@ public void applyAoeEffect(ProjectileEffects effect) { effectComponent.applyEffect(effect, hostEntity, targetEntity); } } - - /** - * Deals damage to target based on hosts' CombatStatsComponent - * @param target CombatStatsComponent of entity hit by projectile - * @param host CombatStatsComponent of projectile - */ - private void fireballEffect(CombatStatsComponent target, CombatStatsComponent host) { - target.hit(host); - } - -// /** -// * Applies 5 ticks of damage from hosts' CombatStatsComponent over 5 seconds -// * @param target CombatStatsComponent of entity hit by projectile -// * @param host CombatStatsComponent of projectile -// */ -// private void burnEffect(CombatStatsComponent target, CombatStatsComponent host) { -// // Ensure burn effects aren't applied multiple times by same projectile -// if (burnEntities.contains(target, false)) { -// return; -// } -// burnEntities.add(target); -// // Create a timer task to apply the effect repeatedly -// int numberOfTicks = 5; -// long delay = 1; -// Timer.schedule(new Timer.Task() { -// private int count = 0; -// -// @Override -// public void run() { -// if (count < numberOfTicks) { -// target.hit(host); -// count++; -// } else { -// // Ensure to cancel the task when it's done -// this.cancel(); -// } -// } -// }, delay, delay); -// } - - /** - * Applies slow effect to targetEntity. If entity is a mob, speed - * and firing rate will be slowed. If entity is a tower, firing rate - * will be slowed - * @param targetEntity Entity for slow effect to be applied to - */ - private void slowEffect(Entity targetEntity) { - boolean towerFlag = false; - boolean mobFlag = false; - - PhysicsMovementComponent targetPhysics = null; - float xSpeed = 0; - float ySpeed = 0; - - // Create a timer task to apply the effect repeatedly - if (PhysicsLayer.contains(PhysicsLayer.HUMANS, targetEntity.getComponent(HitboxComponent.class).getLayer())) { - // towers - towerFlag = true; - targetEntity.getEvents().trigger("upgradeTower", TowerUpgraderComponent.UPGRADE.FIRERATE, -30); - } else if (PhysicsLayer.contains(PhysicsLayer.NPC, targetEntity.getComponent(HitboxComponent.class).getLayer())) { - // mobs - mobFlag = true; - targetPhysics = targetEntity.getComponent(PhysicsMovementComponent.class); - if (targetPhysics == null) { - return; - } - - // Halve the mob speed - xSpeed = targetPhysics.getSpeed().x; - ySpeed = targetPhysics.getSpeed().y; - targetPhysics.setSpeed(new Vector2(xSpeed/2, ySpeed/2)); - } else { - return; - } - - // Reset speed - boolean finalTowerFlag = towerFlag; - boolean finalMobFlag = mobFlag; - PhysicsMovementComponent finalTargetPhysics = targetPhysics; - float finalXSpeed = xSpeed; - float finalYSpeed = ySpeed; - Timer.schedule(new Task() { - @Override - public void run() { - if (finalTowerFlag) { - targetEntity.getEvents().trigger("upgradeTower", TowerUpgraderComponent.UPGRADE.FIRERATE, 30); - } else if (finalMobFlag) { - finalTargetPhysics.setSpeed(new Vector2(finalXSpeed, finalYSpeed)); - } - } - }, 5); // 5 seconds delay - } - - /** - * Applies stun effect to a taget entity. - * @param targetEntity Entity for stun effect to be applied to. - */ - private void stunEffect(Entity targetEntity) { - CombatStatsComponent hostCombatStats = targetEntity.getComponent(CombatStatsComponent.class); - AITaskComponent taskComponent = targetEntity.getComponent(AITaskComponent.class); - - if (hostCombatStats == null || taskComponent == null) { - return; - } - - hostCombatStats.setBaseAttack(0); - - if (stunnedEntities.contains(targetEntity)) { - return; - } - - taskComponent.disposeAll(); - stunnedEntities.add(targetEntity); - - new java.util.Timer().schedule( - new java.util.TimerTask() { - @Override - public void run() { - taskComponent.restore(); - for (int i = 0; i < stunnedEntities.size(); i++) { - if (stunnedEntities.get(i).equals(targetEntity)) { - stunnedEntities.remove(stunnedEntities.get(i)); - } - } - this.cancel(); - } - }, 5000); - } } \ No newline at end of file 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 858563858..7444dfc4f 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 @@ -1,5 +1,6 @@ package com.csse3200.game.components.gamearea; +import com.badlogic.gdx.Gdx; import com.badlogic.gdx.audio.Sound; import com.badlogic.gdx.graphics.Camera; import com.badlogic.gdx.graphics.Texture; @@ -56,11 +57,17 @@ private void addActors() { ServiceLocator.getCurrencyService().getCrystal().getAmount()); table.add(scrapsTb).width(scrapsTb.getWidth() * 0.5f).height(scrapsTb.getHeight() * 0.5f); + table.row(); table.add(crystalsTb).width(crystalsTb.getWidth() * 0.5f).height(crystalsTb.getHeight() * 0.5f); stage.addActor(table); - scrapsTb.addAction(new SequenceAction(Actions.fadeIn(4f))); - crystalsTb.addAction(new SequenceAction(Actions.fadeIn(8f))); + scrapsTb.setPosition(table.getX() - 200, Gdx.graphics.getHeight() - 205); + scrapsTb.addAction(new SequenceAction(Actions.moveTo(table.getX() + 20, Gdx.graphics.getHeight() - 205, + 1f, Interpolation.fastSlow))); + + crystalsTb.setPosition(table.getX() - 200, Gdx.graphics.getHeight() - 268); + crystalsTb.addAction(new SequenceAction(Actions.moveTo(table.getX() + 20, Gdx.graphics.getHeight() - 268, + 1f, Interpolation.fastSlow))); } private TextButton createButton(String imageFilePath, int value) { 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 6334e1b4a..5c809a649 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 @@ -1,8 +1,10 @@ package com.csse3200.game.components.gamearea; +import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.math.Interpolation; import com.badlogic.gdx.scenes.scene2d.Touchable; import com.badlogic.gdx.scenes.scene2d.actions.Actions; import com.badlogic.gdx.scenes.scene2d.actions.SequenceAction; @@ -57,20 +59,25 @@ private void addActors() { table.add(engineerTb).width(engineerTb.getWidth() * 0.5f).height(engineerTb.getHeight() * 0.5f); stage.addActor(table); - engineerTb.addAction(new SequenceAction(Actions.fadeIn(4f))); + // Animate the engineer count label + engineerTb.setPosition(table.getX() - 200, Gdx.graphics.getHeight() - 145); + engineerTb.addAction(new SequenceAction(Actions.moveTo(table.getX() + 20, Gdx.graphics.getHeight() - 145, + 1f, Interpolation.fastSlow))); } /** * Updates the engineer count on the UI component */ public void updateCount() { - int currentCount = ServiceLocator.getGameEndService().getEngineerCount(); - String text = String.format("%d", currentCount); - engineerTb.getLabel().setText(text); - if (currentCount < ServiceLocator.getGameEndService().getThreshold()) { + if (engineerTb != null) { // fix for null pointer exception + int currentCount = ServiceLocator.getGameEndService().getEngineerCount(); + String text = String.format("%d", currentCount); + engineerTb.getLabel().setText(text); + if (currentCount < ServiceLocator.getGameEndService().getThreshold()) { // engineerTb.addAction(Actions.color(Color.RED, 0.5f, Interpolation.swingIn)); - engineerTb.addAction(Actions.forever(new SequenceAction(Actions.fadeOut(0.5f), - Actions.fadeIn(0.5f)))); + engineerTb.addAction(Actions.forever(new SequenceAction(Actions.fadeOut(0.5f), + Actions.fadeIn(0.5f)))); + } } } diff --git a/source/core/src/main/com/csse3200/game/components/maingame/MainGameDisplay.java b/source/core/src/main/com/csse3200/game/components/maingame/MainGameDisplay.java index f9d6c4de1..ec5c56489 100644 --- a/source/core/src/main/com/csse3200/game/components/maingame/MainGameDisplay.java +++ b/source/core/src/main/com/csse3200/game/components/maingame/MainGameDisplay.java @@ -15,7 +15,6 @@ import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; import com.badlogic.gdx.utils.Array; import com.csse3200.game.GdxGame; -import com.csse3200.game.components.pausemenu.PauseMenuButtonComponent; import com.csse3200.game.entities.Entity; import com.csse3200.game.entities.factories.PauseMenuFactory; import com.csse3200.game.screens.TowerType; @@ -32,6 +31,7 @@ public class MainGameDisplay extends UIComponent { private static final Logger logger = LoggerFactory.getLogger(MainGameDisplay.class); private static final float Z_INDEX = 2f; + private static final String SHORTCUT_FONT = "small"; private final Table towerTable = new Table(); private final Table buttonTable = new Table(); private final Table progressTable = new Table(); @@ -86,19 +86,83 @@ private void addActors() { // Create and position the tables that will hold the buttons. // Contains the tower build menu buttons - towerTable.top().padTop(50f); + towerTable.top().padTop(80f); towerTable.setFillParent(true); // Contains other buttons (just pause at this stage) - buttonTable.top().right().padTop(50f).padRight(80f); + buttonTable.top().right().padTop(80f).padRight(80f); buttonTable.setFillParent(true); progressTable.top().center().setWidth(500f); progressTable.setFillParent(true); - levelNameTable.top().left().padLeft(20f).padTop(20f); + levelNameTable.center().top().padLeft(20f).padTop(20f).pad(20f); levelNameTable.setFillParent(true); + // set the towerTypes if they aren't already + setTowers(); + + // Update the centrally located towerTypes list - + ServiceLocator.setTowerTypes(towers); + + // create the tower buttons, pause button, and their associated listeners + createTowerButtons(); + TextButton pauseBtn = createPauseButton(); + + progressbar = new LevelProgressBar(500, 10); + + levelNameTable.setSkin(getSkin()); + levelNameTable.add(this.level, "default"); + + // Scale all the tower build buttons down + // Add all buttons to their respective tables and position them + towerTable.setSkin(getSkin()); + towerTable.add(tower1).padRight(10f); + towerTable.add(tower2).padRight(10f); + towerTable.add(tower3).padRight(10f); + towerTable.add(tower4).padRight(10f); + towerTable.add(tower5).padRight(10f); + towerTable.row(); + towerTable.add("1", SHORTCUT_FONT); + towerTable.add("2", SHORTCUT_FONT); + towerTable.add("3", SHORTCUT_FONT); + towerTable.add("4", SHORTCUT_FONT); + towerTable.add("5", SHORTCUT_FONT); + towerTable.row().colspan(5).pad(20f); + towerTable.add(progressbar).fillX(); + + buttonTable.add(pauseBtn); + + // Add tables to the stage + + stage.addActor(buttonTable); + stage.addActor(towerTable); + stage.addActor(levelNameTable); + + // Animate the tower select buttons + int tower1Gap = Gdx.graphics.getWidth() /2 + (int) towerTable.getX()/2 + 400; + int tower2Gap = Gdx.graphics.getWidth() /2 + (int) towerTable.getX()/2 + 240; + int tower3Gap = Gdx.graphics.getWidth() /2 + (int) towerTable.getX()/2 + 80; + int tower4Gap = Gdx.graphics.getWidth() /2 + (int) towerTable.getX()/2 - 80; + int tower5Gap = Gdx.graphics.getWidth() /2 + (int) towerTable.getX()/2 - 240; + animateTowerButton(tower1, tower1Gap, 230); + animateTowerButton(tower2, tower2Gap, 230); + animateTowerButton(tower3, tower3Gap, 230); + animateTowerButton(tower4, tower4Gap, 230); + animateTowerButton(tower5, tower5Gap, 230); + + TooltipManager tm = TooltipManager.getInstance(); + tm.initialTime = 3; + tm.hideAll(); + } + + @Override + public void draw(SpriteBatch batch) { + // draw is handled by the stage + towerUpdate(); + } + + private void setTowers() { // Stores tower defaults, in case towers haven't been set in the tower select screen TowerType[] defaultTowers = { TowerType.TNT, @@ -117,20 +181,19 @@ private void addActors() { // If no towers set, populate with default towers if (towers.isEmpty() || towers.size < 5) { - if (towers.isEmpty()) { - towers.addAll(defaultTowers); - } else { - for (TowerType tower : defaultTowers) { - if (towers.size < 5 && !towers.contains(tower, false)) { - towers.add(tower); - } +// if (towers.isEmpty()) { +// towers.addAll(defaultTowers); +// } else { + for (TowerType tower : defaultTowers) { + if (towers.size < 5 && !towers.contains(tower, true)) { + towers.add(tower); } } } - - // Update the centrally located towerTypes list - ServiceLocator.setTowerTypes(towers); + } + private void createTowerButtons() { tower1 = new ImageButton(skin, towers.get(0).getSkinName()); towerButtons.add(tower1); tower2 = new ImageButton(skin, towers.get(1).getSkinName()); @@ -142,10 +205,41 @@ private void addActors() { tower5 = new ImageButton(skin, towers.get(4).getSkinName()); towerButtons.add(tower5); + int i = 0; + for (ImageButton button : towerButtons) { + // Triggers an event when the button is pressed. + int finalI = i; + button.addListener( + new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + + TowerType selected = ServiceLocator.getCurrencyService().getTower(); + if (selected == towers.get(finalI) ) { + ServiceLocator.getCurrencyService().setTowerType(null); + + towerToggle(null); + + } else { + ServiceLocator.getCurrencyService().setTowerType(towers.get(finalI)); + + towerToggle(button); + + } + click.play(0.4f); + } + }); + TextTooltip tower1Tooltip = new TextTooltip(towers.get(i).getDescription(), getSkin()); + button.addListener(tower1Tooltip); + i++; + } + } + + private TextButton createPauseButton() { TextButton pauseBtn = ButtonFactory.createButton("Pause"); // Starting animation for pause button - pauseBtn.setPosition(Gdx.graphics.getWidth(), Gdx.graphics.getHeight() - 150); + pauseBtn.setPosition(Gdx.graphics.getWidth(), (float)(Gdx.graphics.getHeight() - 150)); pauseBtn.addAction(new SequenceAction(Actions.moveTo(Gdx.graphics.getWidth() - 200, Gdx.graphics.getHeight() - 150, 1f, Interpolation.fastSlow))); @@ -179,181 +273,7 @@ public boolean keyUp(InputEvent event, int keycode) { return false; } }); - - // Triggers an event when the button is pressed. - tower1.addListener( - new ClickListener() { - @Override - public void clicked(InputEvent event, float x, float y) { - - TowerType selected = ServiceLocator.getCurrencyService().getTower(); - if (selected == towers.get(0) ) { - ServiceLocator.getCurrencyService().setTowerType(null); - - towerToggle(null); - - } else { - ServiceLocator.getCurrencyService().setTowerType(towers.get(0)); - - towerToggle(tower1); - - } - click.play(0.4f); - } - }); - TextTooltip tower1Tooltip = new TextTooltip(towers.get(0).getDescription(), getSkin()); - tower1.addListener(tower1Tooltip); - - // Triggers an event when the button is pressed. - tower2.addListener( - new ClickListener() { - @Override - public void clicked(InputEvent event, float x, float y) { - - TowerType selected = ServiceLocator.getCurrencyService().getTower(); - if (selected == towers.get(1) ) { - ServiceLocator.getCurrencyService().setTowerType(null); - - towerToggle(null); - - } else { - ServiceLocator.getCurrencyService().setTowerType(towers.get(1)); - - towerToggle(tower2); - - } - click.play(0.4f); - } - }); - TextTooltip tower2Tooltip = new TextTooltip(towers.get(1).getDescription(), getSkin()); - tower2.addListener(tower2Tooltip); - - tower3.addListener( - new ClickListener() { - @Override - public void clicked(InputEvent event, float x, float y) { - - TowerType selected = ServiceLocator.getCurrencyService().getTower(); - if (selected == towers.get(2)) { - ServiceLocator.getCurrencyService().setTowerType(null); - - towerToggle(null); - - } else { - ServiceLocator.getCurrencyService().setTowerType(towers.get(2)); - if (ServiceLocator.getCurrencyService().getScrap().getAmount() - >= Integer.parseInt(towers.get(2).getPrice())) { - - towerToggle(tower3); - - } else { - tower3.setDisabled(true); - } - } - click.play(0.4f); - } - }); - - TextTooltip tower3Tooltip = new TextTooltip(towers.get(3).getDescription(), getSkin()); - tower3.addListener(tower3Tooltip); - - tower4.addListener( - new ClickListener() { - @Override - public void clicked(InputEvent event, float x, float y) { - - TowerType selected = ServiceLocator.getCurrencyService().getTower(); - if (selected == towers.get(3)) { - ServiceLocator.getCurrencyService().setTowerType(null); - - towerToggle(null); - - } else { - ServiceLocator.getCurrencyService().setTowerType(towers.get(3)); - - towerToggle(tower4); - - } - click.play(0.4f); - } - }); - TextTooltip tower4Tooltip = new TextTooltip(towers.get(3).getDescription(), getSkin()); - tower4.addListener(tower4Tooltip); - - tower5.addListener( - new ClickListener() { - @Override - public void clicked(InputEvent event, float x, float y) { - - TowerType selected = ServiceLocator.getCurrencyService().getTower(); - if (selected == towers.get(4)) { - ServiceLocator.getCurrencyService().setTowerType(null); - - towerToggle(null); - - } else { - ServiceLocator.getCurrencyService().setTowerType(towers.get(4)); - - towerToggle(tower5); - - } - click.play(0.4f); - } - }); - TextTooltip tower5Tooltip = new TextTooltip(towers.get(4).getDescription(), getSkin()); - tower5.addListener(tower5Tooltip); - - progressbar = new LevelProgressBar(500, 10); - - levelNameTable.setSkin(getSkin()); - levelNameTable.add(this.level, "title"); - - // Scale all the tower build buttons down - // Add all buttons to their respective tables and position them - towerTable.setSkin(getSkin()); - towerTable.add(tower1).padRight(10f); - towerTable.add(tower2).padRight(10f); - towerTable.add(tower3).padRight(10f); - towerTable.add(tower4).padRight(10f); - towerTable.add(tower5).padRight(10f); - towerTable.row(); - towerTable.add("1", "small"); - towerTable.add("2", "small"); - towerTable.add("3", "small"); - towerTable.add("4", "small"); - towerTable.add("5", "small"); - towerTable.row().colspan(5).pad(20f); - towerTable.add(progressbar).fillX(); - - buttonTable.add(pauseBtn); - - // Add tables to the stage - - stage.addActor(buttonTable); - stage.addActor(towerTable); - stage.addActor(levelNameTable); - - // Animate the tower select buttons - int tower1Gap = Gdx.graphics.getWidth() /2 + (int) towerTable.getX()/2 + 400; - int tower2Gap = Gdx.graphics.getWidth() /2 + (int) towerTable.getX()/2 + 240; - int tower3Gap = Gdx.graphics.getWidth() /2 + (int) towerTable.getX()/2 + 80; - int tower4Gap = Gdx.graphics.getWidth() /2 + (int) towerTable.getX()/2 - 80; - int tower5Gap = Gdx.graphics.getWidth() /2 + (int) towerTable.getX()/2 - 240; - animateTowerButton(tower1, tower1Gap, 230); - animateTowerButton(tower2, tower2Gap, 230); - animateTowerButton(tower3, tower3Gap, 230); - animateTowerButton(tower4, tower4Gap, 230); - animateTowerButton(tower5, tower5Gap, 230); - - TooltipManager tm = TooltipManager.getInstance(); - tm.initialTime = 3; - tm.hideAll(); - } - - @Override - public void draw(SpriteBatch batch) { - // draw is handled by the stage - towerUpdate(); + return pauseBtn; } /** @@ -369,6 +289,10 @@ public void updateLevelProgressBar() { * depending on button selection and currency balance */ private void towerUpdate() { + // Check for small tower array + if (towers.size < 5) { + setTowers(); + } // no tower selected, set all to off if (ServiceLocator.getCurrencyService().getTower() == null) { // toggle all buttons to off diff --git a/source/core/src/main/com/csse3200/game/components/maingame/UIElementsDisplay.java b/source/core/src/main/com/csse3200/game/components/maingame/UIElementsDisplay.java index 6b0d93bf1..c3e9d24ff 100644 --- a/source/core/src/main/com/csse3200/game/components/maingame/UIElementsDisplay.java +++ b/source/core/src/main/com/csse3200/game/components/maingame/UIElementsDisplay.java @@ -12,22 +12,16 @@ import com.csse3200.game.services.ServiceLocator; import com.csse3200.game.ui.ButtonFactory; import com.csse3200.game.ui.UIComponent; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.swing.event.ChangeEvent; -import java.security.Provider; - /** * Displays a button to represent the remaining mobs left in the current wave and a button to skip to the next wave. */ public class UIElementsDisplay extends UIComponent { - private static final Logger logger = LoggerFactory.getLogger(UIElementsDisplay.class); private static final float Z_INDEX = 2f; private final Table buttonTable = new Table(); private TextButton remainingMobsButton; private TextButton timerButton; + private long time = 0; @Override public void create() { @@ -44,15 +38,14 @@ private void addActors() { + ServiceLocator.getWaveService().getEnemyCount()); remainingMobsButton.setPosition(Gdx.graphics.getWidth(), Gdx.graphics.getHeight() - 230); - remainingMobsButton.addAction(new SequenceAction(Actions.moveTo(Gdx.graphics.getWidth() - 218, + remainingMobsButton.addAction(new SequenceAction(Actions.moveTo(Gdx.graphics.getWidth() - 217, Gdx.graphics.getHeight() - 230, 1f, Interpolation.fastSlow))); - buttonTable.top().right().padTop(130f).padRight(80f); + buttonTable.top().right().padTop(160f).padRight(80f); buttonTable.setFillParent(true); buttonTable.add(remainingMobsButton).right(); - buttonTable.row(); - buttonTable.add(timerButton); + stage.addActor(buttonTable); @@ -82,10 +75,11 @@ public void createTimerButton() { timerButton = ButtonFactory.createButton("Next wave in:" + (ServiceLocator.getWaveService().getNextWaveTime() / 1000)); timerButton.setPosition(Gdx.graphics.getWidth(), Gdx.graphics.getHeight() - 300); - timerButton.addAction(new SequenceAction(Actions.moveTo(Gdx.graphics.getWidth() - 445, + timerButton.addAction(new SequenceAction(Actions.moveTo(Gdx.graphics.getWidth() - 435, Gdx.graphics.getHeight() - 300, 1f, Interpolation.fastSlow))); + timerButton.setDisabled(true); buttonTable.row(); - buttonTable.add(timerButton).padRight(10f); + buttonTable.add(timerButton); } /** @@ -96,20 +90,22 @@ public void updateTimerButton() { int totalSecs = (int) ((ServiceLocator.getWaveService().getNextWaveTime() - ServiceLocator.getTimeSource().getTime()) / 1000); - // TODO : THESE SHOULD BE REMOVED AND PLACED WHEREVER THE BOSS MOB GETS SPAWNED - if (totalSecs % 20 == 0) { - ServiceLocator.getMapService().shakeCameraMap(); - ServiceLocator.getMapService().shakeCameraGrid(); - } int seconds = totalSecs % 60; int minutes = (totalSecs % 3600) / 60; String finalTime = String.format("%02d:%02d", minutes, seconds); if (ServiceLocator.getTimeSource().getTime() < ServiceLocator.getWaveService().getNextWaveTime()) { if (!findActor(timerButton)) { + remainingMobsButton.setDisabled(false); createTimerButton(); } timerButton.setText("Next wave in: " + finalTime); + time = ServiceLocator.getTimeSource().getTime(); } else { + if (ServiceLocator.getTimeSource().getTime() < time + 2000) { + ServiceLocator.getMapService().shakeCameraMap(); + ServiceLocator.getMapService().shakeCameraGrid(); + } + remainingMobsButton.setDisabled(true); timerButton.addAction(new SequenceAction(Actions.fadeOut(1f), Actions.removeActor())); stage.act(); stage.draw(); diff --git a/source/core/src/main/com/csse3200/game/components/npc/ArcaneArcherAnimationController.java b/source/core/src/main/com/csse3200/game/components/npc/ArcaneArcherAnimationController.java index 71fa5359d..82c587f18 100644 --- a/source/core/src/main/com/csse3200/game/components/npc/ArcaneArcherAnimationController.java +++ b/source/core/src/main/com/csse3200/game/components/npc/ArcaneArcherAnimationController.java @@ -5,19 +5,14 @@ import com.csse3200.game.rendering.AnimationRenderComponent; import com.csse3200.game.services.ServiceLocator; -import java.security.SecureRandom; /** * This class listens to events relevant to a ghost entity's state and plays the animation when one * of the events is triggered. */ public class ArcaneArcherAnimationController extends Component { - // // For on collision sounds later - // private static final String COLLISION_SFX = "sounds/projectiles/on_collision.mp3"; - // Sound onCollisionSound = ServiceLocator.getResourceService().getAsset( - // COLLISION_SFX, Sound.class); + AnimationRenderComponent animator; - private SecureRandom rand = new SecureRandom(); private static final String ATTACK_SOUND = "sounds/mobs/archerArrow.mp3"; Sound attackSound = ServiceLocator.getResourceService().getAsset( diff --git a/source/core/src/main/com/csse3200/game/components/npc/CoatAnimationController.java b/source/core/src/main/com/csse3200/game/components/npc/CoatAnimationController.java index e9bf8170e..c023e0aa5 100644 --- a/source/core/src/main/com/csse3200/game/components/npc/CoatAnimationController.java +++ b/source/core/src/main/com/csse3200/game/components/npc/CoatAnimationController.java @@ -5,19 +5,13 @@ import com.csse3200.game.rendering.AnimationRenderComponent; import com.csse3200.game.services.ServiceLocator; -import java.security.SecureRandom; /** * This class listens to events relevant to a ghost entity's state and plays the animation when one * of the events is triggered. */ public class CoatAnimationController extends Component { - // // For on collision sounds later - // private static final String COLLISION_SFX = "sounds/projectiles/on_collision.mp3"; - // Sound onCollisionSound = ServiceLocator.getResourceService().getAsset( - // COLLISION_SFX, Sound.class); AnimationRenderComponent animator; - private SecureRandom rand = new SecureRandom(); private static final String ATTACK_SOUND = "sounds/mobs/coatAttack.mp3"; Sound attackSound = ServiceLocator.getResourceService().getAsset( diff --git a/source/core/src/main/com/csse3200/game/components/npc/DodgingComponent.java b/source/core/src/main/com/csse3200/game/components/npc/DodgingComponent.java index 14a3b07d9..96cefd608 100644 --- a/source/core/src/main/com/csse3200/game/components/npc/DodgingComponent.java +++ b/source/core/src/main/com/csse3200/game/components/npc/DodgingComponent.java @@ -7,6 +7,8 @@ import com.csse3200.game.physics.raycast.RaycastHit; import com.csse3200.game.services.ServiceLocator; +import java.util.Random; + /** * A component that adds a dodging event listener to the current attached * entity. The entity will dodge another entity that is presumably coming at its @@ -30,6 +32,7 @@ public class DodgingComponent extends Component { private float dodgeSpeed = 1.75f; private float originalSpeed; // Original entity vertical speed private PhysicsEngine physics; + private Random random = new Random(); // Sometimes the raycast mechanic doesn't detect the other entity because of the // target's (or self) collider size does not match. This value makes sure the @@ -92,10 +95,13 @@ public void create() { * @param mobPos The current Vector2 mob position in the map. */ public void changeTraverseDirection(Vector2 mobPos) { + int randDirection = random.nextInt(2) == 1 ? -1 : 1; if (isTargetVisible(mobPos)) { // If mob is in the top half quadrant of the map grid, make the entity dodge // downwards. - setVerticalAngleDirection(mobPos.y > 3.5 ? mobPos.y - 15 : mobPos.y + 15); + // setVerticalAngleDirection(mobPos.y > 3.5 ? mobPos.y - 15 : mobPos.y + 15); + // Random direction + setVerticalAngleDirection(mobPos.y + (15 * randDirection)); setVerticalSpeed(dodgeSpeed); } else { setVerticalAngleDirection(mobPos.y); @@ -110,7 +116,7 @@ public void changeTraverseDirection(Vector2 mobPos) { * @param mobPos The current Vector2 position of the mob * @return True if a target is visible, false otherwise. */ - private boolean isTargetVisible(Vector2 mobPos) { + public boolean isTargetVisible(Vector2 mobPos) { Vector2 maxRange = new Vector2(mobPos.x - rangeDetection, mobPos.y); // check also the upper and lower boundaries of the mob with the offset y mob // detection. diff --git a/source/core/src/main/com/csse3200/game/components/npc/DragonKnightAnimationController.java b/source/core/src/main/com/csse3200/game/components/npc/DragonKnightAnimationController.java index 6d9d54215..7302a1cdc 100644 --- a/source/core/src/main/com/csse3200/game/components/npc/DragonKnightAnimationController.java +++ b/source/core/src/main/com/csse3200/game/components/npc/DragonKnightAnimationController.java @@ -2,19 +2,13 @@ import com.csse3200.game.components.Component; import com.csse3200.game.rendering.AnimationRenderComponent; -import java.security.SecureRandom; /** * This class listens to events relevant to a ghost entity's state and plays the animation when one * of the events is triggered. */ public class DragonKnightAnimationController extends Component { - // // For on collision sounds later - // private static final String COLLISION_SFX = "sounds/projectiles/on_collision.mp3"; - // Sound onCollisionSound = ServiceLocator.getResourceService().getAsset( - // COLLISION_SFX, Sound.class); AnimationRenderComponent animator; - private SecureRandom rand = new SecureRandom(); @Override public void create() { diff --git a/source/core/src/main/com/csse3200/game/components/npc/FireWormAnimationController.java b/source/core/src/main/com/csse3200/game/components/npc/FireWormAnimationController.java index 141d43d69..28d118210 100644 --- a/source/core/src/main/com/csse3200/game/components/npc/FireWormAnimationController.java +++ b/source/core/src/main/com/csse3200/game/components/npc/FireWormAnimationController.java @@ -4,19 +4,13 @@ import com.csse3200.game.components.Component; import com.csse3200.game.rendering.AnimationRenderComponent; import com.csse3200.game.services.ServiceLocator; -import java.security.SecureRandom; /** * This class listens to events relevant to a ghost entity's state and plays the animation when one * of the events is triggered. */ public class FireWormAnimationController extends Component { - // // For on collision sounds later - // private static final String COLLISION_SFX = "sounds/projectiles/on_collision.mp3"; - // Sound onCollisionSound = ServiceLocator.getResourceService().getAsset( - // COLLISION_SFX, Sound.class); AnimationRenderComponent animator; - private SecureRandom rand = new SecureRandom(); private static final String ATTACK_SOUND = "sounds/mobs/fireWormRoar.mp3"; Sound attackSound = ServiceLocator.getResourceService().getAsset( diff --git a/source/core/src/main/com/csse3200/game/components/npc/FirewizardAnimationController.java b/source/core/src/main/com/csse3200/game/components/npc/FirewizardAnimationController.java index 267c23404..b10236761 100644 --- a/source/core/src/main/com/csse3200/game/components/npc/FirewizardAnimationController.java +++ b/source/core/src/main/com/csse3200/game/components/npc/FirewizardAnimationController.java @@ -3,12 +3,9 @@ import com.csse3200.game.components.Component; import com.csse3200.game.rendering.AnimationRenderComponent; -import java.security.SecureRandom; - public class FirewizardAnimationController extends Component { AnimationRenderComponent animator; - private SecureRandom rand = new SecureRandom(); @Override diff --git a/source/core/src/main/com/csse3200/game/components/npc/NecromancerAnimationController.java b/source/core/src/main/com/csse3200/game/components/npc/NecromancerAnimationController.java index 3bdad9407..dfbd4bc9a 100644 --- a/source/core/src/main/com/csse3200/game/components/npc/NecromancerAnimationController.java +++ b/source/core/src/main/com/csse3200/game/components/npc/NecromancerAnimationController.java @@ -3,13 +3,9 @@ import com.csse3200.game.components.Component; import com.csse3200.game.rendering.AnimationRenderComponent; -import java.security.SecureRandom; - public class NecromancerAnimationController extends Component { AnimationRenderComponent animator; - private SecureRandom rand = new SecureRandom(); - @Override public void create() { diff --git a/source/core/src/main/com/csse3200/game/components/npc/NightBorneAnimationController.java b/source/core/src/main/com/csse3200/game/components/npc/NightBorneAnimationController.java index d821f6cca..fccdfe580 100644 --- a/source/core/src/main/com/csse3200/game/components/npc/NightBorneAnimationController.java +++ b/source/core/src/main/com/csse3200/game/components/npc/NightBorneAnimationController.java @@ -2,7 +2,6 @@ import com.csse3200.game.components.Component; import com.csse3200.game.rendering.AnimationRenderComponent; -import java.security.SecureRandom; /** * This class listens to events relevant to a ghost entity's state and plays the animation when one @@ -13,9 +12,7 @@ public class NightBorneAnimationController extends Component { // private static final String COLLISION_SFX = "sounds/projectiles/on_collision.mp3"; // Sound onCollisionSound = ServiceLocator.getResourceService().getAsset( // COLLISION_SFX, Sound.class); - AnimationRenderComponent animator; - private SecureRandom rand = new SecureRandom(); - + AnimationRenderComponent animator; @Override public void create() { diff --git a/source/core/src/main/com/csse3200/game/components/npc/RockyAnimationController.java b/source/core/src/main/com/csse3200/game/components/npc/RockyAnimationController.java index f6743dd9d..63f850085 100644 --- a/source/core/src/main/com/csse3200/game/components/npc/RockyAnimationController.java +++ b/source/core/src/main/com/csse3200/game/components/npc/RockyAnimationController.java @@ -3,11 +3,8 @@ import com.csse3200.game.components.Component; import com.csse3200.game.rendering.AnimationRenderComponent; -import java.security.SecureRandom; - public class RockyAnimationController extends Component { AnimationRenderComponent animator; - private SecureRandom rand = new SecureRandom(); @Override diff --git a/source/core/src/main/com/csse3200/game/components/npc/SkeletonAnimationController.java b/source/core/src/main/com/csse3200/game/components/npc/SkeletonAnimationController.java index d5ea57bfa..7a821ef75 100644 --- a/source/core/src/main/com/csse3200/game/components/npc/SkeletonAnimationController.java +++ b/source/core/src/main/com/csse3200/game/components/npc/SkeletonAnimationController.java @@ -4,19 +4,13 @@ import com.csse3200.game.components.Component; import com.csse3200.game.rendering.AnimationRenderComponent; import com.csse3200.game.services.ServiceLocator; -import java.security.SecureRandom; /** * This class listens to events relevant to a ghost entity's state and plays the animation when one * of the events is triggered. */ public class SkeletonAnimationController extends Component { - // // For on collision sounds later - // private static final String COLLISION_SFX = "sounds/projectiles/on_collision.mp3"; - // Sound onCollisionSound = ServiceLocator.getResourceService().getAsset( - // COLLISION_SFX, Sound.class); AnimationRenderComponent animator; - private SecureRandom rand = new SecureRandom(); /** Sound variables */ private static final String ATTACK_SOUND = "sounds/mobs/boneBreak.mp3"; diff --git a/source/core/src/main/com/csse3200/game/components/npc/WaterQueenAnimationController.java b/source/core/src/main/com/csse3200/game/components/npc/WaterQueenAnimationController.java index 0b8a00b75..294f312b1 100644 --- a/source/core/src/main/com/csse3200/game/components/npc/WaterQueenAnimationController.java +++ b/source/core/src/main/com/csse3200/game/components/npc/WaterQueenAnimationController.java @@ -4,19 +4,13 @@ import com.csse3200.game.components.Component; import com.csse3200.game.rendering.AnimationRenderComponent; import com.csse3200.game.services.ServiceLocator; -import java.security.SecureRandom; /** * This class listens to events relevant to a ghost entity's state and plays the animation when one * of the events is triggered. */ public class WaterQueenAnimationController extends Component { - // // For on collision sounds later - // private static final String COLLISION_SFX = "sounds/projectiles/on_collision.mp3"; - // Sound onCollisionSound = ServiceLocator.getResourceService().getAsset( - // COLLISION_SFX, Sound.class); AnimationRenderComponent animator; - private SecureRandom rand = new SecureRandom(); private static final String ATTACK_SOUND = "sounds/mobs/waterQueenSpell.mp3"; Sound attackSound = ServiceLocator.getResourceService().getAsset( diff --git a/source/core/src/main/com/csse3200/game/components/npc/WaterSlimeAnimationController.java b/source/core/src/main/com/csse3200/game/components/npc/WaterSlimeAnimationController.java index 6909dad10..52163ddcb 100644 --- a/source/core/src/main/com/csse3200/game/components/npc/WaterSlimeAnimationController.java +++ b/source/core/src/main/com/csse3200/game/components/npc/WaterSlimeAnimationController.java @@ -2,19 +2,13 @@ import com.csse3200.game.components.Component; import com.csse3200.game.rendering.AnimationRenderComponent; -import java.security.SecureRandom; /** * This class listens to events relevant to a ghost entity's state and plays the animation when one * of the events is triggered. */ public class WaterSlimeAnimationController extends Component { - // // For on collision sounds later - // private static final String COLLISION_SFX = "sounds/projectiles/on_collision.mp3"; - // Sound onCollisionSound = ServiceLocator.getResourceService().getAsset( - // COLLISION_SFX, Sound.class); AnimationRenderComponent animator; - private SecureRandom rand = new SecureRandom(); @Override public void create() { diff --git a/source/core/src/main/com/csse3200/game/components/npc/WizardAnimationController.java b/source/core/src/main/com/csse3200/game/components/npc/WizardAnimationController.java index c8c8e7073..80623d6db 100644 --- a/source/core/src/main/com/csse3200/game/components/npc/WizardAnimationController.java +++ b/source/core/src/main/com/csse3200/game/components/npc/WizardAnimationController.java @@ -4,19 +4,13 @@ import com.csse3200.game.components.Component; import com.csse3200.game.rendering.AnimationRenderComponent; import com.csse3200.game.services.ServiceLocator; -import java.security.SecureRandom; /** * This class listens to events relevant to a ghost entity's state and plays the animation when one * of the events is triggered. */ public class WizardAnimationController extends Component { - // // For on collision sounds later - // private static final String COLLISION_SFX = "sounds/projectiles/on_collision.mp3"; - // Sound onCollisionSound = ServiceLocator.getResourceService().getAsset( - // COLLISION_SFX, Sound.class); AnimationRenderComponent animator; - private SecureRandom rand = new SecureRandom(); /** Sound variables */ private static final String ATTACK_SOUND = "sounds/mobs/wizardSpell.mp3"; 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 ce305311e..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 @@ -1,13 +1,10 @@ package com.csse3200.game.components.pausemenu; import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.Input; import com.badlogic.gdx.audio.Sound; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.math.Interpolation; import com.badlogic.gdx.scenes.scene2d.Actor; -import com.badlogic.gdx.scenes.scene2d.InputEvent; -import com.badlogic.gdx.scenes.scene2d.InputListener; import com.badlogic.gdx.scenes.scene2d.Touchable; import com.badlogic.gdx.scenes.scene2d.actions.Actions; import com.badlogic.gdx.scenes.scene2d.actions.SequenceAction; @@ -16,14 +13,15 @@ import com.badlogic.gdx.scenes.scene2d.ui.Window; import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener; import com.csse3200.game.GdxGame; -import com.csse3200.game.components.maingame.MainGameDisplay; -import com.csse3200.game.entities.factories.PauseMenuFactory; import com.csse3200.game.services.ServiceLocator; import com.csse3200.game.ui.ButtonFactory; import com.csse3200.game.ui.UIComponent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +/** + * Implements the visual aspects of the pause menu, including button interactions. + */ public class PauseMenuButtonComponent extends UIComponent { private static final Logger logger = LoggerFactory.getLogger(PauseMenuButtonComponent.class); private static final float Z_INDEX = 2f; @@ -42,6 +40,9 @@ public PauseMenuButtonComponent(GdxGame screenSwitchHandle) { game = screenSwitchHandle; } + /** + * Sets up the buttons and window of the pause menu when it is first made. + */ @Override public void create() { super.create(); @@ -105,7 +106,6 @@ public void changed(ChangeEvent changeEvent, Actor actor) { } }); - window.setResizable(true); window.setModal(true); window.setTouchable(Touchable.enabled); @@ -119,14 +119,30 @@ public void changed(ChangeEvent changeEvent, Actor actor) { window.add(planetSelectBtn).center(); window.row(); window.add(mainMenuBtn).center(); + 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) - (WINDOW_SIZE_X / 2),0); + window.addAction(new SequenceAction(Actions.moveTo( + ( ((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); } + /** + * Draws the pause menu on the game screen. + * @param batch Batch to render to. + */ @Override protected void draw(SpriteBatch batch) { // handled by stage @@ -142,11 +158,18 @@ public void loadSounds() { closeSound = ServiceLocator.getResourceService().getAsset(sounds[1], Sound.class); } + /** + * Gets the z-index of the pause menu + * @return The z-index of the pause menu + */ @Override public float getZIndex() { return Z_INDEX; } + /** + * Removes the pause menu when the entity is disposed. + */ @Override public void dispose() { click.play(0.5f); 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 b1be835cb..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 @@ -10,7 +10,6 @@ * Handles the pausing/resuming of time when the pause menu is brought up/put away. */ public class PauseMenuTimeStopComponent extends Component { - private Array freezeList; public PauseMenuTimeStopComponent() { // Not implemented diff --git a/source/core/src/main/com/csse3200/game/components/popupmenu/PopupMenuInputComponent.java b/source/core/src/main/com/csse3200/game/components/popupmenu/PopupMenuInputComponent.java index a12dd12ad..43907be2f 100644 --- a/source/core/src/main/com/csse3200/game/components/popupmenu/PopupMenuInputComponent.java +++ b/source/core/src/main/com/csse3200/game/components/popupmenu/PopupMenuInputComponent.java @@ -7,14 +7,12 @@ * This input handler only uses keyboard input. */ public class PopupMenuInputComponent extends InputComponent{ - /** TO DO: - * This component's end goal is to send a deactivation trigger when the - * user clicks on anything other than the menu entity, and reactivate it - * if the user clicks on a tower, with the new tower's stats as per its - * config file. - * Current implementation step: trigger a generic event whenever - * the mouse is clicked, with no checks for the entity clicked on. + /** + * !!! + * NOTE: THIS CLASS IS OBSOLETE + * !!! */ + public PopupMenuInputComponent() {super(1);} // Note: will need to change constructor's priority when merging with other // branches that add other input components. 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 08aa0b627..2cc103bd8 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 @@ -6,6 +6,7 @@ import com.csse3200.game.ai.tasks.PriorityTask; import com.csse3200.game.components.CombatStatsComponent; import com.csse3200.game.components.ProjectileEffects; +import com.csse3200.game.components.npc.DodgingComponent; import com.csse3200.game.components.tasks.MovementTask; import com.csse3200.game.entities.Entity; import com.csse3200.game.entities.factories.ProjectileFactory; @@ -56,7 +57,7 @@ public class MobTask extends DefaultTask implements PriorityTask { // Enums private enum State { - RUN, ATTACK, DEATH, DEFAULT + RUN, ATTACK, DEATH, DEFAULT, DODGE } /** @@ -112,22 +113,37 @@ public void start() { @Override public void update() { + if(mob.getCenterPosition().x <= 1) { + mob.getComponent(CombatStatsComponent.class).setHealth(0); + ServiceLocator.getGameEndService().updateEngineerCount(); + } + // death check - if (mob.getComponent(CombatStatsComponent.class).getHealth() <= 0 && !deathFlag) { + if ((mob.getComponent(CombatStatsComponent.class).getHealth() <= 0 && !deathFlag)) { + // decrement engineer count + // ! tests failing because of textbox + changeState(State.DEATH); animate(); movementTask.stop(); deathFlag = true; + } else if (deathFlag && animation.isFinished()) { ServiceLocator.getWaveService().updateEnemyCount(); mob.setFlagForDelete(true); } + // Uhhh if(gameTime.getTime() >= dodgeEndTime) { if (canDodge) { mob.getEvents().trigger("dodgeIncomingEntity", mob.getCenterPosition()); - } + if(mob.getComponent(DodgingComponent.class).isTargetVisible(mob.getCenterPosition())) { + changeState(State.DODGE); + animate(); + // movementTask.stop(); + } + } dodgeEndTime = gameTime.getTime() + 500; // 500ms } @@ -164,6 +180,14 @@ public void update() { runFlag = true; } } + case DODGE -> { + if (animation.isFinished()) { + movementTask.start(); + changeState(State.RUN); + animate(); + runFlag = true; + } + } } } @@ -178,6 +202,7 @@ private void animate() { owner.getEntity().getEvents().trigger("mob_death"); owner.getEntity().getEvents().trigger("splitDeath"); } + case DODGE -> owner.getEntity().getEvents().trigger("mob_dodge"); case DEFAULT -> owner.getEntity().getEvents().trigger("mob_default"); } } diff --git a/source/core/src/main/com/csse3200/game/components/tower/DroidAnimationController.java b/source/core/src/main/com/csse3200/game/components/tower/DroidAnimationController.java index efd00a117..8ed009a12 100644 --- a/source/core/src/main/com/csse3200/game/components/tower/DroidAnimationController.java +++ b/source/core/src/main/com/csse3200/game/components/tower/DroidAnimationController.java @@ -1,5 +1,6 @@ package com.csse3200.game.components.tower; +import com.badlogic.gdx.audio.Sound; import com.badlogic.gdx.math.Vector2; import com.csse3200.game.components.Component; import com.csse3200.game.components.ProjectileEffects; @@ -16,6 +17,11 @@ public class DroidAnimationController extends Component { private AnimationRenderComponent animator; + private static final String FIRE_SINGLE_SFX = "sounds/towers/5.56_single_shot.mp3"; + + private final Sound fireSingleSound = ServiceLocator.getResourceService().getAsset( + FIRE_SINGLE_SFX, Sound.class); + /** * Creation call for a DroidAnimationController, fetches the animationRenderComponent that this controller will * be attached to and registers all the event listeners required to trigger the animations and sounds. @@ -66,6 +72,7 @@ void animateGoDown() { */ void animateAttackUp() { animator.startAnimation("attackUp"); + fireSingleSound.play(); } /** @@ -74,6 +81,7 @@ void animateAttackUp() { */ void animateAttackDown() { animator.startAnimation("attackDown"); + fireSingleSound.play(); } /** diff --git a/source/core/src/main/com/csse3200/game/components/tower/EconTowerAnimationController.java b/source/core/src/main/com/csse3200/game/components/tower/EconTowerAnimationController.java index 3fcd566f5..3e9a3a785 100644 --- a/source/core/src/main/com/csse3200/game/components/tower/EconTowerAnimationController.java +++ b/source/core/src/main/com/csse3200/game/components/tower/EconTowerAnimationController.java @@ -1,7 +1,9 @@ package com.csse3200.game.components.tower; +import com.badlogic.gdx.audio.Sound; import com.csse3200.game.components.Component; import com.csse3200.game.rendering.AnimationRenderComponent; +import com.csse3200.game.services.ServiceLocator; /** * Listens for events relevant to a weapon tower state. @@ -15,6 +17,11 @@ public class EconTowerAnimationController extends Component { private static final String ECO_MOVE = "move1"; private static final String ECO_IDLE = "idle"; + private static final String PING = "sounds/towers/eco_tower_ping.mp3"; + + private final Sound ping = ServiceLocator.getResourceService().getAsset( + PING, Sound.class); + AnimationRenderComponent animator; /** @@ -36,7 +43,8 @@ void animateIdle() { animator.startAnimation(ECO_IDLE); } - void animateMove() { animator.startAnimation(ECO_MOVE); } + void animateMove() { animator.startAnimation(ECO_MOVE); + ping.play();} } \ No newline at end of file diff --git a/source/core/src/main/com/csse3200/game/components/tower/FireTowerAnimationController.java b/source/core/src/main/com/csse3200/game/components/tower/FireTowerAnimationController.java index 0bfe1fe11..b370365d1 100644 --- a/source/core/src/main/com/csse3200/game/components/tower/FireTowerAnimationController.java +++ b/source/core/src/main/com/csse3200/game/components/tower/FireTowerAnimationController.java @@ -23,6 +23,11 @@ public class FireTowerAnimationController extends Component{ private static final String DEATH_ANIM = "death"; //here we can add the sounds for the implemented animations + private static final String FIRE_SINGLE_SFX = "sounds/towers/Desert-Eagle-Far-Single-Gunshot.mp3"; + + private final Sound fireSingleSound = ServiceLocator.getResourceService().getAsset( + FIRE_SINGLE_SFX, Sound.class); + AnimationRenderComponent animator; /** @@ -57,6 +62,7 @@ void animatePrepAttack() { */ void animateAttack() { animator.startAnimation(ATTACK_ANIM); + fireSingleSound.play(); } void animateDeath() { diff --git a/source/core/src/main/com/csse3200/game/components/tower/FireworksTowerAnimationController.java b/source/core/src/main/com/csse3200/game/components/tower/FireworksTowerAnimationController.java index cd701b0db..e9ec5c653 100644 --- a/source/core/src/main/com/csse3200/game/components/tower/FireworksTowerAnimationController.java +++ b/source/core/src/main/com/csse3200/game/components/tower/FireworksTowerAnimationController.java @@ -1,7 +1,9 @@ package com.csse3200.game.components.tower; +import com.badlogic.gdx.audio.Sound; import com.csse3200.game.components.Component; import com.csse3200.game.rendering.AnimationRenderComponent; +import com.csse3200.game.services.ServiceLocator; /** * This class listens to events relevant to DroidTower entity's state and plays the animation when one @@ -10,6 +12,11 @@ public class FireworksTowerAnimationController extends Component { private AnimationRenderComponent animator; + private static final String FIRE_SINGLE_SFX = "sounds/towers/5.56_single_shot.mp3"; + + private final Sound fireSingleSound = ServiceLocator.getResourceService().getAsset( + FIRE_SINGLE_SFX, Sound.class); + /** * Creation call for a DroidAnimationController, fetches the animationRenderComponent that this controller will * be attached to and registers all the event listeners required to trigger the animations and sounds. @@ -30,6 +37,7 @@ public void create() { */ void animateAttack() { animator.startAnimation("Attack"); + fireSingleSound.play(); } diff --git a/source/core/src/main/com/csse3200/game/components/tower/PierceTowerAnimationController.java b/source/core/src/main/com/csse3200/game/components/tower/PierceTowerAnimationController.java index 9daa39acb..f9018e0af 100644 --- a/source/core/src/main/com/csse3200/game/components/tower/PierceTowerAnimationController.java +++ b/source/core/src/main/com/csse3200/game/components/tower/PierceTowerAnimationController.java @@ -1,7 +1,9 @@ package com.csse3200.game.components.tower; +import com.badlogic.gdx.audio.Sound; import com.csse3200.game.components.Component; import com.csse3200.game.rendering.AnimationRenderComponent; +import com.csse3200.game.services.ServiceLocator; /** * Listens to triggers phrases and executes the required animations. @@ -19,7 +21,10 @@ public class PierceTowerAnimationController extends Component { private static final String ALERT_ANIM = "Warning"; //further sounds can be added for the tower attacks/movement + private static final String FIRE_SINGLE_SFX = "sounds/towers/5.56_single_shot.mp3"; + private final Sound fireSingleSound = ServiceLocator.getResourceService().getAsset( + FIRE_SINGLE_SFX, Sound.class); AnimationRenderComponent animator; /** @@ -48,6 +53,7 @@ void animateIdle() { */ void animateAttack() { animator.startAnimation(ATTACK_ANIM); + fireSingleSound.play(); } /** diff --git a/source/core/src/main/com/csse3200/game/components/tower/RicochetTowerAnimationController.java b/source/core/src/main/com/csse3200/game/components/tower/RicochetTowerAnimationController.java index 1a197868b..8210e7d73 100644 --- a/source/core/src/main/com/csse3200/game/components/tower/RicochetTowerAnimationController.java +++ b/source/core/src/main/com/csse3200/game/components/tower/RicochetTowerAnimationController.java @@ -1,13 +1,19 @@ package com.csse3200.game.components.tower; +import com.badlogic.gdx.audio.Sound; import com.csse3200.game.components.Component; import com.csse3200.game.rendering.AnimationRenderComponent; +import com.csse3200.game.services.ServiceLocator; /** * This class listens to events relevant to DroidTower entity's state and plays the animation when one * of the events is triggered. */ public class RicochetTowerAnimationController extends Component { + private static final String FIRE_SINGLE_SFX = "sounds/towers/5.56_single_shot.mp3"; + + private final Sound fireSingleSound = ServiceLocator.getResourceService().getAsset( + FIRE_SINGLE_SFX, Sound.class); private AnimationRenderComponent animator; /** @@ -30,6 +36,7 @@ public void create() { */ void animateAttack() { animator.startAnimation("Attack"); + fireSingleSound.play(); } diff --git a/source/core/src/main/com/csse3200/game/components/tower/StunTowerAnimationController.java b/source/core/src/main/com/csse3200/game/components/tower/StunTowerAnimationController.java index 846d344dd..d3eaec777 100644 --- a/source/core/src/main/com/csse3200/game/components/tower/StunTowerAnimationController.java +++ b/source/core/src/main/com/csse3200/game/components/tower/StunTowerAnimationController.java @@ -20,6 +20,11 @@ public class StunTowerAnimationController extends Component { //further sounds can be added for the tower attacks/movement + private static final String FIRE_SINGLE_SFX = "sounds/towers/ar15_single_shot_far.mp3"; + + private final Sound fireSingleSound = ServiceLocator.getResourceService().getAsset( + FIRE_SINGLE_SFX, Sound.class); + AnimationRenderComponent animator; /** @@ -47,6 +52,7 @@ void animateIdle() { */ void animateAttack() { animator.startAnimation(ATTACK_ANIM); + fireSingleSound.play(); } /** diff --git a/source/core/src/main/com/csse3200/game/components/tower/TNTAnimationController.java b/source/core/src/main/com/csse3200/game/components/tower/TNTAnimationController.java index 1f092dab5..4ebfa2bb8 100644 --- a/source/core/src/main/com/csse3200/game/components/tower/TNTAnimationController.java +++ b/source/core/src/main/com/csse3200/game/components/tower/TNTAnimationController.java @@ -1,7 +1,9 @@ package com.csse3200.game.components.tower; +import com.badlogic.gdx.audio.Sound; import com.csse3200.game.components.Component; import com.csse3200.game.rendering.AnimationRenderComponent; +import com.csse3200.game.services.ServiceLocator; /** * This class listens to events relevant to TNTTower entity's state and plays the animation when one @@ -9,6 +11,10 @@ */ public class TNTAnimationController extends Component { private AnimationRenderComponent animator; + private static final String EXPLOSION = "sounds/towers/explosion.mp3"; + + private final Sound explosion = ServiceLocator.getResourceService().getAsset( + EXPLOSION, Sound.class); /** * Creation call for a TNTAnimationController, fetches the animationRenderComponent that this controller will @@ -43,7 +49,7 @@ void animateDig() { * This method should be invoked when the entity enters the explosion state. */ void animateExplode() { animator.startAnimation("explode"); - + explosion.play(); } } diff --git a/source/core/src/main/com/csse3200/game/components/tower/TowerUpgraderComponent.java b/source/core/src/main/com/csse3200/game/components/tower/TowerUpgraderComponent.java index e83210b48..4394d6309 100644 --- a/source/core/src/main/com/csse3200/game/components/tower/TowerUpgraderComponent.java +++ b/source/core/src/main/com/csse3200/game/components/tower/TowerUpgraderComponent.java @@ -3,17 +3,21 @@ import com.csse3200.game.components.CombatStatsComponent; import com.csse3200.game.components.Component; -import static com.csse3200.game.screens.TowerType.INCOME; - /** * Listens for an event from the popup menu to upgrade * the turret entity this component is attached to. */ public class TowerUpgraderComponent extends Component { + /** + * Enum for specifying what type of upgrade to implement + */ public enum UPGRADE { ATTACK, MAXHP, FIRERATE, REPAIR, INCOME } + /** + * Creates the component and sets it up to respond to upgrade event triggers. + */ @Override public void create() { super.create(); @@ -29,11 +33,11 @@ public void create() { */ public void upgradeTower(UPGRADE upgradeType, int value) { switch (upgradeType) { - case INCOME -> {getEntity().getEvents().trigger("addIncome", value);} - case ATTACK -> {upgradeTowerAttack(value);} - case MAXHP -> {upgradeTowerMaxHealth( value);} - case FIRERATE -> {getEntity().getEvents().trigger("addFireRate", value);} - case REPAIR -> {repairTower();} + case INCOME -> getEntity().getEvents().trigger("addIncome", value); + case ATTACK -> upgradeTowerAttack(value); + case MAXHP -> upgradeTowerMaxHealth( value); + case FIRERATE -> getEntity().getEvents().trigger("addFireRate", value); + case REPAIR -> repairTower(); } } diff --git a/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java index e8038c978..cecd77e99 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/NPCFactory.java @@ -622,10 +622,10 @@ public static Entity createSplittingNightBorne(int health) { public static Entity createDodgingDragonKnight(int health) { Entity dodgeKnight = createDragonKnight(health); - dodgeKnight.addComponent(new DodgingComponent(PhysicsLayer.PROJECTILE, 0.25f)); + dodgeKnight.addComponent(new DodgingComponent(PhysicsLayer.PROJECTILE, 0.25f, 5f)); dodgeKnight.getComponent(AITaskComponent.class).getTask(MobTask.class).setDodge(true); - PhysicsUtils.setScaledCollider(dodgeKnight, 0.3f, 0.7f); - dodgeKnight.setScale(0.3f, 0.7f); + PhysicsUtils.setScaledCollider(dodgeKnight, 0.3f, 1f); + dodgeKnight.setScale(0.3f, 1f); return dodgeKnight; } diff --git a/source/core/src/main/com/csse3200/game/entities/factories/ProjectileFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/ProjectileFactory.java index ce160b65b..b64959976 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/ProjectileFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/ProjectileFactory.java @@ -343,7 +343,7 @@ public static Entity createBaseProjectile(short targetLayer, Vector2 // This is the component that allows the projectile to damage a // specified target. // Original knockback value: 1.5f - .addComponent(new TouchAttackComponent(targetLayer, 1.5f, true)) + .addComponent(new TouchAttackComponent(targetLayer, 0f, true)) .addComponent(new CombatStatsComponent(config.health, config.baseAttack)) // *TEMPORARY .addComponent(new DeleteOnMapEdgeComponent()); 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 bf3c8f4be..0b9f6db73 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 @@ -40,8 +40,8 @@ public class WaveFactory { )); private static final ArrayList> lvl2Structure = new ArrayList<>(Arrays.asList( - new ArrayList<>(Arrays.asList("Skeleton" - )), new ArrayList<>(Arrays.asList("Skeleton", "ArcaneArcher" + 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" 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 0dcb71dec..2d514c43a 100644 --- a/source/core/src/main/com/csse3200/game/input/BuildInputComponent.java +++ b/source/core/src/main/com/csse3200/game/input/BuildInputComponent.java @@ -13,8 +13,6 @@ import com.csse3200.game.screens.TowerType; import com.csse3200.game.services.CurrencyService; import com.csse3200.game.services.ServiceLocator; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** @@ -22,7 +20,6 @@ * DropInputComponent */ public class BuildInputComponent extends InputComponent { - private static final Logger logger = LoggerFactory.getLogger(BuildInputComponent.class); private final EntityService entityService; private final Camera camera; private final String[] sounds = { @@ -44,7 +41,6 @@ public BuildInputComponent(Camera camera) { loadSounds(); towers.addAll(ServiceLocator.getTowerTypes()); - logger.debug(String.format("selected towers in buildInputComponent are %s", towers)); TowerType[] defaultTowerTypes = { TowerType.TNT, TowerType.DROID, @@ -55,10 +51,15 @@ public BuildInputComponent(Camera camera) { Array defaultTowers = new Array<>(); defaultTowers.addAll(defaultTowerTypes); - if (towers.isEmpty()) { - ServiceLocator.setTowerTypes(defaultTowers); - towers = defaultTowers; + if (towers.isEmpty() || towers.size < 5) { + for (TowerType tower : defaultTowers) { + if (towers.size < 5 && !towers.contains(tower, true)) { + towers.add(tower); + } + } } + + ServiceLocator.setTowerTypes(towers); } /** @@ -90,11 +91,9 @@ public boolean touchDown(int screenX, int screenY, int pointer, int button) { // determine if the tile is unoccupied boolean tileOccupied = entityService.entitiesInTile((int)cursorPosition.x, (int)cursorPosition.y); - logger.debug(String.format("Tile is occupied: %s", tileOccupied)); // check that no entities are occupying the tile if (!tileOccupied) { - logger.debug(String.format("spawning a tower at %f, %f", cursorPosition.x, cursorPosition.y)); return buildTower((int)cursorPosition.x, (int)cursorPosition.y); } else { return false; @@ -111,31 +110,35 @@ public boolean touchDown(int screenX, int screenY, int pointer, int button) { @Override public boolean keyUp(int keycode) { switch (keycode) { - case Input.Keys.NUM_1: + case Input.Keys.NUM_1 -> { ServiceLocator.getCurrencyService().setTowerType(towers.get(0)); - return true; - case Input.Keys.NUM_2: + } + case Input.Keys.NUM_2 -> { ServiceLocator.getCurrencyService().setTowerType(towers.get(1)); return true; - case Input.Keys.NUM_3: + } + case Input.Keys.NUM_3 -> { ServiceLocator.getCurrencyService().setTowerType(towers.get(2)); return true; - case Input.Keys.NUM_4: + } + case Input.Keys.NUM_4 -> { ServiceLocator.getCurrencyService().setTowerType(towers.get(3)); return true; - case Input.Keys.NUM_5: + } + case Input.Keys.NUM_5 -> { ServiceLocator.getCurrencyService().setTowerType(towers.get(4)); return true; - case Input.Keys.CONTROL_LEFT: + } + case Input.Keys.CONTROL_LEFT -> { // After multiple placement, deselect tower and prevent further builds ServiceLocator.getCurrencyService().setTowerType(null); multipleTowerBuild = false; return true; - case Input.Keys.ESCAPE: - - default: + } + default -> { return false; + } } } @@ -161,53 +164,26 @@ public boolean keyDown(int keycode) { * @param y y-coordinate int value */ public boolean buildTower(int x, int y) { - TowerType tower; - CurrencyService currencyService; // fetch the currently set TowerType in the currency service, and its associated build cost. - currencyService = ServiceLocator.getCurrencyService(); - if (currencyService == null) { - // if the currency service fails or is not running - return false; - } - tower = currencyService.getTower(); + CurrencyService currencyService = ServiceLocator.getCurrencyService(); + TowerType tower = currencyService.getTower(); if (tower != null) { // fetch the price of the selected tower and attempt to instantiate int cost = Integer.parseInt(currencyService.getTower().getPrice()); - if (cost <= currencyService.getScrap().getAmount()) { - Entity newTower = switch (tower) { - case WEAPON -> TowerFactory.createWeaponTower(); - case INCOME -> TowerFactory.createIncomeTower(); - case TNT -> TowerFactory.createTNTTower(); - case DROID -> TowerFactory.createDroidTower(); - 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); - - if (entityService == null){ - return false; - } - entityService.register(newTower); - // Decrement currency and show a popup that reflects the cost of the build - ServiceLocator.getCurrencyService().getScrap().modify(-cost); - ServiceLocator.getCurrencyService().getDisplay().updateScrapsStats(); - ServiceLocator.getCurrencyService().getDisplay().currencyPopUp(x, y, -cost, 10); + if (canAfford(cost)) { + createTower(tower, x, y, cost); long soundId = buildSound.play(); buildSound.setVolume(soundId, 0.4f); - // deselect the tower after building + // deselect the tower after building if not in multiple placement mode if (!multipleTowerBuild) { ServiceLocator.getCurrencyService().setTowerType(null); } return true; + } else { // play a sound to indicate an invalid action long soundId = errorSound.play(); @@ -218,6 +194,47 @@ public boolean buildTower(int x, int y) { return false; } + /** + * Creates the new tower instance + * @param tower the TowerType currently set + * @param x the x position int the tower will occupy + * @param y the y position int the tower will occupy + */ + private void createTower(TowerType tower, int x, int y, int cost) { + if (tower == null) { + return; + } + Entity newTower = switch (tower) { + case WEAPON -> TowerFactory.createWeaponTower(); + case INCOME -> TowerFactory.createIncomeTower(); + case TNT -> TowerFactory.createTNTTower(); + case DROID -> TowerFactory.createDroidTower(); + 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); + entityService.register(newTower); + + // Decrement currency and show a popup that reflects the cost of the build + ServiceLocator.getCurrencyService().getScrap().modify(-cost); + ServiceLocator.getCurrencyService().getDisplay().updateScrapsStats(); + ServiceLocator.getCurrencyService().getDisplay().currencyPopUp(x, y, -cost, 10); + } + + /** + * Determines if there are sufficient resources for a tower build + * @param cost integer representing the cost of the intended build + * @return true if the cost is less than or equal to the current balance, false otherwise + */ + private boolean canAfford(int cost) { + return (cost <= ServiceLocator.getCurrencyService().getScrap().getAmount()); + } + /** * Load the sound assets related to in-game tower building activity */ 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 11bbf590a..602409bcf 100644 --- a/source/core/src/main/com/csse3200/game/screens/TowerType.java +++ b/source/core/src/main/com/csse3200/game/screens/TowerType.java @@ -15,11 +15,11 @@ public enum TowerType { 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-selected.png"), - PIERCE("Pierce Tower", "", "The Pierce Tower fires a projectile that pierces through targets and does not dissipate upon contact.", + 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", "", "The Ricochet Tower fires a projectile that upon contact does damage and changes direction", + 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", "", "The Firework Tower fires a projectile that splits on contact with its target", + 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; diff --git a/source/core/src/test/com/csse3200/game/components/SplitMoblingsTest.java b/source/core/src/test/com/csse3200/game/components/SplitMoblingsTest.java index 49fdeeee0..4b1fcf15e 100644 --- a/source/core/src/test/com/csse3200/game/components/SplitMoblingsTest.java +++ b/source/core/src/test/com/csse3200/game/components/SplitMoblingsTest.java @@ -13,6 +13,7 @@ import java.util.ArrayList; import java.util.Arrays; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.extension.ExtendWith; @@ -31,6 +32,7 @@ import com.csse3200.game.physics.components.HitboxComponent; import com.csse3200.game.rendering.DebugRenderer; import com.csse3200.game.rendering.RenderService; +import com.csse3200.game.services.GameEndService; import com.csse3200.game.services.GameTime; import com.csse3200.game.services.ResourceService; import com.csse3200.game.services.ServiceLocator; @@ -56,6 +58,7 @@ public void setUp() { ServiceLocator.registerPhysicsService(new PhysicsService()); ServiceLocator.registerEntityService(new EntityService()); + ServiceLocator.registerGameEndService(new GameEndService()); RenderService render = new RenderService(); render.setDebug(mock(DebugRenderer.class)); @@ -69,14 +72,16 @@ public void setUp() { WaveService waveService = mock(WaveService.class); ServiceLocator.registerWaveService(waveService); + GameEndService gameEndService = new GameEndService(); + ServiceLocator.registerGameEndService(gameEndService); + baseMob = createSplitMob(BASE_AMOUNT); } @Test void shouldNotBeNull() { Entity mob = createSplitMob(5); - assertNotNull("Mobling components does not exists", - mob.getComponent(SplitMoblings.class)); + Assertions.assertNotNull(mob.getComponent(SplitMoblings.class), "Mobling components does not exists"); } @Test @@ -90,8 +95,7 @@ void shouldHaveAsset() { if (entity.equals(baseMob) || entity.equals(projectile)) continue; - assertTrue("moblings does not contain the right asset", - ServiceLocator.getResourceService().containsAsset(atlas[0], entity.getClass())); + Assertions.assertTrue(ServiceLocator.getResourceService().containsAsset(atlas[0], entity.getClass()), "moblings does not contain the right asset"); } } diff --git a/source/core/src/test/com/csse3200/game/components/pausemenu/PauseMenuTimeStopComponentTest.java b/source/core/src/test/com/csse3200/game/components/pausemenu/PauseMenuTimeStopComponentTest.java index f097b5bb3..3018c6434 100644 --- a/source/core/src/test/com/csse3200/game/components/pausemenu/PauseMenuTimeStopComponentTest.java +++ b/source/core/src/test/com/csse3200/game/components/pausemenu/PauseMenuTimeStopComponentTest.java @@ -19,9 +19,9 @@ public class PauseMenuTimeStopComponentTest { void beforeEach() { EntityService entityService = new EntityService(); ServiceLocator.registerEntityService(entityService); - WaveService waveService = new WaveService(); + WaveService waveService = mock(WaveService.class); ServiceLocator.registerWaveService(waveService); - GameTime gameTime = new GameTime(); + GameTime gameTime = mock(GameTime.class); ServiceLocator.registerTimeSource(gameTime); entity = mock(Entity.class); when(entity.getId()).thenReturn(-1); //Ensure it does not coincide with the pause menu's ID @@ -52,4 +52,17 @@ void doesNotPauseNewEntities() { ServiceLocator.getEntityService().register(lateEntity); verify(lateEntity, times(0)).setEnabled(false); } + + @Test + void waveServiceIsPaused() { + ServiceLocator.getEntityService().register(pauseMenu); + verify(ServiceLocator.getWaveService()).toggleGamePause(); + } + + @Test + void waveServiceIsPausedAndUnpaused() { + ServiceLocator.getEntityService().register(pauseMenu); + pauseMenu.dispose(); + verify(ServiceLocator.getWaveService(), times(2)).toggleGamePause(); + } } diff --git a/source/core/src/test/com/csse3200/game/components/tower/DroidAnimationControllerTest.java b/source/core/src/test/com/csse3200/game/components/tower/DroidAnimationControllerTest.java index bbae63278..a752a20c0 100644 --- a/source/core/src/test/com/csse3200/game/components/tower/DroidAnimationControllerTest.java +++ b/source/core/src/test/com/csse3200/game/components/tower/DroidAnimationControllerTest.java @@ -23,6 +23,10 @@ public class DroidAnimationControllerTest { private final String[] texture = {"images/towers/DroidTower.png"}; private final String[] atlas = {"images/towers/DroidTower.atlas"}; + private static final String[] sounds = { + "sounds/towers/5.56_single_shot.mp3" + }; + @BeforeEach public void setUp() { ServiceLocator.registerPhysicsService(new PhysicsService()); @@ -33,6 +37,7 @@ public void setUp() { ServiceLocator.registerResourceService(resourceService); resourceService.loadTextures(texture); resourceService.loadTextureAtlases(atlas); + resourceService.loadSounds(sounds); resourceService.loadAll(); mockEntity = TowerFactory.createDroidTower(); // Replace with actual Droid Tower creation logic diff --git a/source/core/src/test/com/csse3200/game/components/tower/FireTowerAnimationControllerTest.java b/source/core/src/test/com/csse3200/game/components/tower/FireTowerAnimationControllerTest.java index f6d91ddd3..c8187529b 100644 --- a/source/core/src/test/com/csse3200/game/components/tower/FireTowerAnimationControllerTest.java +++ b/source/core/src/test/com/csse3200/game/components/tower/FireTowerAnimationControllerTest.java @@ -23,6 +23,10 @@ public class FireTowerAnimationControllerTest { private final String[] texture = {"images/towers/fire_tower_atlas.png"}; private final String[] atlas = {"images/towers/fire_tower_atlas.atlas"}; + private static final String[] sounds = { + "sounds/towers/Desert-Eagle-Far-Single-Gunshot.mp3" + }; + @BeforeEach public void setUp() { ServiceLocator.registerPhysicsService(new PhysicsService()); @@ -33,6 +37,7 @@ public void setUp() { ServiceLocator.registerResourceService(resourceService); resourceService.loadTextures(texture); resourceService.loadTextureAtlases(atlas); + resourceService.loadSounds(sounds); resourceService.loadAll(); mockEntity = TowerFactory.createFireTower(); // Replace with actual Droid Tower creation logic diff --git a/source/core/src/test/com/csse3200/game/components/tower/StunTowerAnimationControllerTest.java b/source/core/src/test/com/csse3200/game/components/tower/StunTowerAnimationControllerTest.java index 478fd7314..7e5c272ba 100644 --- a/source/core/src/test/com/csse3200/game/components/tower/StunTowerAnimationControllerTest.java +++ b/source/core/src/test/com/csse3200/game/components/tower/StunTowerAnimationControllerTest.java @@ -22,6 +22,9 @@ public class StunTowerAnimationControllerTest { private Entity mockEntity; private final String[] texture = {"images/towers/stun_tower.png"}; private final String[] atlas = {"images/towers/stun_tower.atlas"}; + private static final String[] sounds = { + "sounds/towers/ar15_single_shot_far.mp3" + }; @BeforeEach public void setUp() { @@ -33,6 +36,7 @@ public void setUp() { ServiceLocator.registerResourceService(resourceService); resourceService.loadTextures(texture); resourceService.loadTextureAtlases(atlas); + resourceService.loadSounds(sounds); resourceService.loadAll(); mockEntity = TowerFactory.createStunTower(); // Replace with actual Droid Tower creation logic diff --git a/source/core/src/test/com/csse3200/game/components/tower/TNTAnimationControllerTest.java b/source/core/src/test/com/csse3200/game/components/tower/TNTAnimationControllerTest.java index d72dd437e..a76f4ad18 100644 --- a/source/core/src/test/com/csse3200/game/components/tower/TNTAnimationControllerTest.java +++ b/source/core/src/test/com/csse3200/game/components/tower/TNTAnimationControllerTest.java @@ -25,6 +25,10 @@ public class TNTAnimationControllerTest { private final String[] texture = {"images/towers/TNTTower.png"}; private final String[] atlas = {"images/towers/TNTTower.atlas"}; + private static final String[] sounds = { + "sounds/towers/explosion.mp3" + }; + @BeforeEach public void setUp() { @@ -37,6 +41,7 @@ public void setUp() { ServiceLocator.registerResourceService(resourceService); resourceService.loadTextures(texture); resourceService.loadTextureAtlases(atlas); + resourceService.loadSounds(sounds); resourceService.loadAll(); mockEntity = TowerFactory.createTNTTower(); diff --git a/source/core/src/test/com/csse3200/game/entities/factories/PauseMenuFactoryTest.java b/source/core/src/test/com/csse3200/game/entities/factories/PauseMenuFactoryTest.java index 1feb7101f..ddcb22223 100644 --- a/source/core/src/test/com/csse3200/game/entities/factories/PauseMenuFactoryTest.java +++ b/source/core/src/test/com/csse3200/game/entities/factories/PauseMenuFactoryTest.java @@ -22,9 +22,6 @@ public class PauseMenuFactoryTest { Entity entity; GdxGame game; - String[] texture = { - "images/ui/Sprites/UI_Glass_Toggle_Bar_01a.png" - }; @BeforeEach void beforeEach() { EntityService entityService = new EntityService(); @@ -38,7 +35,6 @@ void beforeEach() { ServiceLocator.registerRenderService(renderService); ResourceService resourceService = new ResourceService(); ServiceLocator.registerResourceService(resourceService); - resourceService.loadTextures(texture); resourceService.loadAll(); game = mock(GdxGame.class); diff --git a/source/core/src/test/com/csse3200/game/entities/factories/TowerFactoryTest.java b/source/core/src/test/com/csse3200/game/entities/factories/TowerFactoryTest.java index e3d20b53a..01462c0f1 100644 --- a/source/core/src/test/com/csse3200/game/entities/factories/TowerFactoryTest.java +++ b/source/core/src/test/com/csse3200/game/entities/factories/TowerFactoryTest.java @@ -55,7 +55,13 @@ public class TowerFactoryTest { private static final String[] sounds = { "sounds/towers/gun_shot_trimmed.mp3", "sounds/towers/deploy.mp3", - "sounds/towers/stow.mp3" + "sounds/towers/stow.mp3", + "sounds/towers/Desert-Eagle-Far-Single-Gunshot.mp3", + "sounds/towers/5.56_single_shot.mp3", + "sounds/towers/explosion.mp3", + "sounds/towers/eco_tower_ping.mp3", + "sounds/towers/ar15_single_shot_far.mp3" + }; @BeforeEach diff --git a/source/core/src/test/com/csse3200/game/input/BuildInputComponentTest.java b/source/core/src/test/com/csse3200/game/input/BuildInputComponentTest.java index 77e81bb5b..36d9b8600 100644 --- a/source/core/src/test/com/csse3200/game/input/BuildInputComponentTest.java +++ b/source/core/src/test/com/csse3200/game/input/BuildInputComponentTest.java @@ -6,16 +6,11 @@ import com.badlogic.gdx.graphics.Camera; import com.csse3200.game.areas.terrain.TerrainComponent; import com.csse3200.game.components.CameraComponent; -import com.csse3200.game.components.gamearea.CurrencyDisplay; -import com.csse3200.game.entities.Entity; import com.csse3200.game.entities.EntityService; -import com.csse3200.game.entities.factories.TowerFactory; import com.csse3200.game.extensions.GameExtension; import com.csse3200.game.physics.PhysicsService; -import com.csse3200.game.rendering.AnimationRenderComponent; import com.csse3200.game.rendering.DebugRenderer; import com.csse3200.game.rendering.RenderService; -import com.csse3200.game.screens.MainGameScreen; import com.csse3200.game.screens.TowerType; import com.csse3200.game.services.*; import org.junit.jupiter.api.BeforeEach;