JavaScript状态引擎初次尝试失败,画布内容无法切换
解决Canvas状态切换时旧内容残留的问题
嘿,别担心,刚接触编程和Canvas遇到这种问题太正常啦!你的核心问题其实是Canvas的绘制是叠加式的——每次你调用drawBox画新盒子,之前画的内容不会自动消失,得手动清除画布才行。另外你的代码里还有个小bug,也得一起修正,不然帧率会有问题。
问题分析
- 未清除画布:每次切换状态后,新的盒子画在旧盒子上面,导致所有盒子都保留在画布上。
- setInterval参数错误:
setInterval的第二个参数是毫秒数,你传入的FPS=60意味着每60毫秒执行一次,这会导致每秒仅执行16次左右,远低于你想要的60帧。正确的计算应该是1000/FPS,也就是每16.67毫秒执行一次。
解决方案步骤
1. 添加清屏函数
先写一个简单的函数,用来清除整个Canvas的内容:
function clearCanvas() { // 从(0,0)开始,清除整个画布的宽高范围 ctx.clearRect(0, 0, c.width, c.height); }
2. 修复帧率设置
把ticker函数里的setInterval参数改成1000/FPS:
function ticker(){ setInterval(initGame, 1000/FPS); }
3. 每次绘制前清屏
在initGame函数里,调用checkState之前先执行清屏,这样每次状态更新前都会把旧内容清除干净:
function initGame(){ clearCanvas(); // 先清屏 checkState(); counter++; }
修改后的完整代码
<!DOCTYPE html> <html> <body onload="init()"> <canvas id="myCanvas" width="1024" height="1024" style="border:1px solid #d3d3d3;"></canvas> <script> var FPS = 60; var counter = 0; var currentState = 0; var intervalTime = 300; var c = document.getElementById("myCanvas"); var ctx = c.getContext("2d"); function init(){ ticker(); } function ticker(){ setInterval(initGame, 1000/FPS); } function initGame(){ clearCanvas(); checkState(); counter++; } function drawBox(x,y){ ctx.fillStyle="#FF0000"; ctx.fillRect(x, y, 50, 50); } function clearCanvas() { ctx.clearRect(0, 0, c.width, c.height); } function checkState(){ switch(currentState){ case 0: console.log("case 0"); drawBox(0,0); if (counter === intervalTime){ counter = 0; currentState = 1; } break; case 1: console.log("case 1"); drawBox(50,0); if (counter === intervalTime){ counter = 0; currentState = 2; } break; case 2: console.log("case 2"); drawBox(100,0); if (counter === intervalTime){ counter = 0; currentState = 0; } break; } } </script> </body> </html>
额外小建议
- 对于游戏状态管理,你可以把每个状态的逻辑封装成独立的函数(比如
state0()、state1()),这样代码会更清晰,后期拓展关卡也更方便。 - 记得Canvas的绘制上下文(
ctx)会保留之前的设置(比如fillStyle),如果不同状态需要不同样式,最好每次绘制前明确设置,避免样式混乱。
内容的提问来源于stack exchange,提问作者Jack Smillie
相关产品推荐
相关产品推荐

