balance: 全面提升游戏难度——怪物HP/速度/KPI扣减上调,精力消耗加快,初始HC降至150,波次加量缩间隔,Boss技能冷却12s,自动下一波等待2s

This commit is contained in:
Cloud Bot
2026-03-24 08:56:14 +00:00
parent e460d90b3a
commit 4fec1ebe9d
11 changed files with 38 additions and 33 deletions

View File

@@ -470,7 +470,7 @@ function PuaPanel({ gameReady, hc, waveStarted }: { gameReady: boolean; hc: numb
// ── 主游戏页面 ──────────────────────────────────────────────────────────────── // ── 主游戏页面 ────────────────────────────────────────────────────────────────
export default function GamePage() { export default function GamePage() {
const gameRef = useRef<{ destroy: (removeCanvas: boolean) => void } | null>(null) const gameRef = useRef<{ destroy: (removeCanvas: boolean) => void } | null>(null)
const [hc, setHc] = useState(200) const [hc, setHc] = useState(150)
const [selectedTower, setSelectedTower] = useState<TowerType | null>(null) const [selectedTower, setSelectedTower] = useState<TowerType | null>(null)
const [gameReady, setGameReady] = useState(false) const [gameReady, setGameReady] = useState(false)
const [waveStarted, setWaveStarted] = useState(false) const [waveStarted, setWaveStarted] = useState(false)

View File

@@ -321,7 +321,7 @@ export function createGameScene(PhaserLib: typeof Phaser): typeof Phaser.Scene {
// 自动下一波倒计时ms-1 表示未激活 // 自动下一波倒计时ms-1 表示未激活
private autoNextWaveTimer: number = -1 private autoNextWaveTimer: number = -1
private readonly AUTO_WAVE_DELAY = 3000 // 3 秒后自动开始 private readonly AUTO_WAVE_DELAY = 2000 // 自动开始等待3s→2s缩短喘息时间
update(_time: number, delta: number): void { update(_time: number, delta: number): void {
if (this.manager.gameState !== 'playing' && this.manager.gameState !== 'idle') return if (this.manager.gameState !== 'playing' && this.manager.gameState !== 'idle') return

View File

@@ -12,7 +12,7 @@ export const HUD_HEIGHT = 60
export const WAVES_PER_MAP = 5 export const WAVES_PER_MAP = 5
// 游戏初始数值 // 游戏初始数值
export const INITIAL_HC = 200 export const INITIAL_HC = 150 // 降低初始HC200→150提高前期资源压力
export const INITIAL_KPI = 100 export const INITIAL_KPI = 100
export const STAMINA_MAX = 100 export const STAMINA_MAX = 100
export const STAMINA_REGEN = 5 // 每秒恢复量 export const STAMINA_REGEN = 5 // 每秒恢复量

View File

@@ -33,9 +33,9 @@ export const DIFFICULTY_MULTIPLIER: Record<DifficultyLevel, {
bossHp: number bossHp: number
hcReward: number hcReward: number
}> = { }> = {
easy: { enemyCount: 0.7, enemySpeed: 0.8, bossHp: 0.7, hcReward: 1.2 }, easy: { enemyCount: 0.7, enemySpeed: 0.85, bossHp: 0.7, hcReward: 1.1 },
normal: { enemyCount: 1.0, enemySpeed: 1.0, bossHp: 1.0, hcReward: 1.0 }, normal: { enemyCount: 1.0, enemySpeed: 1.0, bossHp: 1.0, hcReward: 1.0 },
hard: { enemyCount: 1.4, enemySpeed: 1.3, bossHp: 1.5, hcReward: 0.8 }, hard: { enemyCount: 1.5, enemySpeed: 1.35, bossHp: 1.8, hcReward: 0.75 },
} }
// 地图1人力资源部S型路径 // 地图1人力资源部S型路径
@@ -68,11 +68,11 @@ const MAP1: MapConfig = {
], ],
waveCount: 5, waveCount: 5,
waves: [ waves: [
{ enemies: [{ type: 'FreshGraduate', count: 10, interval: 800 }] }, { enemies: [{ type: 'FreshGraduate', count: 14, interval: 650 }] },
{ enemies: [{ type: 'FreshGraduate', count: 8, interval: 700 }, { type: 'OldEmployee', count: 2, interval: 2000 }] }, { enemies: [{ type: 'FreshGraduate', count: 10, interval: 600 }, { type: 'OldEmployee', count: 3, interval: 1800 }] },
{ enemies: [{ type: 'OldEmployee', count: 4, interval: 1800 }, { type: 'TroubleMaker', count: 3, interval: 1500 }] }, { enemies: [{ type: 'OldEmployee', count: 5, interval: 1500 }, { type: 'TroubleMaker', count: 4, interval: 1200 }] },
{ enemies: [{ type: 'FreshGraduate', count: 12, interval: 600 }, { type: 'TroubleMaker', count: 3, interval: 1200 }] }, { enemies: [{ type: 'FreshGraduate', count: 16, interval: 500 }, { type: 'TroubleMaker', count: 4, interval: 1000 }] },
{ enemies: [{ type: 'BossVP', count: 1, interval: 0 }, { type: 'OldEmployee', count: 3, interval: 2000 }, { type: 'FreshGraduate', count: 5, interval: 800 }] }, { enemies: [{ type: 'BossVP', count: 1, interval: 0 }, { type: 'OldEmployee', count: 4, interval: 1800 }, { type: 'FreshGraduate', count: 8, interval: 700 }] },
], ],
} }
@@ -111,11 +111,11 @@ const MAP2: MapConfig = {
], ],
waveCount: 5, waveCount: 5,
waves: [ waves: [
{ enemies: [{ type: 'FreshGraduate', count: 12, interval: 700 }, { type: 'OldEmployee', count: 2, interval: 2000 }] }, { enemies: [{ type: 'FreshGraduate', count: 15, interval: 600 }, { type: 'OldEmployee', count: 3, interval: 1800 }] },
{ enemies: [{ type: 'OldEmployee', count: 5, interval: 1500 }, { type: 'TroubleMaker', count: 3, interval: 1200 }] }, { enemies: [{ type: 'OldEmployee', count: 6, interval: 1300 }, { type: 'TroubleMaker', count: 4, interval: 1000 }] },
{ enemies: [{ type: 'FreshGraduate', count: 15, interval: 500 }, { type: 'TroubleMaker', count: 4, interval: 1000 }] }, { enemies: [{ type: 'FreshGraduate', count: 18, interval: 450 }, { type: 'TroubleMaker', count: 5, interval: 900 }] },
{ enemies: [{ type: 'BossVP', count: 1, interval: 0 }, { type: 'OldEmployee', count: 4, interval: 1500 }] }, { enemies: [{ type: 'BossVP', count: 1, interval: 0 }, { type: 'OldEmployee', count: 5, interval: 1300 }, { type: 'TroubleMaker', count: 3, interval: 1000 }] },
{ enemies: [{ type: 'BossVP', count: 1, interval: 0 }, { type: 'FreshGraduate', count: 10, interval: 600 }, { type: 'TroubleMaker', count: 5, interval: 1000 }] }, { enemies: [{ type: 'BossVP', count: 1, interval: 0 }, { type: 'FreshGraduate', count: 14, interval: 500 }, { type: 'TroubleMaker', count: 6, interval: 850 }] },
], ],
} }
@@ -154,11 +154,11 @@ const MAP3: MapConfig = {
], ],
waveCount: 5, waveCount: 5,
waves: [ waves: [
{ enemies: [{ type: 'OldEmployee', count: 6, interval: 1500 }, { type: 'TroubleMaker', count: 4, interval: 1000 }] }, { enemies: [{ type: 'OldEmployee', count: 7, interval: 1300 }, { type: 'TroubleMaker', count: 5, interval: 900 }] },
{ enemies: [{ type: 'BossVP', count: 1, interval: 0 }, { type: 'FreshGraduate', count: 12, interval: 600 }, { type: 'OldEmployee', count: 3, interval: 1500 }] }, { enemies: [{ type: 'BossVP', count: 1, interval: 0 }, { type: 'FreshGraduate', count: 16, interval: 500 }, { type: 'OldEmployee', count: 4, interval: 1300 }] },
{ enemies: [{ type: 'BossVP', count: 1, interval: 0 }, { type: 'TroubleMaker', count: 6, interval: 800 }, { type: 'OldEmployee', count: 4, interval: 1500 }] }, { enemies: [{ type: 'BossVP', count: 1, interval: 0 }, { type: 'TroubleMaker', count: 8, interval: 700 }, { type: 'OldEmployee', count: 5, interval: 1200 }] },
{ enemies: [{ type: 'BossVP', count: 2, interval: 5000 }, { type: 'OldEmployee', count: 5, interval: 1200 }, { type: 'FreshGraduate', count: 8, interval: 600 }] }, { enemies: [{ type: 'BossVP', count: 2, interval: 4000 }, { type: 'OldEmployee', count: 6, interval: 1100 }, { type: 'FreshGraduate', count: 12, interval: 500 }] },
{ enemies: [{ type: 'BossVP', count: 2, interval: 3000 }, { type: 'TroubleMaker', count: 8, interval: 600 }, { type: 'OldEmployee', count: 6, interval: 1000 }] }, { enemies: [{ type: 'BossVP', count: 2, interval: 2500 }, { type: 'TroubleMaker', count: 10, interval: 550 }, { type: 'OldEmployee', count: 7, interval: 900 }] },
], ],
} }

