把耐力、異常狀態與道具補給串起來之後,繼續要讓這個循環更完整,也就是敵人被打倒會留下道具。所以玩家不只是在清怪,可能需要評估什麼時候砍下最後一刀、如何走位撿補給、以及要不要冒著中毒的風險換一瓶解毒藥水。
預計達成的目標:
掉落邏輯寫在 new_demo/src/systems/enemy.rs
裡現有的 despawn_dead_enemies_system
,只要偵測到 Health
歸零且還沒進入淡出,就會立刻產生道具:
for (entity, transform, health, death_effect, mut sprite) in &mut query {
if health.current > 0 || death_effect.is_some() {
continue;
}
sprite.color.set_alpha(1.0);
let drop_effect = random_pickup_effect(&mut rng);
spawn_pickup_entity(
&mut commands,
asset_server.as_ref(),
drop_effect,
transform.translation,
);
commands.entity(entity).insert(EnemyDeathEffect {
timer: Timer::from_seconds(ENEMY_DEATH_FADE_SECONDS, TimerMode::Once),
});
info!("敵人被擊倒,掉落{}並開始淡出", drop_label);
}
關鍵點:
Transform
:掉落物會精準出現在屍體所在格子,不會出現在其他地方。EnemyDeathEffect
還是會加上去,所以原本的淡出與 despawn()
流程完全不動。EnemyPlugin
讓這支系統永遠在 player_melee_attack_system
之後、enemy_death_effect_system
之前執行:
app.add_systems(
Update,
(
...,
despawn_dead_enemies_system.after(player_melee_attack_system),
enemy_death_effect_system.after(despawn_dead_enemies_system),
),
);
因此流程會是:先扣血 → 下一禎產生掉落 → 再淡出敵人。玩家只要走過去,player_pickup_detection_system
就會立即觸發效果。
items.rs
新增的輔助函式為了避免「地圖補給」和「敵人掉落」兩邊各寫一次程式,所以會把把邏輯拆成三個工具:
fn pickup_effect_options() -> [PickupEffect; 3];
pub fn random_pickup_effect<R: rand::Rng + ?Sized>(rng: &mut R) -> PickupEffect;
pub fn spawn_pickup_entity(
commands: &mut Commands,
asset_server: &AssetServer,
effect: PickupEffect,
base_position: Vec3,
);
pickup_effect_options()
有紅、綠、灰三種藥水,哪裡要改掉落池只要動這裡。random_pickup_effect()
接受任何 Rng
,未來要依敵人種類換權重也很方便。spawn_pickup_entity()
統一 Sprite 載入、縮放與 Z 軸偏移,確保地圖上的補給一致。spawn_random_pickups
也改成呼叫這些函式,地圖初始化時丟出的道具和敵人掉落完全一樣,不會出現大小不同或命名不一致的狀況。
src/components/items.rs
的結構延續上一篇講到的:
#[derive(Component, Debug, Clone)]
pub struct Pickup {
pub effect: PickupEffect,
}
#[derive(Debug, Clone)]
pub enum PickupEffect {
Heal(i32),
RestoreStamina(f32),
CurePoison,
}
拿取時 player_pickup_detection_system
直接 match 效果:
Heal
:補血但不會超過上限。RestoreStamina
:補耐力,搭配 log 顯示前後數值。CurePoison
:移除 Poisoned
Component,解除持續扣血。戰鬥節奏跟之前相比,最大的改變是擊殺 = 資源回收。實測幾個情境:
Poisoned
的時候,只要再砍一刀把敵人收掉,就有機會掉出灰色解毒藥水,絕境翻盤的機率變高。log 與 UI 互相呼應:
整體體感變成「擊殺 → 撿補給 → 再出手」的節奏,玩家不再只是在清空房間,而是透過戰鬥取得續戰資源。
實際打怪完顯示道具的流程
EnemyDeathEffect
已經加在身上,就不會再跑一次掉落邏輯。spawn_pickup_entity
多掛一個計時器即可。現在有一些獎勵的機制,來鼓勵玩家攻擊對手,但還是有些地方可以再做調整,例如:
assets/items/elixirs/
,預計之後會加入暫時提高上限的效果,會需要額外的計時 UI。今日程式碼同步至 repo