import { WEAPONS, WEAPON_CONFIG } from '../utils/constants.js' /** * HUD界面类 * 显示游戏中的血量、武器、弹药等信息 */ export class HUD { constructor(container) { this.container = container this.container.className = 'hud-container' this.container.innerHTML = '' this.visible = false this._build() } /** * 构建HUD界面元素 */ _build() { // 血量条 this.healthBar = document.createElement('div') this.healthBar.className = 'hud-health-bar' this.healthBar.innerHTML = '
100' this.container.appendChild(this.healthBar) // 武器面板 this.weaponPanel = document.createElement('div') this.weaponPanel.className = 'hud-weapon-panel' // 武器列表 const weaponList = [WEAPONS.PISTOL, WEAPONS.MACHINE_GUN, WEAPONS.SHOTGUN, WEAPONS.GRENADE] this.weaponSlots = [] for (let i = 0; i < weaponList.length; i++) { const slot = document.createElement('div') slot.className = 'hud-weapon-slot' slot.dataset.index = i // 按键提示(1-4) const keyLabel = document.createElement('span') keyLabel.className = 'hud-weapon-key' keyLabel.textContent = (i + 1).toString() // 武器名称 const weaponName = document.createElement('span') weaponName.className = 'hud-weapon-name' weaponName.textContent = WEAPON_CONFIG[weaponList[i]].name // 弹药数量 const ammoText = document.createElement('span') ammoText.className = 'hud-weapon-ammo' slot.appendChild(keyLabel) slot.appendChild(weaponName) slot.appendChild(ammoText) this.weaponSlots.push({ slot, ammoText }) this.weaponPanel.appendChild(slot) } this.container.appendChild(this.weaponPanel) // 手雷蓄力条(默认隐藏) this.grenadeChargeBar = document.createElement('div') this.grenadeChargeBar.className = 'hud-grenade-charge' this.grenadeChargeBar.innerHTML = '
' this.grenadeChargeBar.style.display = 'none' this.container.appendChild(this.grenadeChargeBar) // 信息面板(波次、分数、时间) this.infoPanel = document.createElement('div') this.infoPanel.className = 'hud-info-panel' this.waveText = document.createElement('span') this.waveText.className = 'hud-info-item' this.waveText.textContent = 'Wave: 0' this.scoreText = document.createElement('span') this.scoreText.className = 'hud-info-item' this.scoreText.textContent = 'Score: 0' this.timeText = document.createElement('span') this.timeText.className = 'hud-info-item' this.timeText.textContent = 'Time: 0:00' this.infoPanel.appendChild(this.waveText) this.infoPanel.appendChild(this.scoreText) this.infoPanel.appendChild(this.timeText) this.container.appendChild(this.infoPanel) // 准星 this.crosshair = document.createElement('div') this.crosshair.className = 'hud-crosshair' this.container.appendChild(this.crosshair) // 击杀信息(最近5条) this.killFeed = document.createElement('div') this.killFeed.className = 'hud-kill-feed' this.container.appendChild(this.killFeed) } /** * 显示HUD */ show() { this.visible = true this.container.style.display = 'flex' } /** * 隐藏HUD */ hide() { this.visible = false this.container.style.display = 'none' } /** * 更新血量显示 * @param {number} health 血量值 0-100 */ updateHealth(health) { const fill = this.healthBar.querySelector('.hud-health-fill') const text = this.healthBar.querySelector('.hud-health-text') const pct = Math.max(0, Math.min(100, health)) fill.style.width = pct + '%' // 颜色根据血量变化:绿色>60,橙色>30,红色<=30 if (pct > 60) fill.style.backgroundColor = '#44ff44' else if (pct > 30) fill.style.backgroundColor = '#ffaa00' else fill.style.backgroundColor = '#ff4444' text.textContent = Math.ceil(pct) } /** * 更新武器显示 * @param {number} currentIndex 当前武器索引 * @param {Object} ammo 各武器弹药数 */ updateWeapons(currentIndex, ammo) { const weaponList = [WEAPONS.PISTOL, WEAPONS.MACHINE_GUN, WEAPONS.SHOTGUN, WEAPONS.GRENADE] for (let i = 0; i < this.weaponSlots.length; i++) { const slot = this.weaponSlots[i] // 高亮当前武器 slot.slot.classList.toggle('hud-weapon-active', i === currentIndex) const weaponKey = weaponList[i] const currentAmmo = ammo[weaponKey] if (currentAmmo === Infinity) { slot.ammoText.textContent = '∞' } else { slot.ammoText.textContent = currentAmmo + '/' + WEAPON_CONFIG[weaponKey].maxAmmo } } } /** * 更新手雷蓄力显示 * @param {number} percent 蓄力百分比 0-1 */ updateGrenadeCharge(percent) { if (percent > 0) { this.grenadeChargeBar.style.display = 'block' const fill = this.grenadeChargeBar.querySelector('.hud-grenade-charge-fill') fill.style.width = (percent * 100) + '%' } else { this.grenadeChargeBar.style.display = 'none' } } /** * 更新游戏信息 * @param {number} wave 当前波次 * @param {number} score 分数 * @param {number} time 游戏时间(秒) */ updateInfo(wave, score, time) { this.waveText.textContent = 'Wave: ' + wave this.scoreText.textContent = 'Score: ' + score const mins = Math.floor(time / 60) const secs = Math.floor(time % 60) this.timeText.textContent = `Time: ${mins}:${secs.toString().padStart(2, '0')}` } /** * 添加击杀信息条目 * @param {string} message 击杀信息文本 */ addKillFeed(message) { const entry = document.createElement('div') entry.className = 'hud-kill-entry' entry.textContent = message this.killFeed.appendChild(entry) // 4秒后自动移除 setTimeout(() => { if (entry.parentNode) entry.parentNode.removeChild(entry) }, 4000) // 最多保留5条 while (this.killFeed.children.length > 5) { this.killFeed.removeChild(this.killFeed.firstChild) } } }