View File

@@ -4,7 +4,7 @@ import { getRandomQuote } from '../data/quotes'
import { AudioEngine } from '../AudioEngine' import { AudioEngine } from '../AudioEngine'
export class BossVP extends EnemyBase { export class BossVP extends EnemyBase {
private skillTimer: number = 20000 private skillTimer: number = 12000 // 技能间隔从20s压缩到12s
private onDestroyTower?: () => void private onDestroyTower?: () => void
private bossLabel!: Phaser.GameObjects.Text private bossLabel!: Phaser.GameObjects.Text
@@ -15,7 +15,8 @@ export class BossVP extends EnemyBase {
speedMultiplier: number = 1.0, speedMultiplier: number = 1.0,
hpMultiplier: number = 1.0 hpMultiplier: number = 1.0
) { ) {
super(scene, pathPoints, 800, 40, 30, 150, 'enemy-boss', speedMultiplier, hpMultiplier) // HP: 800→1200, speed: 40→55, kpiDamage: 30→40, hcReward: 150→100
super(scene, pathPoints, 1200, 55, 40, 100, 'enemy-boss', speedMultiplier, hpMultiplier)
this.onDestroyTower = onDestroyTower this.onDestroyTower = onDestroyTower
const bossSize = this.cellW * 1.3 const bossSize = this.cellW * 1.3
this.imageSprite.setDisplaySize(bossSize, bossSize) this.imageSprite.setDisplaySize(bossSize, bossSize)
@@ -47,7 +48,7 @@ export class BossVP extends EnemyBase {
super.update(delta) super.update(delta)
this.skillTimer -= delta this.skillTimer -= delta
if (this.skillTimer <= 0) { if (this.skillTimer <= 0) {
this.skillTimer = 20000 this.skillTimer = 12000 // 重置技能冷却
this.triggerOrgRestructure() this.triggerOrgRestructure()
} }
if (this.bossLabel) { if (this.bossLabel) {

View File

@@ -9,7 +9,8 @@ export class FreshGraduate extends EnemyBase {
speedMultiplier: number = 1.0, speedMultiplier: number = 1.0,
hpMultiplier: number = 1.0 hpMultiplier: number = 1.0
) { ) {
super(scene, pathPoints, 30, 120, 2, 10, 'enemy-fresh', speedMultiplier, hpMultiplier) // HP: 30→50, speed: 120→145, kpiDamage: 2→3, hcReward: 10→8
super(scene, pathPoints, 50, 145, 3, 8, 'enemy-fresh', speedMultiplier, hpMultiplier)
} }
getQuote(): string { return getRandomQuote('FreshGraduate') } getQuote(): string { return getRandomQuote('FreshGraduate') }
} }

View File

@@ -9,8 +9,9 @@ export class OldEmployee extends EnemyBase {
speedMultiplier: number = 1.0, speedMultiplier: number = 1.0,
hpMultiplier: number = 1.0 hpMultiplier: number = 1.0
) { ) {
super(scene, pathPoints, 150, 50, 8, 30, 'enemy-old', speedMultiplier, hpMultiplier) // HP: 150→240, speed: 50→65, kpiDamage: 8→12, hcReward: 30→22, shield: 3→4
this.shieldCount = 3 super(scene, pathPoints, 240, 65, 12, 22, 'enemy-old', speedMultiplier, hpMultiplier)
this.shieldCount = 4
this.imageSprite.setDisplaySize(this.cellW * 0.85, this.cellW * 0.85) this.imageSprite.setDisplaySize(this.cellW * 0.85, this.cellW * 0.85)
} }

View File

@@ -10,7 +10,8 @@ export class TroubleMaker extends EnemyBase {
speedMultiplier: number = 1.0, speedMultiplier: number = 1.0,
hpMultiplier: number = 1.0 hpMultiplier: number = 1.0
) { ) {
super(scene, pathPoints, 80, 80, 5, 20, 'enemy-trouble', speedMultiplier, hpMultiplier) // HP: 80→130, speed: 80→100, kpiDamage: 5→7, hcReward: 20→15
super(scene, pathPoints, 130, 100, 7, 15, 'enemy-trouble', speedMultiplier, hpMultiplier)
} }
protected override onDeath(): void { protected override onDeath(): void {

View File

@@ -5,6 +5,7 @@ import {
GAME_WIDTH, GAME_WIDTH,
GAME_HEIGHT, GAME_HEIGHT,
HUD_HEIGHT, HUD_HEIGHT,
INITIAL_HC,
INITIAL_KPI, INITIAL_KPI,
} from './constants' } from './constants'
import type { MapConfig } from './data/mapConfigs' import type { MapConfig } from './data/mapConfigs'
@@ -222,7 +223,7 @@ export function renderHUD(scene: Phaser.Scene): {
const hcText = scene.add.text( const hcText = scene.add.text(
GAME_WIDTH - 16, HUD_HEIGHT / 2, GAME_WIDTH - 16, HUD_HEIGHT / 2,
`HC: 200`, `HC: ${INITIAL_HC}`,
{ {
fontFamily: "'Press Start 2P', monospace", fontFamily: "'Press Start 2P', monospace",
fontSize: '10px', fontSize: '10px',

View File

@@ -98,7 +98,7 @@ export abstract class TowerBase {
const target = this.findTarget(enemies) const target = this.findTarget(enemies)
if (target && this.attackCooldown <= 0) { if (target && this.attackCooldown <= 0) {
this.attack(target) this.attack(target)
this.stamina -= 5 this.stamina -= 8 // 精力消耗5→8更快进入摸鱼状态
// 应用 PUA 攻速倍率(倍率越高冷却越短) // 应用 PUA 攻速倍率(倍率越高冷却越短)
this.attackCooldown = 1000 / (this.attackSpeed * this._puaSpeedMult) this.attackCooldown = 1000 / (this.attackSpeed * this._puaSpeedMult)
this.updateStaminaBar() this.updateStaminaBar()

View File

@@ -93,7 +93,7 @@ export class MapTransitionModal {
// KPI & 说明 // KPI & 说明
const statsEl = document.createElement('div') const statsEl = document.createElement('div')
statsEl.innerHTML = `最终KPI: <span style="color:#34d399">${kpi}%</span> &nbsp;|&nbsp; <span style="color:#94a3b8">HC 将重置为 200</span>` statsEl.innerHTML = `最终KPI: <span style="color:#34d399">${kpi}%</span> &nbsp;|&nbsp; <span style="color:#94a3b8">HC 将重置为 150</span>`
statsEl.style.cssText = ` statsEl.style.cssText = `
font-size: 20px; font-size: 20px;
color: #e2e8f0; color: #e2e8f0;
@@ -131,7 +131,7 @@ export class MapTransitionModal {
// 倒计时提示HC 重置提醒) // 倒计时提示HC 重置提醒)
const countdownEl = document.createElement('div') const countdownEl = document.createElement('div')
countdownEl.id = 'mt-countdown' countdownEl.id = 'mt-countdown'
countdownEl.textContent = isFinalMap ? '3秒后返回主菜单...' : '3秒后进入下一关HC重置为200...' countdownEl.textContent = isFinalMap ? '3秒后返回主菜单...' : '3秒后进入下一关HC重置为150...'
countdownEl.style.cssText = ` countdownEl.style.cssText = `
font-size: 16px; font-size: 16px;
color: #6b7280; color: #6b7280;
@@ -157,7 +157,7 @@ export class MapTransitionModal {
const el = document.getElementById('mt-countdown') const el = document.getElementById('mt-countdown')
if (el) el.textContent = isFinalMap if (el) el.textContent = isFinalMap
? `${remaining}秒后返回主菜单...` ? `${remaining}秒后返回主菜单...`
: `${remaining}秒后进入下一关HC重置为200...` : `${remaining}秒后进入下一关HC重置为150...`
} }
const interval = setInterval(tick, 1000) const interval = setInterval(tick, 1000)
this.autoCloseTimer = setTimeout(() => { this.autoCloseTimer = setTimeout(() => {