优化蒸汽引擎模拟系统:实现数值与仪表平滑变化
解决方案:平滑蒸汽引擎模拟数值变化并替换数组计算
关键修改步骤
1. 缩短更新间隔并适配步长
将定时器间隔从500ms改为100ms,同时按比例调整温度变化步长:
- 加热时,原500ms增加0.5℃ → 改为100ms增加
0.1℃(保持总升温速率不变) - 降温时,原500ms减少0.25℃ → 改为100ms减少
0.05℃
更小的步长配合更短的更新间隔,能让数值变化更顺滑,避免生硬跳变。
2. 用数学公式替代庞大数组
压力计算
原数组是温度从100℃到145℃时,压力从1Bar线性增长到10Bar,直接用线性公式计算即可:
pressure = 1 + (temperature - 100) * 0.2; pressure = Math.min(Math.max(pressure, 1), 10); // 限制压力在1-10Bar区间
速度计算
原数组的速度增长是非线性的(前期慢、后期快),用幂函数模拟这个物理特性,替代离散数组:
// 将压力映射到0-1区间,通过1.5次幂实现非线性增长,最终映射到0-90km/h speed = 90 * Math.pow((pressure - 1) / 9, 1.5); speed = Math.min(Math.max(speed, 0), 90); // 限制速度在0-90km/h区间
3. 优化数值显示精度
通过toFixed()方法保留1位小数,避免显示过多冗余小数位,同时保持平滑感:
function updateTemperatureDisplay() { temperatureDisplay.innerHTML = temperature.toFixed(1) + " °C"; } function updatePressureDisplay() { pressureDisplay.innerHTML = "Current Pressure: " + pressure.toFixed(1) + " Bar"; } function updateSpeedDisplay() { speedDisplay.innerHTML = speed.toFixed(1) + " km/h"; }
修改后的完整JS代码
let temperature = 20; let pressure = 1; let speed = 0; const temperatureDisplay = document.getElementById("temperature"); const pressureDisplay = document.getElementById("pressure"); const speedDisplay = document.getElementById("speed"); const gaugeElement = document.querySelector(".gauge"); function updateTemperatureDisplay() { temperatureDisplay.innerHTML = temperature.toFixed(1) + " °C"; } function updatePressureDisplay() { pressureDisplay.innerHTML = "Current Pressure: " + pressure.toFixed(1) + " Bar"; } function updateSpeedDisplay() { speedDisplay.innerHTML = speed.toFixed(1) + " km/h"; } function toggleHeater() { const heaterStatus = document.getElementById("heater-status"); const heaterAudio = document.getElementById("heater-audio"); if (heaterStatus.innerHTML === "On") { heaterStatus.innerHTML = "Off"; heaterAudio.pause(); } else { heaterStatus.innerHTML = "On"; heaterAudio.play(); } } function playSteamWhistle() { if (temperature >= 100) { const steamWhistle = new Audio("sfx6-whistlescreemtrain-33567.mp3"); steamWhistle.play(); temperature -= 2.5; } } // 提前封装仪表盘设置函数,避免重复定义 function setGaugeValue(gauge, value) { if (value < 0 || value > 90) { return; } gauge.querySelector(".gauge__fill").style.transform = `rotate(${value / 180}turn)`; gauge.querySelector(".gauge__cover").textContent = `${value.toFixed(1)} km/h`; } setInterval(function () { const heaterStatus = document.getElementById("heater-status"); if (heaterStatus.innerHTML === "On") { if (temperature < 145) { temperature += 0.1; // 适配100ms间隔的步长 } } else if (temperature > 20) { temperature -= 0.05; // 适配100ms间隔的步长 } if (temperature >= 100) { // 线性计算压力 pressure = 1 + (temperature - 100) * 0.2; pressure = Math.min(Math.max(pressure, 1), 10); // 非线性计算速度 speed = 90 * Math.pow((pressure - 1) / 9, 1.5); speed = Math.min(Math.max(speed, 0), 90); } else { // 温度低于100时,压力和速度平滑回落 pressure = Math.max(pressure - 0.02, 1); speed = Math.max(speed - 0.1, 0); } setGaugeValue(gaugeElement, speed); updateTemperatureDisplay(); updatePressureDisplay(); updateSpeedDisplay(); }, 100); // 更新间隔改为100ms
额外优化说明
- 将
setGaugeValue函数提取到定时器外部,避免每次触发都重新定义函数,提升性能 - 补充了温度低于100℃时,压力和速度的平滑回落逻辑,更贴近真实物理规律
- 用
Math.min/Math.max限制所有数值的合理区间,避免出现异常值
内容的提问来源于stack exchange,提问作者Riad Afandili
相关产品推荐
相关产品推荐

