JS/HTML/CSS战斗游戏攻击按钮仅单次点击生效问题求助
问题
开发玩家对战敌人的简易战斗游戏,玩家拥有4个攻击按钮,点击按钮后生成随机数判定攻击先手,再生成随机数确定伤害值并累加到HP进度条中。但目前按钮仅首次点击能触发伤害计算,后续点击完全无效。
逻辑说明:
attackOrder():负责判定攻击先手start():启动攻击流程enemyAttack():生成敌人伤害
附完整代码:
HTML
<!DOCTYPE html> <html> <!-- Head --> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Mon Fight!</title> <link rel="stylesheet" href="style.css"> <style> body { background-image: url('battleBackground.png'); background-repeat: no-repeat; background-position: 50% 1%; } </style> </head> <!-- Body --> <body> <div class="container"> <!-- moves --> <div class="actions"> <button id = "attackMove1" class="userMove">Quick Attack</button> <button id = "attackMove2" class="userMove">Water Gun</button> </div> <div class="actions"> <button id = "attackMove3" class="userMove">Lick</button> <button id = "attackMove4" class="userMove">Pound</button> </div> <!-- user character --> <div class="userCharacter"> <img class="userSprite" src="https://www.pokencyclopedia.info/sprites/3ds/ani-b_6/3a-b__656__xy.gif" style = "position: absolute; left: 30%; top:50%"> <progress id = "userHP" value="0" max="100"></progress> </div> <!-- enemy character--> <div class="monsterCharacter"> <img class="enemySprite" src="https://pa1.aminoapps.com/6202/8b1a1344c2f3c1e5d8251d998f8e9b63e193c81f_hq.gif" style = "position: absolute; left: 58%; top:27%"> <progress id = "monsterHP" value="0" max="100"></progress> </div> </div> <script src="script.js"></script> </body> </html>
CSS
body { background-color: #449C6A; } progress { width: 300px; height : 25px; border: 2px solid #FFE5B4; } progress::-webkit-progress-bar { background-color: green; } progress::-webkit-progress-value { background-color: red; } body{ overflow:hidden; } .container{ width: 95%; height: 100vh; margin: auto; display: flex; align-items: end; justify-content: center; /*Delete after done*/ border: 1px solid black; } .actions{ width: 370px; margin: 0; border-radius: 2px; padding: 15px 15px 20px 20px; align-items: end; justify-content: center; position: static; /*Delete after done*/ border: 1px solid black; } .userMove{ width: 95%; height: 40px; border-radius: 2px; border: none; border-radius: 2rem; margin-top: 3px; margin-bottom: 15px; background: white(0, 0, 0); } .userMove:hover{background-color: rgba(255, 255, 255, 0.514);} #userHP{ position:fixed; top:72%; left:26.5%; } #monsterHP{ position:fixed; top:50%; left:57%; } img.userSprite{ width: 9%; height: auto; } img.enemySprite{ width: 13%; height: auto; }
JavaScript
var userDamage, monsterDamage = 0; var move = 0; var priority; var randomNum = 0; var someoneIsAlive = true; attackMove1.addEventListener("click", function(e){ attackOrder(); move = 1; }); attackMove2.addEventListener("click", function(e){ attackOrder(); move = 2; }); attackMove3.addEventListener("click", function(e){ attackOrder(); move = 3; }); attackMove4.addEventListener("click", function(e){ attackOrder(); move = 4; }); function attackOrder(){ let froakieSpeed = Math.floor((Math.random()* 62)); let goomySpeed = Math.floor((Math.random()* 55)); if (froakieSpeed > goomySpeed) { priority = "froakie"; } else { priority = "goomy" if (move = 1){priority = "froakie"}; } start(); } function start(){ if (priority = "froakie"){ userAttack(); enemyAttack(); } else { enemyAttack(); userAttack(); } } var poisonDamage; /* Quick Attack (unconditionally attacks first), Watergun, Lick (afflicts poison), Pound */ function userAttack(){ randomNum = Math.floor((Math.random() * 6)); switch(randomNum){ case 0: userDamage = 1; break; case 1: userDamage = 10; break; case 2: userDamage = 10; break; case 3: userDamage = 15; break; case 4: userDamage = 15; break; case 5: userDamage = 20; break; case 6: userDamage = 40; break; } if (move = 3){ poisonStatus(); } if (poisonStatus = true){ userDamage += 5; } let monsterHP = document.getElementById("monsterHP") monsterHP.value += userDamage; if (monsterHP.value >= 100){ alert("You Win!"); } } function enemyAttack(){ randomNum = Math.floor((Math.random() * 6)); switch(randomNum){ case 0: monsterDamage = 1; break; case 1: monsterDamage = 10; break; case 2: monsterDamage = 10; break; case 3: monsterDamage = 15; break; case 4: monsterDamage = 15; break; case 5: monsterDamage = 20; break; case 6: monsterDamage = 40; break; } let userHP = document.getElementById("userHP") userHP.value += monsterDamage; if (userHP.value >= 100){ alert("You Lose! :("); } } var poisonBreak; function poisonStatus(){ poisonBreak = Math.floor((Math.random() * 2 )); if (poisonBreak = 2){ poisonDamage = false; } else { poisonDamage = true; } } userDamage, monsterDamage = 0; randomNum = 0; move = 0;
问题原因与修复方案
核心错误点
- 赋值运算符替代比较运算符:代码中大量使用
=(赋值)而非===(严格比较),导致逻辑判断完全失效,比如if (priority = "froakie")会直接将priority设为"froakie",而非判断是否相等。 - 按钮点击逻辑顺序错误:点击按钮时先调用
attackOrder()再设置move,导致attackOrder()中无法获取当前点击的技能类型,先手判定逻辑出错。 - 进度条值类型问题:
progress元素的value是字符串类型,直接用+=会触发字符串拼接而非数值累加,比如"0"+10变成"010",后续>=100的判断永远为真,触发alert后用户误以为按钮失效。 - 变量初始化冗余:代码末尾重复初始化变量,覆盖了当前战斗状态,导致后续逻辑混乱。
修复后的JavaScript代码
var userDamage = 0, monsterDamage = 0; var move = 0; var priority; var randomNum = 0; var someoneIsAlive = true; var poisonDamage = false; // 初始化毒状态为false // 调整点击顺序:先设置当前技能,再执行攻击逻辑 attackMove1.addEventListener("click", function(e){ move = 1; attackOrder(); }); attackMove2.addEventListener("click", function(e){ move = 2; attackOrder(); }); attackMove3.addEventListener("click", function(e){ move = 3; attackOrder(); }); attackMove4.addEventListener("click", function(e){ move = 4; attackOrder(); }); function attackOrder(){ let froakieSpeed = Math.floor(Math.random() * 62); let goomySpeed = Math.floor(Math.random() * 55); // Quick Attack无条件先手,或玩家速度更高时先手 if (move === 1 || froakieSpeed > goomySpeed) { priority = "froakie"; } else { priority = "goomy"; } start(); } function start(){ if (priority === "froakie"){ userAttack(); // 敌人攻击前先判断是否已战败 if (parseInt(document.getElementById("monsterHP").value) < 100) { enemyAttack(); } } else { enemyAttack(); // 玩家攻击前先判断是否已战败 if (parseInt(document.getElementById("userHP").value) < 100) { userAttack(); } } } function userAttack(){ randomNum = Math.floor(Math.random() * 7); // 生成0-6的随机数,需乘7 switch(randomNum){ case 0: userDamage = 1; break; case 1: case 2: userDamage = 10; break; case 3: case 4: userDamage = 15; break; case 5: userDamage = 20; break; case 6: userDamage = 40; break; } // Lick技能触发毒状态判断 if (move === 3){ poisonStatus(); } // 毒状态生效时追加伤害 if (poisonDamage){ userDamage += 5; } let monsterHP = document.getElementById("monsterHP"); // 转换为数值后累加,避免字符串拼接 monsterHP.value = parseInt(monsterHP.value) + userDamage; if (monsterHP.value >= 100){ alert("You Win!"); // 获胜后禁用所有攻击按钮 document.querySelectorAll('.userMove').forEach(btn => btn.disabled = true); } } function enemyAttack(){ randomNum = Math.floor(Math.random() * 7); switch(randomNum){ case 0: monsterDamage = 1; break; case 1: case 2: monsterDamage = 10; break; case 3: case 4: monsterDamage = 15; break; case 5: monsterDamage = 20; break; case 6: monsterDamage = 40; break; } let userHP = document.getElementById("userHP"); userHP.value = parseInt(userHP.value) + monsterDamage; if (userHP.value >= 100){ alert("You Lose! :("); // 战败后禁用所有攻击按钮 document.querySelectorAll('.userMove').forEach(btn => btn.disabled = true); } } function poisonStatus(){ // 生成0或1的随机数,50%概率触发毒状态 poisonBreak = Math.floor(Math.random() * 2); poisonDamage = poisonBreak !== 0; }
额外优化
- 简化了
switch语句的重复分支,提升代码可读性 - 增加了战败/获胜后禁用按钮的逻辑,避免无效重复点击
- 修复了Quick Attack的先手逻辑(原代码中该技能的先手判断位置错误)
- 初始化
poisonDamage为false,避免未定义状态导致的逻辑异常
内容的提问来源于stack exchange,提问作者Potato
相关产品推荐
相关产品推荐

