Spaces:
Paused
Paused
| // 敌方信息原始文本 | |
| const enemyInfoText = ` | |
| 发起战斗,敌方信息如下 | |
| name: 杂鱼 | |
| maxHealth: 低 | |
| basicDamage: 低 | |
| `; | |
| // 游戏主背景和弹窗背景图片链接 | |
| const GAME_BG_URL = 'https://files.catbox.moe/4qg2k3.png'; | |
| const MODAL_BG_URL = 'https://img.freepik.com/free-photo/brown-concrete-wall-with-scratches_45130-1491.jpg?size=626&ext=jpg'; | |
| // 玩家信息 | |
| const PLAYER_INFO = { | |
| name: 'user', | |
| maxHealth: 50, | |
| currentHealth: 50, | |
| energy: 0, | |
| maxEnergy: 10, | |
| selectedAction: null, | |
| basicDamage: 20 // 轻攻击基础伤害 | |
| }; | |
| // 生命值和伤害等级映射 | |
| const healthMap = { '低': 50, '中': 80, '高': 100 }; | |
| const damageMap = { '低': 20, '中': 30, '高': 40 }; | |
| const styles = ['风', '火', '林', '山']; | |
| // 常见NPC信息 | |
| const commonNPCs = { | |
| '姬姒': { | |
| name: '姬姒', | |
| maxHealth: 100, | |
| basicDamage: 30, | |
| style: '风', | |
| portrait: 'https://files.catbox.moe/3sfu4i.png' | |
| }, | |
| '北条': { | |
| name: '北条', | |
| maxHealth: 80, | |
| basicDamage: 50, | |
| style: '火', | |
| portrait: 'https://files.catbox.moe/07djrh.png' | |
| }, | |
| '神宫寺': { | |
| name: '神宫寺', | |
| maxHealth: 120, | |
| basicDamage: 20, | |
| style: '山', | |
| portrait: 'https://files.catbox.moe/3sfu4i.png' | |
| }, | |
| // 可继续添加更多NPC | |
| }; | |
| // 解析敌方信息的函数 | |
| function parseEnemyInfo(text) { | |
| // 提取 | |
| const nameMatch = text.match(/name:\s*([^\n]+)/); | |
| const npcName = nameMatch ? nameMatch[1].trim() : ''; | |
| clearEnemyPortrait(); | |
| // 优先查找常见NPC | |
| if (npcName && commonNPCs[npcName]) { | |
| const npc = commonNPCs[npcName]; | |
| // 更新敌人立绘 | |
| updateEnemyPortrait(npc.portrait); | |
| return { | |
| name: npc.name, | |
| maxHealth: npc.maxHealth, | |
| currentHealth: npc.maxHealth, | |
| energy: 0, | |
| maxEnergy: 10, | |
| selectedAction: null, | |
| basicDamage: npc.basicDamage, | |
| style: npc.style | |
| }; | |
| } | |
| // 没有匹配到常见NPC,走原有解析逻辑,风格随机 | |
| const maxHealthMatch = text.match(/maxHealth:\s*([^\n]+)/); | |
| const basicDamageMatch = text.match(/basicDamage:\s*([^\n]+)/); | |
| // 清除敌人立绘 | |
| clearEnemyPortrait(); | |
| return { | |
| name: npcName, | |
| maxHealth: maxHealthMatch ? healthMap[maxHealthMatch[1].trim()] || 80 : 80, | |
| currentHealth: maxHealthMatch ? healthMap[maxHealthMatch[1].trim()] || 80 : 80, | |
| energy: 0, | |
| maxEnergy: 10, | |
| selectedAction: null, | |
| basicDamage: basicDamageMatch ? damageMap[basicDamageMatch[1].trim()] || 30 : 30, | |
| style: styles[Math.floor(Math.random() * styles.length)] | |
| }; | |
| } | |
| // 更新敌人立绘 | |
| function updateEnemyPortrait(portraitUrl) { | |
| const npcPortraitLayer = document.querySelector('.npc-portrait-layer'); | |
| npcPortraitLayer.style.backgroundImage = `url('${portraitUrl}')`; | |
| } | |
| // 清除敌人立绘 | |
| function clearEnemyPortrait() { | |
| const npcPortraitLayer = document.querySelector('.npc-portrait-layer'); | |
| npcPortraitLayer.style.backgroundImage = ''; | |
| } | |
| // 游戏状态对象 | |
| const gameState = { | |
| currentTurn: 'player', // 'player' or 'enemy' | |
| waitingForConfirmation: false, | |
| player: { ...PLAYER_INFO }, | |
| enemy: parseEnemyInfo(enemyInfoText) | |
| }; | |
| // 获取DOM元素 | |
| const playerHealthBar = document.getElementById('player-health'); | |
| const enemyHealthBar = document.getElementById('enemy-health'); | |
| const playerHealthValue = document.getElementById('player-health-value'); | |
| const enemyHealthValue = document.getElementById('enemy-health-value'); | |
| const playerMaxHealth = document.getElementById('player-max-health'); // 新增 | |
| const enemyMaxHealth = document.getElementById('enemy-max-health'); // 新增 | |
| const playerEnergyDisplay = document.getElementById('player-energy'); | |
| const enemyEnergyDisplay = document.getElementById('enemy-energy'); | |
| const battleLog = document.getElementById('battle-log'); | |
| const turnText = document.getElementById('turn-text'); | |
| const selectedActionText = document.getElementById('selected-action'); | |
| const confirmActionButton = document.getElementById('confirm-action'); | |
| const cancelActionButton = document.getElementById('cancel-action'); | |
| const commandButtons = document.querySelectorAll('.command-btn'); | |
| const confirmModal = document.getElementById('confirm-modal'); | |
| // 角色元素 | |
| const playerCharacter = document.querySelector('.player-character'); | |
| const enemyCharacter = document.querySelector('.enemy-character'); | |
| // 初始化游戏 | |
| function initGame() { | |
| updateDisplay(); | |
| addLog('战斗开始,请选择行动...'); | |
| // 添加按钮点击事件 - 支持触屏和鼠标 | |
| setupButtonEvents(); | |
| // 键盘控制 | |
| document.addEventListener('keydown', handleKeyPress); | |
| } | |
| // 设置按钮事件 | |
| function setupButtonEvents() { | |
| document.getElementById('gather').addEventListener('click', () => selectAction('gather')); | |
| document.getElementById('defend').addEventListener('click', () => selectAction('defend')); | |
| document.getElementById('light-attack').addEventListener('click', () => selectAction('light-attack')); | |
| document.getElementById('heavy-attack').addEventListener('click', () => selectAction('heavy-attack')); | |
| document.getElementById('special').addEventListener('click', () => selectAction('special')); | |
| document.getElementById('taunt').addEventListener('click', () => selectAction('taunt')); | |
| // 确认按钮事件 | |
| confirmActionButton.addEventListener('click', () => { | |
| confirmModal.style.display = 'none'; | |
| confirmAction(); | |
| }); | |
| // 取消按钮事件 | |
| cancelActionButton.addEventListener('click', () => { | |
| confirmModal.style.display = 'none'; | |
| gameState.player.selectedAction = null; | |
| updateDisplay(); | |
| }); | |
| } | |
| // 更新显示 | |
| function updateDisplay() { | |
| // 更新生命值显示 | |
| playerHealthBar.style.width = `${(gameState.player.currentHealth / gameState.player.maxHealth) * 100}%`; | |
| enemyHealthBar.style.width = `${(gameState.enemy.currentHealth / gameState.enemy.maxHealth) * 100}%`; | |
| // 更新生命值文本 | |
| playerHealthValue.textContent = gameState.player.currentHealth; | |
| enemyHealthValue.textContent = gameState.enemy.currentHealth; | |
| // 更新最大生命值文本 | |
| playerMaxHealth.textContent = gameState.player.maxHealth; | |
| enemyMaxHealth.textContent = gameState.enemy.maxHealth; | |
| // 更新能量值 | |
| playerEnergyDisplay.textContent = gameState.player.energy; | |
| enemyEnergyDisplay.textContent = gameState.enemy.energy; | |
| // 更新回合指示 | |
| turnText.textContent = gameState.currentTurn === 'player' ? '我方行动' : '敌方行动'; | |
| // 根据能量值启用/禁用按钮 | |
| checkButtonAvailability(); | |
| } | |
| // 检查按钮可用性 | |
| function checkButtonAvailability() { | |
| // 如果不是玩家回合或正在等待确认,禁用所有按钮 | |
| if (gameState.currentTurn !== 'player' || gameState.waitingForConfirmation) { | |
| commandButtons.forEach(btn => { | |
| btn.classList.add('disabled'); | |
| }); | |
| return; | |
| } | |
| // 重置按钮状态 | |
| commandButtons.forEach(btn => { | |
| btn.classList.remove('disabled'); | |
| btn.classList.remove('selected'); | |
| }); | |
| // 根据能量值启用/禁用按钮 | |
| if (gameState.player.energy < 1) { | |
| document.getElementById('light-attack').classList.add('disabled'); | |
| } | |
| if (gameState.player.energy < 2) { | |
| document.getElementById('heavy-attack').classList.add('disabled'); | |
| } | |
| if (gameState.player.energy < 5) { | |
| document.getElementById('special').classList.add('disabled'); | |
| } | |
| // 如果有选中的动作,高亮显示 | |
| if (gameState.player.selectedAction) { | |
| document.getElementById(gameState.player.selectedAction).classList.add('selected'); | |
| } | |
| } | |
| // 添加战斗日志 | |
| function addLog(message) { | |
| const logEntry = document.createElement('p'); | |
| logEntry.textContent = message; | |
| battleLog.appendChild(logEntry); | |
| battleLog.scrollTop = battleLog.scrollHeight; | |
| } | |
| // 选择动作 | |
| function selectAction(action) { | |
| // 如果不是玩家回合或正在等待确认,返回 | |
| if (gameState.currentTurn !== 'player' || gameState.waitingForConfirmation) return; | |
| // 检查按钮是否被禁用 | |
| if (document.getElementById(action).classList.contains('disabled')) { | |
| return; | |
| } | |
| // 清除之前的选择 | |
| commandButtons.forEach(btn => btn.classList.remove('selected')); | |
| // 检查是否有足够的能量 | |
| if ((action === 'light-attack' && gameState.player.energy < 1) || | |
| (action === 'heavy-attack' && gameState.player.energy < 2) || | |
| (action === 'special' && gameState.player.energy < 5)) { | |
| addLog('能量不足,无法执行此动作!'); | |
| return; | |
| } | |
| // 设置选中状态 | |
| document.getElementById(action).classList.add('selected'); | |
| gameState.player.selectedAction = action; | |
| // 更新选择显示 | |
| const actionNames = { | |
| 'gather': '集气', | |
| 'defend': '防御', | |
| 'light-attack': '轻攻击', | |
| 'heavy-attack': '重攻击', | |
| 'special': '绝招', | |
| 'taunt': '嘴炮' | |
| }; | |
| selectedActionText.textContent = actionNames[action]; | |
| // 显示确认弹窗 | |
| confirmModal.style.display = 'flex'; | |
| } | |
| // 确认动作 | |
| function confirmAction() { | |
| if (!gameState.player.selectedAction) return; | |
| // 设置为等待确认状态 | |
| gameState.waitingForConfirmation = true; | |
| // 禁用按钮 | |
| commandButtons.forEach(btn => { | |
| btn.classList.add('disabled'); | |
| }); | |
| addLog(`${gameState.player.name}准备行动...`); | |
| // 敌人AI选择动作 | |
| selectEnemyAction(); | |
| // 执行回合结算 | |
| setTimeout(executeTurn, 1000); | |
| } | |
| // 敌人AI选择动作 | |
| function selectEnemyAction() { | |
| const enemy = gameState.enemy; | |
| const player = gameState.player; | |
| const style = enemy.style || '风'; // 默认风格 | |
| // 玩家气的威胁等级 | |
| const playerEnergy = player.energy; | |
| // 嘴炮判定:玩家气满5时,敌人有较高概率嘴炮 | |
| if (playerEnergy >= 5) { | |
| if (style === '山' && Math.random() < 0.5) { | |
| enemy.selectedAction = 'taunt'; | |
| return; | |
| } | |
| if (style === '林' && Math.random() < 0.4) { | |
| enemy.selectedAction = 'taunt'; | |
| return; | |
| } | |
| if (style === '火' && Math.random() < 0.25) { | |
| enemy.selectedAction = 'taunt'; | |
| return; | |
| } | |
| if (style === '风' && Math.random() < 0.2) { | |
| enemy.selectedAction = 'taunt'; | |
| return; | |
| } | |
| } | |
| // 防御判定:玩家气较高时,敌人有概率防御 | |
| if (playerEnergy >= 1) { | |
| if (style === '山' && Math.random() < 0.5) { | |
| enemy.selectedAction = 'defend'; | |
| return; | |
| } | |
| if (style === '林' && Math.random() < 0.3) { | |
| enemy.selectedAction = 'defend'; | |
| return; | |
| } | |
| if (style === '火' && Math.random() < 0.2) { | |
| enemy.selectedAction = 'defend'; | |
| return; | |
| } | |
| if (style === '风' && Math.random() < 0.15) { | |
| enemy.selectedAction = 'defend'; | |
| return; | |
| } | |
| } | |
| // 风格主策略 | |
| if (style === '风') { | |
| // 风:更倾向于轻攻击 | |
| if (enemy.energy >= 1 && Math.random() < 0.7) { | |
| enemy.selectedAction = 'light-attack'; | |
| return; | |
| } | |
| if (enemy.energy < 10 && Math.random() < 0.6) { | |
| enemy.selectedAction = 'gather'; | |
| return; | |
| } | |
| if (enemy.energy >= 2 && Math.random() < 0.3) { | |
| enemy.selectedAction = 'heavy-attack'; | |
| return; | |
| } | |
| if (enemy.energy >= 5 && Math.random() < 0.2) { | |
| enemy.selectedAction = 'special'; | |
| return; | |
| } | |
| enemy.selectedAction = 'gather'; | |
| return; | |
| } | |
| if (style === '火') { | |
| // 火:更倾向于重攻击 | |
| if (enemy.energy >= 2 && Math.random() < 0.7) { | |
| enemy.selectedAction = 'heavy-attack'; | |
| return; | |
| } | |
| if (enemy.energy >= 1 && Math.random() < 0.4) { | |
| enemy.selectedAction = 'light-attack'; | |
| return; | |
| } | |
| if (enemy.energy < 10 && Math.random() < 0.5) { | |
| enemy.selectedAction = 'gather'; | |
| return; | |
| } | |
| if (enemy.energy >= 5 && Math.random() < 0.2) { | |
| enemy.selectedAction = 'special'; | |
| return; | |
| } | |
| enemy.selectedAction = 'gather'; | |
| return; | |
| } | |
| if (style === '林') { | |
| // 林:更倾向于攒气用绝招 | |
| if (enemy.energy >= 5 && Math.random() < 0.7) { | |
| enemy.selectedAction = 'special'; | |
| return; | |
| } | |
| if (enemy.energy < 10 && Math.random() < 0.7) { | |
| enemy.selectedAction = 'gather'; | |
| return; | |
| } | |
| if (enemy.energy >= 2 && Math.random() < 0.2) { | |
| enemy.selectedAction = 'heavy-attack'; | |
| return; | |
| } | |
| if (enemy.energy >= 1 && Math.random() < 0.2) { | |
| enemy.selectedAction = 'light-attack'; | |
| return; | |
| } | |
| enemy.selectedAction = 'gather'; | |
| return; | |
| } | |
| if (style === '山') { | |
| // 山:注重防守 | |
| if (enemy.currentHealth < enemy.maxHealth * 0.5 && playerEnergy >= 1 && Math.random() < 0.5) { | |
| enemy.selectedAction = 'defend'; | |
| return; | |
| } | |
| if (enemy.energy < 10 && Math.random() < 0.6) { | |
| enemy.selectedAction = 'gather'; | |
| return; | |
| } | |
| if (enemy.energy >= 1 && Math.random() < 0.4) { | |
| enemy.selectedAction = 'light-attack'; | |
| return; | |
| } | |
| if (enemy.energy >= 2 && Math.random() < 0.3) { | |
| enemy.selectedAction = 'heavy-attack'; | |
| return; | |
| } | |
| if (enemy.energy >= 5 && Math.random() < 0.1) { | |
| enemy.selectedAction = 'special'; | |
| return; | |
| } | |
| enemy.selectedAction = 'gather'; | |
| return; | |
| } | |
| // 默认行为 | |
| enemy.selectedAction = 'gather'; | |
| } | |
| // 执行回合 | |
| function executeTurn() { | |
| const player = gameState.player; | |
| const enemy = gameState.enemy; | |
| // 获取双方行动 | |
| const playerAction = player.selectedAction; | |
| const enemyAction = enemy.selectedAction; | |
| addLog(`${enemy.name}选择了行动...`); | |
| // 根据行动类型执行特效和结算 | |
| setTimeout(() => { | |
| // 显示双方选择的动作 | |
| const actionNames = { | |
| 'gather': '集气', | |
| 'defend': '防御', | |
| 'light-attack': '轻攻击', | |
| 'heavy-attack': '重攻击', | |
| 'special': '绝招', | |
| 'taunt': '嘴炮' | |
| }; | |
| addLog(`${player.name}使用了${actionNames[playerAction]}!${enemy.name}使用了${actionNames[enemyAction]}!`); | |
| // 处理行动结果 | |
| processActions(playerAction, enemyAction); | |
| // 检查游戏是否结束 | |
| if (checkGameOver()) { | |
| return; | |
| } | |
| // 继续下一回合 | |
| continueGame(); | |
| }, 1000); | |
| } | |
| // 处理双方行动的结果 | |
| function processActions(playerAction, enemyAction) { | |
| const player = gameState.player; | |
| const enemy = gameState.enemy; | |
| const gameContainer = document.querySelector('.game-container'); | |
| const npcPortraitLayer = document.querySelector('.npc-portrait-layer'); | |
| const screenFlash = document.querySelector('.screen-flash'); | |
| let playerWasHit = false; | |
| let enemyWasHit = false; | |
| // 处理集气 | |
| if (playerAction === 'gather') { | |
| if (player.energy < player.maxEnergy) { | |
| player.energy += 1; | |
| addLog(`${player.name}集气成功,能量+1!`); | |
| } else { | |
| addLog(`${player.name}的能量已满!`); | |
| } | |
| } | |
| if (enemyAction === 'gather') { | |
| if (enemy.energy < enemy.maxEnergy) { | |
| enemy.energy += 1; | |
| addLog(`${enemy.name}集气成功,能量+1!`); | |
| } else { | |
| addLog(`${enemy.name}的能量已满!`); | |
| } | |
| } | |
| // 处理防御状态 | |
| const playerDefending = playerAction === 'defend'; | |
| const enemyDefending = enemyAction === 'defend'; | |
| if (playerDefending) { | |
| playerCharacter.classList.add('player-defend'); | |
| setTimeout(() => { | |
| playerCharacter.classList.remove('player-defend'); | |
| }, 1000); | |
| addLog(`${player.name}进入防御状态!`); | |
| } | |
| if (enemyDefending) { | |
| enemyCharacter.classList.add('enemy-defend'); | |
| setTimeout(() => { | |
| enemyCharacter.classList.remove('enemy-defend'); | |
| }, 1000); | |
| addLog(`${enemy.name}进入防御状态!`); | |
| } | |
| // 嘴炮只能无效化绝招的伤害 | |
| let playerTauntSuccess = false; | |
| let enemyTauntSuccess = false; | |
| if (playerAction === 'taunt' && enemyAction === 'special') { | |
| playerTauntSuccess = true; | |
| addLog(`${player.name}的嘴炮成功无效化了${enemy.name}的绝招伤害!`); | |
| // 注意:不在这里扣除敌人的能量,而是统一在特殊技能处理部分扣除 | |
| } | |
| if (enemyAction === 'taunt' && playerAction === 'special') { | |
| enemyTauntSuccess = true; | |
| addLog(`${enemy.name}的嘴炮成功无效化了${player.name}的绝招伤害!`); | |
| // 注意:不在这里扣除玩家的能量,而是统一在特殊技能处理部分扣除 | |
| } | |
| // 处理绝招(无视防御) | |
| if (playerAction === 'special') { | |
| // 无论绝招是否被嘴炮无效化,都消耗能量 | |
| player.energy -= 5; | |
| playerCharacter.classList.add('player-special'); | |
| if (!enemyTauntSuccess) { | |
| enemyCharacter.classList.add('enemy-hit'); | |
| setTimeout(() => { | |
| enemyCharacter.classList.remove('enemy-hit'); | |
| }, 1000); | |
| const damage = player.basicDamage * 3; | |
| enemy.currentHealth -= damage; | |
| addLog(`${player.name}使用绝招,对${enemy.name}造成${damage}点伤害!`); | |
| enemyWasHit = true; | |
| } else { | |
| addLog(`${player.name}使用绝招,但伤害被${enemy.name}的嘴炮无效化了!`); | |
| } | |
| setTimeout(() => { | |
| playerCharacter.classList.remove('player-special'); | |
| }, 1000); | |
| // 无效化敌人的普通攻击 | |
| if (enemyAction === 'light-attack' || enemyAction === 'heavy-attack') { | |
| addLog(`${enemy.name}的攻击被${player.name}的绝招无效化了!`); | |
| // 敌人消耗的能量不返还 | |
| if (enemyAction === 'light-attack') enemy.energy -= 1; | |
| if (enemyAction === 'heavy-attack') enemy.energy -= 2; | |
| } | |
| } | |
| if (enemyAction === 'special') { | |
| // 无论绝招是否被嘴炮无效化,都消耗能量 | |
| enemy.energy -= 5; | |
| enemyCharacter.classList.add('enemy-special'); | |
| if (!playerTauntSuccess) { | |
| playerCharacter.classList.add('player-hit'); | |
| setTimeout(() => { | |
| playerCharacter.classList.remove('player-hit'); | |
| }, 1000); | |
| const damage = enemy.basicDamage * 3; | |
| player.currentHealth -= damage; | |
| addLog(`${enemy.name}使用绝招,对${player.name}造成${damage}点伤害!`); | |
| playerWasHit = true; | |
| } else { | |
| addLog(`${enemy.name}使用绝招,但伤害被${player.name}的嘴炮无效化了!`); | |
| } | |
| setTimeout(() => { | |
| enemyCharacter.classList.remove('enemy-special'); | |
| }, 1000); | |
| // 无效化玩家的普通攻击 | |
| if (playerAction === 'light-attack' || playerAction === 'heavy-attack') { | |
| addLog(`${player.name}的攻击被${enemy.name}的绝招无效化了!`); | |
| // 玩家消耗的能量不返还 | |
| if (playerAction === 'light-attack') player.energy -= 1; | |
| if (playerAction === 'heavy-attack') player.energy -= 2; | |
| } | |
| } | |
| // 如果没有被绝招无效,处理重攻击 | |
| if (playerAction === 'heavy-attack' && | |
| enemyAction !== 'special' && | |
| playerAction !== 'special') { | |
| player.energy -= 2; | |
| // 检查是否被防御或是否无效对方轻攻击 | |
| if (enemyDefending) { | |
| playerCharacter.classList.add('player-attack'); | |
| setTimeout(() => { | |
| playerCharacter.classList.remove('player-attack'); | |
| }, 600); | |
| addLog(`${player.name}的重攻击被${enemy.name}防御了!`); | |
| } else if (enemyAction === 'light-attack') { | |
| // 重攻击克制轻攻击 | |
| playerCharacter.classList.add('player-attack'); | |
| enemyCharacter.classList.add('enemy-hit'); | |
| setTimeout(() => { | |
| playerCharacter.classList.remove('player-attack'); | |
| enemyCharacter.classList.remove('enemy-hit'); | |
| }, 600); | |
| const damage = player.basicDamage * 1.5; | |
| enemy.currentHealth -= damage; | |
| enemy.energy -= 1; // 消耗敌人的能量 | |
| addLog(`${player.name}的重攻击无效化了${enemy.name}的轻攻击,并造成${damage}点伤害!`); | |
| enemyWasHit = true; | |
| } else { | |
| playerCharacter.classList.add('player-attack'); | |
| enemyCharacter.classList.add('enemy-hit'); | |
| setTimeout(() => { | |
| playerCharacter.classList.remove('player-attack'); | |
| enemyCharacter.classList.remove('enemy-hit'); | |
| }, 600); | |
| const damage = player.basicDamage * 1.5; | |
| enemy.currentHealth -= damage; | |
| addLog(`${player.name}的重攻击对${enemy.name}造成${damage}点伤害!`); | |
| enemyWasHit = true; | |
| } | |
| } | |
| if (enemyAction === 'heavy-attack' && | |
| playerAction !== 'special' && | |
| enemyAction !== 'special') { | |
| enemy.energy -= 2; | |
| // 检查是否被防御或是否无效对方轻攻击 | |
| if (playerDefending) { | |
| enemyCharacter.classList.add('enemy-attack'); | |
| setTimeout(() => { | |
| enemyCharacter.classList.remove('enemy-attack'); | |
| }, 600); | |
| addLog(`${enemy.name}的重攻击被${player.name}防御了!`); | |
| } else if (playerAction === 'light-attack') { | |
| // 重攻击克制轻攻击 | |
| enemyCharacter.classList.add('enemy-attack'); | |
| playerCharacter.classList.add('player-hit'); | |
| setTimeout(() => { | |
| enemyCharacter.classList.remove('enemy-attack'); | |
| playerCharacter.classList.remove('player-hit'); | |
| }, 600); | |
| const damage = enemy.basicDamage * 1.5; | |
| player.currentHealth -= damage; | |
| player.energy -= 1; // 消耗玩家的能量 | |
| addLog(`${enemy.name}的重攻击无效化了${player.name}的轻攻击,并造成${damage}点伤害!`); | |
| playerWasHit = true; | |
| } else { | |
| enemyCharacter.classList.add('enemy-attack'); | |
| playerCharacter.classList.add('player-hit'); | |
| setTimeout(() => { | |
| enemyCharacter.classList.remove('enemy-attack'); | |
| playerCharacter.classList.remove('player-hit'); | |
| }, 600); | |
| const damage = enemy.basicDamage * 1.5; | |
| player.currentHealth -= damage; | |
| addLog(`${enemy.name}的重攻击对${player.name}造成${damage}点伤害!`); | |
| playerWasHit = true; | |
| } | |
| } | |
| // 如果没有被重攻击或绝招无效,处理轻攻击 | |
| if (playerAction === 'light-attack' && | |
| enemyAction !== 'heavy-attack' && | |
| enemyAction !== 'special') { | |
| player.energy -= 1; | |
| // 检查是否被防御 | |
| if (enemyDefending) { | |
| playerCharacter.classList.add('player-attack'); | |
| setTimeout(() => { | |
| playerCharacter.classList.remove('player-attack'); | |
| }, 600); | |
| addLog(`${player.name}的轻攻击被${enemy.name}防御了!`); | |
| } else { | |
| playerCharacter.classList.add('player-attack'); | |
| enemyCharacter.classList.add('enemy-hit'); | |
| setTimeout(() => { | |
| playerCharacter.classList.remove('player-attack'); | |
| enemyCharacter.classList.remove('enemy-hit'); | |
| }, 600); | |
| const damage = player.basicDamage; | |
| enemy.currentHealth -= damage; | |
| addLog(`${player.name}的轻攻击对${enemy.name}造成${damage}点伤害!`); | |
| enemyWasHit = true; | |
| } | |
| } | |
| if (enemyAction === 'light-attack' && | |
| playerAction !== 'heavy-attack' && | |
| playerAction !== 'special') { | |
| enemy.energy -= 1; | |
| // 检查是否被防御 | |
| if (playerDefending) { | |
| enemyCharacter.classList.add('enemy-attack'); | |
| setTimeout(() => { | |
| enemyCharacter.classList.remove('enemy-attack'); | |
| }, 600); | |
| addLog(`${enemy.name}的轻攻击被${player.name}防御了!`); | |
| } else { | |
| enemyCharacter.classList.add('enemy-attack'); | |
| playerCharacter.classList.add('player-hit'); | |
| setTimeout(() => { | |
| enemyCharacter.classList.remove('enemy-attack'); | |
| playerCharacter.classList.remove('player-hit'); | |
| }, 600); | |
| const damage = enemy.basicDamage; | |
| player.currentHealth -= damage; | |
| addLog(`${enemy.name}的轻攻击对${player.name}造成${damage}点伤害!`); | |
| playerWasHit = true; | |
| } | |
| } | |
| // 确保生命值不为负数 | |
| if (player.currentHealth < 0) player.currentHealth = 0; | |
| if (enemy.currentHealth < 0) enemy.currentHealth = 0; | |
| // 受击反馈动画 | |
| if (playerWasHit) { | |
| gameContainer.classList.add('shake'); | |
| screenFlash.classList.add('active'); | |
| setTimeout(() => { | |
| gameContainer.classList.remove('shake'); | |
| screenFlash.classList.remove('active'); | |
| }, 400); | |
| } | |
| if (enemyWasHit) { | |
| npcPortraitLayer.classList.add('shake'); | |
| setTimeout(() => { | |
| npcPortraitLayer.classList.remove('shake'); | |
| }, 400); | |
| } | |
| // 更新显示 | |
| updateDisplay(); | |
| } | |
| // 继续游戏 | |
| function continueGame() { | |
| // 重置选择状态 | |
| gameState.player.selectedAction = null; | |
| gameState.enemy.selectedAction = null; | |
| gameState.waitingForConfirmation = false; | |
| selectedActionText.textContent = '无'; | |
| // 更新显示 | |
| updateDisplay(); | |
| // 继续游戏 | |
| addLog('准备下一回合...'); | |
| // 更新回合指示 | |
| setTimeout(() => { | |
| addLog('请选择你的行动...'); | |
| }, 1000); | |
| } | |
| // 检查游戏是否结束 | |
| function checkGameOver() { | |
| if (gameState.player.currentHealth <= 0) { | |
| addLog(`${gameState.player.name}被击败了!游戏结束。`); | |
| gameEnd(false); | |
| return true; | |
| } else if (gameState.enemy.currentHealth <= 0) { | |
| addLog(`${gameState.enemy.name}被击败了!胜利!`); | |
| gameEnd(true); | |
| return true; | |
| } | |
| return false; | |
| } | |
| // 游戏结束 | |
| function gameEnd(isVictory) { | |
| // 禁用所有按钮 | |
| commandButtons.forEach(btn => { | |
| btn.classList.add('disabled'); | |
| }); | |
| // 显示结果 | |
| addLog(isVictory ? '恭喜你取得胜利!' : '游戏结束,再接再厉!'); | |
| // 添加重新开始游戏的按钮 | |
| const restartBtn = document.createElement('button'); | |
| restartBtn.textContent = '重新开始'; | |
| restartBtn.style.padding = '10px 20px'; | |
| restartBtn.style.margin = '10px auto'; | |
| restartBtn.style.display = 'block'; | |
| restartBtn.style.backgroundColor = '#4c3d2e'; | |
| restartBtn.style.color = 'white'; | |
| restartBtn.style.border = '1px solid #7c5a3d'; | |
| restartBtn.style.borderRadius = '4px'; | |
| restartBtn.style.cursor = 'pointer'; | |
| restartBtn.style.fontFamily = "'Ma Shan Zheng', cursive"; | |
| restartBtn.style.fontSize = '18px'; | |
| restartBtn.onclick = () => window.location.reload(); | |
| battleLog.appendChild(restartBtn); | |
| } | |
| // 键盘事件处理 | |
| function handleKeyPress(event) { | |
| // 如果弹窗显示中,按ESC关闭 | |
| if (confirmModal.style.display === 'flex' && event.key === 'Escape') { | |
| confirmModal.style.display = 'none'; | |
| gameState.player.selectedAction = null; | |
| updateDisplay(); | |
| return; | |
| } | |
| // 如果弹窗显示中,按Enter确认 | |
| if (confirmModal.style.display === 'flex' && event.key === 'Enter') { | |
| confirmModal.style.display = 'none'; | |
| confirmAction(); | |
| return; | |
| } | |
| // 如果不是玩家回合或正在等待确认,返回 | |
| if (gameState.currentTurn !== 'player' || gameState.waitingForConfirmation) return; | |
| const key = event.key.toUpperCase(); | |
| switch (key) { | |
| case 'Q': | |
| selectAction('gather'); | |
| break; | |
| case 'W': | |
| selectAction('defend'); | |
| break; | |
| case 'E': | |
| selectAction('light-attack'); | |
| break; | |
| case 'R': | |
| selectAction('heavy-attack'); | |
| break; | |
| case 'T': | |
| selectAction('special'); | |
| break; | |
| case 'Y': | |
| selectAction('taunt'); | |
| break; | |
| } | |
| } | |
| // 初始化游戏 | |
| document.addEventListener('DOMContentLoaded', () => { | |
| // 设置主背景 | |
| const gameContainer = document.querySelector('.game-container'); | |
| if (gameContainer) { | |
| // 保持立绘层的背景不变,只设置背景图层 | |
| const npcPortraitLayer = document.querySelector('.npc-portrait-layer'); | |
| gameContainer.style.backgroundImage = `url('${GAME_BG_URL}')`; | |
| } | |
| // 设置弹窗背景 | |
| const modalContents = document.querySelectorAll('.modal-content'); | |
| modalContents.forEach(modal => { | |
| modal.style.background = `url('${MODAL_BG_URL}') center center / cover`; | |
| }); | |
| initGame(); | |
| }); | |