Skip to content

Commit c51a128

Browse files
committed
Add hero ultimate skill feature and Add button
1 parent 5108771 commit c51a128

File tree

6 files changed

+198
-1
lines changed

6 files changed

+198
-1
lines changed

source/core/src/main/com/csse3200/game/components/hero/HeroTurretAttackComponent.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,15 @@ public HeroTurretAttackComponent(float cooldown, float bulletSpeed, float bullet
4646
this.camera = camera;
4747
}
4848

49+
@Override
50+
public void create() {
51+
// 监听大招倍率变化(HeroUltimateComponent 触发 "attack.multiplier")
52+
entity.getEvents().addListener("attack.multiplier", (Float mul) -> {
53+
if (mul == null || mul <= 0f) mul = 1f;
54+
this.attackScale = mul; // 直接写倍率;computeDamageFromStats() 已使用它
55+
});
56+
}
57+
4958
@Override
5059
public void update() {
5160
if (entity == null) return;
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package com.csse3200.game.components.hero;
2+
3+
4+
import com.csse3200.game.components.Component;
5+
import com.csse3200.game.components.currencysystem.CurrencyComponent.CurrencyType;
6+
import com.csse3200.game.components.currencysystem.CurrencyManagerComponent;
7+
import com.badlogic.gdx.utils.TimeUtils;
8+
9+
/**
10+
* 英雄大招组件:
11+
* - 按按钮/事件触发
12+
* - 扣除玩家钱包里的货币
13+
* - 提升攻击伤害(倍率)
14+
* - 持续 5 秒后恢复
15+
*/
16+
public class HeroUltimateComponent extends Component{
17+
private static final int ULT_COST = 2; // 一次大招消耗多少货币
18+
private static final long ULT_DURATION_MS = 5000; // 持续 5 秒
19+
private static final float ULT_MULTIPLIER = 2.0f; // 伤害倍率
20+
21+
private boolean active = false;
22+
private long endAtMs = 0L;
23+
24+
// 指向已有的升级组件(里面缓存了 player + wallet)
25+
private HeroUpgradeComponent upgrade;
26+
27+
@Override
28+
public void create() {
29+
upgrade = entity.getComponent(HeroUpgradeComponent.class);
30+
31+
// UI 或键盘触发 "ultimate.request" 事件时调用
32+
entity.getEvents().addListener("ultimate.request", () -> onRequest());
33+
}
34+
35+
private void onRequest() {
36+
if (active) return;
37+
38+
if (upgrade == null) {
39+
// 没有升级组件,直接开大招(方便测试)
40+
activateNow();
41+
return;
42+
}
43+
44+
com.csse3200.game.components.currencysystem.CurrencyManagerComponent wallet =
45+
(upgrade != null) ? upgrade.getWallet() : null;
46+
47+
48+
if (wallet == null) {
49+
// 钱包还没准备好,提示失败
50+
entity.getEvents().trigger("ultimate.failed", "Wallet not ready");
51+
return;
52+
}
53+
54+
// 尝试扣费
55+
boolean ok = wallet.trySpendCurrency(CurrencyType.METAL_SCRAP, ULT_COST);
56+
if (!ok) {
57+
entity.getEvents().trigger("ultimate.failed", "Not enough " + CurrencyType.METAL_SCRAP);
58+
return;
59+
}
60+
61+
// 扣费成功 → 激活大招
62+
activateNow();
63+
}
64+
65+
private void activateNow() {
66+
active = true;
67+
endAtMs = TimeUtils.millis() + ULT_DURATION_MS;
68+
69+
// 通知攻击组件提升伤害
70+
entity.getEvents().trigger("attack.multiplier", ULT_MULTIPLIER);
71+
entity.getEvents().trigger("ultimate.state", true);
72+
}
73+
74+
@Override
75+
public void update() {
76+
if (!active) return;
77+
if (TimeUtils.millis() >= endAtMs) {
78+
active = false;
79+
// 恢复伤害
80+
entity.getEvents().trigger("attack.multiplier", 1.0f);
81+
entity.getEvents().trigger("ultimate.state", false);
82+
}
83+
}
84+
85+
@Override
86+
public void dispose() {
87+
if (active) {
88+
entity.getEvents().trigger("attack.multiplier", 1.0f);
89+
entity.getEvents().trigger("ultimate.state", false);
90+
active = false;
91+
}
92+
}
93+
}

source/core/src/main/com/csse3200/game/components/hero/HeroUpgradeComponent.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,15 @@ private Entity findPlayerEntity() {
114114
public int getLevel() {
115115
return level;
116116
}
117+
// 读余额组件(给大招等用)
118+
public com.csse3200.game.components.currencysystem.CurrencyManagerComponent getWallet() {
119+
return wallet;
120+
}
121+
122+
// (可选)需要的话保留这个
123+
public com.csse3200.game.entities.Entity getPlayer() {
124+
return player;
125+
}
117126
}
118127

119128

source/core/src/main/com/csse3200/game/entities/factories/HeroFactory.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import com.csse3200.game.services.ResourceService;
2121

2222
import java.util.LinkedHashSet;
23+
import com.csse3200.game.components.hero.HeroUltimateComponent;
24+
import com.csse3200.game.ui.UltimateButtonComponent;
2325

2426
/**
2527
* Factory class for creating hero entities.
@@ -131,7 +133,10 @@ public static Entity createHero(HeroConfig cfg, Camera camera) {
131133
camera // Inject camera for aiming & rotation
132134
))
133135
.addComponent(new HeroUpgradeComponent())
134-
.addComponent(new HeroAppearanceComponent(cfg));
136+
.addComponent(new HeroUltimateComponent())
137+
.addComponent(new HeroUltimateComponent())
138+
.addComponent(new UltimateButtonComponent())
139+
.addComponent(new HeroAppearanceComponent(cfg));
135140

136141
// Default scale to 1x1 so the hero is visible during testing
137142
hero.setScale(1f, 1f);
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package com.csse3200.game.ui;
2+
3+
import com.badlogic.gdx.Gdx;
4+
import com.badlogic.gdx.Input;
5+
import com.badlogic.gdx.scenes.scene2d.Stage;
6+
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
7+
import com.badlogic.gdx.scenes.scene2d.ui.Table;
8+
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
9+
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
10+
import com.badlogic.gdx.scenes.scene2d.InputEvent;
11+
import com.csse3200.game.components.Component;
12+
import com.csse3200.game.services.ServiceLocator;
13+
14+
/**
15+
* 临时测试用:在 HUD 右下角放一个“ULT”按钮。
16+
* 点击按钮或按下键盘 Q 时,会触发 "ultimate.request" 事件。
17+
* 大招期间按钮置灰;余额不足时在日志里提示。
18+
*/
19+
20+
public class UltimateButtonComponent extends Component{
21+
private Stage stage;
22+
private Skin skin;
23+
private Table root;
24+
private TextButton ultBtn;
25+
26+
@Override
27+
public void create() {
28+
stage = ServiceLocator.getRenderService().getStage();
29+
30+
// 用 SimpleUI 提供的按钮样式
31+
skin = new Skin();
32+
skin.add("default-font", SimpleUI.font(), com.badlogic.gdx.graphics.g2d.BitmapFont.class);
33+
skin.add("default", SimpleUI.buttonStyle(), TextButton.TextButtonStyle.class);
34+
35+
ultBtn = new TextButton("ULT (2)", skin); // 简单写死 50,后面可替换
36+
37+
// 点击触发大招
38+
ultBtn.addListener(new ClickListener() {
39+
@Override
40+
public void clicked(InputEvent event, float x, float y) {
41+
entity.getEvents().trigger("ultimate.request");
42+
}
43+
});
44+
45+
// 放在右下角
46+
root = new Table();
47+
root.setFillParent(true);
48+
root.bottom().right().pad(10);
49+
root.add(ultBtn).width(100).height(44);
50+
51+
stage.addActor(root);
52+
53+
// 大招期间禁用按钮
54+
entity.getEvents().addListener("ultimate.state", (Boolean on) -> {
55+
ultBtn.setDisabled(Boolean.TRUE.equals(on));
56+
});
57+
58+
// 余额不足提示
59+
entity.getEvents().addListener("ultimate.failed", (String reason) -> {
60+
Gdx.app.log("ULT", "Failed: " + reason);
61+
});
62+
63+
// 键盘 Q 触发(方便快速测试)
64+
stage.addListener(new com.badlogic.gdx.scenes.scene2d.InputListener() {
65+
@Override
66+
public boolean keyDown(InputEvent event, int keycode) {
67+
if (keycode == Input.Keys.Q) {
68+
entity.getEvents().trigger("ultimate.request");
69+
return true;
70+
}
71+
return false;
72+
}
73+
});
74+
}
75+
76+
@Override
77+
public void dispose() {
78+
if (root != null) root.remove();
79+
if (skin != null) skin.dispose();
80+
}
81+
}

source/gradlew

100644100755
File mode changed.

0 commit comments

Comments
 (0)