You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么新增的if语句会导致我的JavaScript骑士跳岩游戏功能失效

问题原因分析

  1. 无限死循环阻塞主线程:你代码中的while (falseVar == false)循环内没有任何修改falseVar值的逻辑,循环会无限执行,完全占满JS单线程,直接导致页面崩溃。你想要的动画循环效果不能用同步while循环实现,需要靠异步的动画结束回调触发下一次动画。
  2. 冗余代码问题:三个动画函数逻辑高度重复,且定义在循环内部,每次循环都会重复创建函数,产生不必要的性能开销。
  3. 潜在样式冲突风险:添加新的动画类之前没有清除旧的动画类,多个类叠加可能导致动画表现异常。

修复后的代码参考

CSS代码

#rock {
    height: 50px;
    width: 50px;
    position: relative;
    top: 122px;
    left: 550px;
    background-image: url("http://pixelartmaker-data-78746291193.nyc3.digitaloceanspaces.com/image/da268f06e621b21.png");
    background-size: cover;
}

.rockAnimationFast {
    animation: rockAnimationFast 0.75s linear forwards;
}

.rockAnimationMedium {
    animation: rockAnimationMedium 1s linear forwards;
}

.rockAnimationSlow {
    animation: rockAnimationSlow 1.5s linear forwards;
}

@keyframes rockAnimationFast {
    0%{left: 500px;}
    100%{left: -50px;}
}

@keyframes rockAnimationMedium {
    0%{left: 500px;}
    100%{left: -50px;}
}

@keyframes rockAnimationSlow {
    0%{left: 500px;}
    100%{left: -50px;}
}

JavaScript代码

// 缓存岩石DOM节点,避免每次查询DOM
const rock = document.getElementById("rock");
// 动画配置统一管理
const animationConfigs = [
  { className: 'rockAnimationFast', duration: 750, weight: 4 }, // 权重4,对应0-3共4个随机值
  { className: 'rockAnimationMedium', duration: 1000, weight: 4 }, // 权重4,对应4-7共4个随机值
  { className: 'rockAnimationSlow', duration: 1500, weight: 2 } // 权重2,对应8-9共2个随机值
]
let dead = false;

// 单次岩石动画逻辑
function playRockAnimation() {
  if (dead) return;
  // 清除所有旧的动画类
  rock.classList.remove('rockAnimationFast', 'rockAnimationMedium', 'rockAnimationSlow');
  // 强制回流,保证移除类之后重新添加类能触发动画重放
  void rock.offsetWidth;

  // 随机选择动画
  const randRockSpeed = Math.floor(Math.random() * 10);
  let selectedConfig;
  if (randRockSpeed <=3) {
    selectedConfig = animationConfigs[0];
  } else if (randRockSpeed <=7) {
    selectedConfig = animationConfigs[1];
  } else {
    selectedConfig = animationConfigs[2];
  }

  // 添加动画类
  rock.classList.add(selectedConfig.className);
  // 动画结束后触发下一次动画
  setTimeout(() => {
    playRockAnimation();
  }, selectedConfig.duration);
}

function play() {
  dead = false;
  playRockAnimation();
}

// 如果需要终止游戏,调用这个方法即可
function stopGame() {
  dead = true;
}

关键修改说明

  • 去掉了同步死循环,改用setTimeout在每次动画结束后异步触发下一次动画,不会阻塞主线程
  • 提前缓存了岩石DOM节点,避免每次都查询DOM提升性能
  • 每次添加动画类前先清除所有旧动画类,加void rock.offsetWidth触发浏览器回流,保证动画可以重复触发
  • 所有动画配置统一管理,后续要调整速度、概率都可以直接修改配置数组,不用修改逻辑代码

内容的提问来源于stack exchange,提问作者flyingchicken

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 13:54:07