Skip to content

Commit 8a65149

Browse files
authored
Merge pull request #241 from UQcsse3200/Map/Path-feature
Add Narrative Systems, Weather Effects, and Environmental Updates
2 parents 2bab70f + f1c9b08 commit 8a65149

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+2316
-503
lines changed

source/core/assets/configs/player.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"health": 100,
2+
"health": 400,
33
"baseAttack": 10,
44
"gold": 50,
55
"favouriteColour": "peach"
3.97 MB
Loading
2.48 MB
Loading
-1.97 MB
Binary file not shown.

source/core/assets/saves/111.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"player":{"pos":{"x":14.31,"y":2.31},"hp":980,"gold":50150},"enemies":[{"type":"grunt","pos":{"x":5.003304,"y":3.0008469},"hp":50},{"type":"drone","pos":{"x":14.603464,"y":3.0997891},"hp":25},{"type":"drone","pos":{"x":12.391519,"y":4.330454},"hp":25},{"type":"drone","pos":{"x":8.92149,"y":5.9875093},"hp":15}]}
58 KB
Binary file not shown.

source/core/assets/sounds/haha.mp3

174 KB
Binary file not shown.
Binary file not shown.

source/core/src/main/com/csse3200/game/areas/ForestGameArea.java

Lines changed: 111 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141

4242
import java.util.ArrayList;
4343
import java.util.List;
44+
import java.util.Locale;
4445

4546

4647
import com.csse3200.game.components.currencysystem.CurrencyManagerComponent;
@@ -112,6 +113,10 @@ public class ForestGameArea extends GameArea {
112113
"sounds/place_soft_click.ogg",
113114
"sounds/place_metal_clunk.ogg",
114115
"sounds/place_energy_drop.ogg",
116+
"sounds/Impact4.ogg",
117+
"sounds/Explosion_sfx3.ogg",
118+
"sounds/sci-fi-effect-about-danger-alarm-sound.mp3",
119+
"sounds/explosion-in-the-cave.mp3",
115120
"sounds/Enemy Sounds/tank/Tank_Death.mp3",
116121
"sounds/Enemy Sounds/tank/Tank_Walk.mp3",
117122
"sounds/Enemy Sounds/tank/Tank_Attack.mp3",
@@ -139,6 +144,8 @@ public class ForestGameArea extends GameArea {
139144
"sounds/Enemy Sounds/speedster/Speedster_Attack.mp3",
140145
"sounds/Enemy Sounds/speedster/Speedster_Random_Noise.mp3"
141146
};
147+
private static final String PLASMA_WARNING_SOUND = "sounds/sci-fi-effect-about-danger-alarm-sound.mp3";
148+
private static final String PLASMA_IMPACT_SOUND = "sounds/explosion-in-the-cave.mp3";
142149
private static final String backgroundMusic = "sounds/new_menutheme.mp3";
143150
private static final String[] forestMusic = {backgroundMusic};
144151

@@ -611,7 +618,7 @@ public void update() {
611618
mapHighlighter.setTowerUpgradeMenu(towerUpgradeMenu);
612619

613620
if (!hasExistingPlayer) {
614-
spawnIntroDialogue();
621+
showChapterIntro();
615622
}
616623

617624
// Add hero placement system
@@ -730,7 +737,11 @@ private void handlePlasmaImpact(Vector2 position) {
730737
towerTargets.add(entity);
731738
continue;
732739
}
733-
if (entity.getComponent(EnemyTypeComponent.class) != null) {
740+
EnemyTypeComponent typeComponent = entity.getComponent(EnemyTypeComponent.class);
741+
if (typeComponent != null) {
742+
if (isPlasmaImmune(typeComponent)) {
743+
continue;
744+
}
734745
enemyTargets.add(entity);
735746
}
736747
}
@@ -769,6 +780,18 @@ private void dismantleTower(Entity tower) {
769780
ServiceLocator.getEntityService().unregister(tower);
770781
}
771782

783+
private boolean isPlasmaImmune(EnemyTypeComponent typeComponent) {
784+
if (typeComponent == null) {
785+
return false;
786+
}
787+
String type = typeComponent.getType();
788+
if (type == null) {
789+
return false;
790+
}
791+
String normalised = type.trim().toLowerCase(Locale.ROOT);
792+
return "tank".equals(normalised) || "boss".equals(normalised);
793+
}
794+
772795
private void eliminateEnemy(Entity enemy) {
773796
CombatStatsComponent stats = enemy.getComponent(CombatStatsComponent.class);
774797
if (stats != null) {
@@ -1135,6 +1158,7 @@ private void spawnSamuraiAt(GridPoint2 cell) {
11351158
}
11361159

11371160
private void createHeroPlacementUI() {
1161+
// 先创建英雄放置实体,但初始隐藏
11381162
var gs = ServiceLocator.getGameStateService();
11391163
GameStateService.HeroType chosen = gs.getSelectedHero();
11401164
java.util.function.Consumer<com.badlogic.gdx.math.GridPoint2> placeCb =
@@ -1147,6 +1171,45 @@ private void createHeroPlacementUI() {
11471171
.addComponent(new com.csse3200.game.components.hero.HeroPlacementComponent(terrain, mapEditor, placeCb))
11481172
.addComponent(new com.csse3200.game.components.hero.HeroHotbarDisplay());
11491173
spawnEntity(placementEntity);
1174+
1175+
// 立即隐藏英雄UI
1176+
hideHeroUI();
1177+
1178+
// 2秒后显示英雄UI
1179+
com.badlogic.gdx.utils.Timer.schedule(new com.badlogic.gdx.utils.Timer.Task() {
1180+
@Override
1181+
public void run() {
1182+
showHeroUI();
1183+
}
1184+
}, 2.0f);
1185+
}
1186+
1187+
/**
1188+
* 隐藏英雄UI
1189+
*/
1190+
private void hideHeroUI() {
1191+
for (Entity entity : ServiceLocator.getEntityService().getEntities()) {
1192+
com.csse3200.game.components.hero.HeroHotbarDisplay heroUI = entity.getComponent(com.csse3200.game.components.hero.HeroHotbarDisplay.class);
1193+
if (heroUI != null) {
1194+
heroUI.setVisible(false);
1195+
logger.info("英雄UI已隐藏");
1196+
break;
1197+
}
1198+
}
1199+
}
1200+
1201+
/**
1202+
* 显示英雄UI
1203+
*/
1204+
private void showHeroUI() {
1205+
for (Entity entity : ServiceLocator.getEntityService().getEntities()) {
1206+
com.csse3200.game.components.hero.HeroHotbarDisplay heroUI = entity.getComponent(com.csse3200.game.components.hero.HeroHotbarDisplay.class);
1207+
if (heroUI != null) {
1208+
heroUI.setVisible(true);
1209+
logger.info("英雄UI已显示");
1210+
break;
1211+
}
1212+
}
11501213
}
11511214

11521215
private void spawnIntroDialogue() {
@@ -1173,6 +1236,27 @@ private void spawnIntroDialogue() {
11731236
);
11741237
spawnEntity(dialogueEntity);
11751238
}
1239+
1240+
/**
1241+
* 显示章节介绍
1242+
*/
1243+
private void showChapterIntro() {
1244+
String[] storyTexts = {
1245+
"Chapter I : Icebox",
1246+
"This is Icebox, a former research outpost now buried beneath eternal night.\nThe AI legions have ravaged this land beyond recognition,\nbut now, it stands as the cradle of humanity's awakening.",
1247+
"The sorcerers gathered here forming circles of frost and flame\nunleashed the first wave of pure human magic, untouched by machines.\nGlaciers shattered. Circuits failed.\nAcross the frozen plains, the echoes of ancient power\nannounced the dawn of rebellion.\n\n\"On the coldest land, the oldest flame burns once more.\""
1248+
};
1249+
1250+
Entity chapterEntity = new Entity().addComponent(
1251+
new com.csse3200.game.components.maingame.ChapterIntroComponent(
1252+
storyTexts,
1253+
() -> {
1254+
// 章节介绍结束后开始对话
1255+
spawnIntroDialogue();
1256+
})
1257+
);
1258+
spawnEntity(chapterEntity);
1259+
}
11761260

11771261
/**
11781262
* Spawn the wave tracker UI
@@ -1187,15 +1271,30 @@ private void spawnWaveTracker() {
11871271
* 显示防御塔UI(在对话结束后调用)
11881272
*/
11891273
private void showTowerUI() {
1190-
// 找到主UI实体并显示防御塔列表组件
1274+
// 先隐藏塔防UI
11911275
for (Entity entity : ServiceLocator.getEntityService().getEntities()) {
11921276
TowerHotbarDisplay towerUI = entity.getComponent(TowerHotbarDisplay.class);
11931277
if (towerUI != null) {
1194-
towerUI.setVisible(true);
1195-
logger.info("防御塔列表已显示");
1278+
towerUI.setVisible(false);
1279+
logger.info("防御塔列表已隐藏");
11961280
break;
11971281
}
11981282
}
1283+
1284+
// 3.3秒后显示塔防UI
1285+
com.badlogic.gdx.utils.Timer.schedule(new com.badlogic.gdx.utils.Timer.Task() {
1286+
@Override
1287+
public void run() {
1288+
for (Entity entity : ServiceLocator.getEntityService().getEntities()) {
1289+
TowerHotbarDisplay towerUI = entity.getComponent(TowerHotbarDisplay.class);
1290+
if (towerUI != null) {
1291+
towerUI.setVisible(true);
1292+
logger.info("防御塔列表已显示");
1293+
break;
1294+
}
1295+
}
1296+
}
1297+
}, 2.0f);
11991298
}
12001299

12011300
private void playMusic() {
@@ -1219,9 +1318,13 @@ private void loadAssets() {
12191318
resourceService.loadSounds(forestSounds);
12201319
resourceService.loadMusic(forestMusic);
12211320

1222-
while (!resourceService.loadForMillis(10)) {
1223-
logger.info("Loading... {}%", resourceService.getProgress());
1224-
}
1321+
while (!resourceService.loadForMillis(10)) {
1322+
logger.info("Loading... {}%", resourceService.getProgress());
1323+
}
1324+
if (ServiceLocator.getAudioService() != null) {
1325+
ServiceLocator.getAudioService().registerSound("plasma_warning", PLASMA_WARNING_SOUND);
1326+
ServiceLocator.getAudioService().registerSound("plasma_impact", PLASMA_IMPACT_SOUND);
1327+
}
12251328
// try {
12261329
// com.badlogic.gdx.audio.Sound s =
12271330
// resourceService.getAsset("sounds/Explosion_sfx.ogg", com.badlogic.gdx.audio.Sound.class);

source/core/src/main/com/csse3200/game/areas/MapEditor.java

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -206,28 +206,28 @@ public void generateEnemyPath() {
206206
keyWaypoints.add(new GridPoint2(0, 10)); // Start
207207
keyWaypoints.add(new GridPoint2(5, 10)); // First turn
208208
keyWaypoints.add(new GridPoint2(5, 6)); // Up turn completed
209-
keyWaypoints.add(new GridPoint2(6, 6));
210-
keyWaypoints.add(new GridPoint2(7, 6));
211-
keyWaypoints.add(new GridPoint2(8, 6));
212-
keyWaypoints.add(new GridPoint2(9, 6));
213-
keyWaypoints.add(new GridPoint2(12, 6)); // Walk to the right completed
209+
keyWaypoints.add(new GridPoint2(10, 6));
210+
keyWaypoints.add(new GridPoint2(11, 6));
211+
keyWaypoints.add(new GridPoint2(12, 6));
212+
keyWaypoints.add(new GridPoint2(12, 7));
214213
keyWaypoints.add(new GridPoint2(12, 12)); // Down turn completed
215-
keyWaypoints.add(new GridPoint2(18, 12));
216-
keyWaypoints.add(new GridPoint2(19, 12));
217-
keyWaypoints.add(new GridPoint2(20, 12));
218214
keyWaypoints.add(new GridPoint2(21, 12));
215+
keyWaypoints.add(new GridPoint2(22, 12));
216+
keyWaypoints.add(new GridPoint2(23, 12));
217+
keyWaypoints.add(new GridPoint2(24, 12));
219218
keyWaypoints.add(new GridPoint2(25, 12)); // Long distance to the right completed
220219
keyWaypoints.add(new GridPoint2(25, 6)); // Up turn completed
221220
keyWaypoints.add(new GridPoint2(32, 6)); // End - extended past base to ensure enemies reach it
222-
Map<String, Float> speedModifiers = Map.of(
223-
"6,6", 0.5f,
224-
"7,6", 0.5f,
225-
"8,6", 0.5f,
226-
"9,6", 0.5f,
227-
"18,12", 0.5f,
228-
"19,12", 0.5f,
229-
"20,12", 0.5f,
230-
"21,12", 0.5f
221+
Map<String, Float> speedModifiers = Map.ofEntries(
222+
Map.entry("10,6", 0.5f),
223+
Map.entry("11,6", 0.5f),
224+
Map.entry("12,6", 0.5f),
225+
Map.entry("12,7", 0.5f),
226+
Map.entry("21,12", 0.5f),
227+
Map.entry("22,12", 0.5f),
228+
Map.entry("23,12", 0.5f),
229+
Map.entry("24,12", 0.5f),
230+
Map.entry("25,12", 0.5f)
231231
);
232232

233233
// Mark key path points标记关键路径点
@@ -274,21 +274,26 @@ public void generateEnemyPath() {
274274

275275
// water area
276276
int[][] waterArea = {
277-
{21,23,10,19},
278-
{24,26,16,19},
279-
{25,31,18,20},
280-
{27,31,21,22},
281-
{20,24,9,12},
277+
{21,26,13,19},
278+
{23,40,17,21},
279+
{28,31,21,23},
280+
{20,24,9,11},
282281
{18,22,6,9},
283282
{0,12,0,2},
284283
{13,21,0,1},
285-
{0,4,4,9},
286284
{22,24,0,2},
287285
{25,31,0,1},
288286
{30,32,2,5},
289287
{30,32,6,7},
290288
{17,22,0,4},
291-
{32,33,0,5}
289+
{32,33,0,5},
290+
{21,26,9,11},
291+
{24,26,13,16},
292+
{24,26,7,8},
293+
{21,23,6,8},
294+
{29,31,0,3},
295+
{29,31,18,22},
296+
{26,28,16,17}
292297
};
293298

294299
// Water tile
@@ -300,8 +305,6 @@ public void generateEnemyPath() {
300305
}
301306
}
302307

303-
304-
305308
// generatePlaceableAreas();
306309
System.out.println("✅ Fixed path generated, number=" + pathTiles.size());
307310
System.out.println("✅ Key path points number=" + keyWaypoints.size());

0 commit comments

Comments
 (0)