Canvas矩形移动时无法触发边界反弹问题求助
Canvas矩形反弹功能失效问题修复
我正在为课程开发一款简单游戏,想通过bounce函数让矩形在Canvas边界内移动时触发反弹,但这个功能无效——移动矩形时它会直接飞出Canvas边界,找不到问题出在哪。以下是我的代码:
var canvas; var ctx; var w = 1000; var h = 700; var o1 = { x: 100, y: h/2, w: 100, h: 100, c: 0, a: 100, angle: 0, //changes angle that shape sits at distance: 10 } document.onkeydown = function(e){keypress(e, o1)} setUpCanvas(); animationLoop(); function animationLoop(){ clear(); rect(o1); bounce(o1) requestAnimationFrame(animationLoop) } function bounce(o){ if(o.x+o.w/2 > w || o.x-o.w/2 < 0){ o.changeX *= -1; } if(o.y+o.h/2 > h || o.y-o.h/2 <0){ o.changeY *= -1; } } function updateData(o){ o.x += o.changeX; o.y += o.changeY; } function keypress(e,o){ if (e.key == "ArrowUp"){ o.angle = 270; o.distance= 80; forward(o); } if (e.key == "ArrowDown"){ o.angle = 90; o.distance= 20; forward(o); } } function forward(o){ var cx; var cy; cx = o.distance*Math.cos(o.angle); cy = o.distance*Math.sin(o.angle) o.y += cy; } function rect(o){ var bufferx = o.x; var buffery = o.y o.x = o.x - o.w/2; o.y = o.y- o.h/2; ctx.beginPath(); ctx.moveTo(o.x,o.y); ctx.lineTo(o.x+o.w,o.y); ctx.lineTo(o.x+o.w,o.y+o.h); ctx.lineTo(o.x, o.y+o.h); ctx.lineTo(o.x,o.y); ctx.fillStyle = "hsla("+String (o.c)+",100%,50%,"+o.a+")"; ctx.fill(); o.x = bufferx; o.y = buffery; } function clear(){ ctx.clearRect(0, 0, w, h); } function randn(range){ var r = Math.random()*range-(range/2); return r } function rand(range){ var r = Math.random()*range return r } function setUpCanvas(){ canvas = document.querySelector("#myCanvas"); canvas.width = w; canvas.height = h; canvas.style.border = "10px solid black"; ctx = canvas.getContext("2d"); } console.log("Final Assignment")
问题原因及修复步骤
1. 缺失核心属性
o1对象中没有定义changeX和changeY属性,bounce函数里对这两个属性的操作完全无效。需要在o1中添加初始值:
var o1 = { // ... 原有属性 changeX: 0, changeY: 0 }
2. 未调用位置更新函数
animationLoop里只调用了bounce,但没有执行updateData来根据changeX/changeY更新矩形位置。修改animationLoop:
function animationLoop(){ clear(); rect(o1); updateData(o1); // 先更新位置 bounce(o1); // 再检测反弹 requestAnimationFrame(animationLoop) }
3. 角度单位不匹配
JavaScript的Math.cos和Math.sin接收弧度作为参数,但代码里用的是度数,导致移动计算完全错误。修改forward函数,把角度转为弧度:
function forward(o){ var angleInRadians = o.angle * Math.PI / 180; o.changeY = o.distance * Math.sin(angleInRadians); // 改为设置changeY,而非直接修改y }
4. 反弹逻辑不完善
原bounce函数只反转方向,但如果矩形已经超出边界,会持续触发反弹判断。需要在反转方向后将矩形拉回边界:
function bounce(o){ // 水平边界检测 if(o.x + o.w/2 > w){ o.x = w - o.w/2; // 拉回右边界内 o.changeX *= -1; } else if(o.x - o.w/2 < 0){ o.x = o.w/2; // 拉回左边界内 o.changeX *= -1; } // 垂直边界检测 if(o.y + o.h/2 > h){ o.y = h - o.h/2; // 拉回下边界内 o.changeY *= -1; } else if(o.y - o.h/2 < 0){ o.y = o.h/2; // 拉回上边界内 o.changeY *= -1; } }
修复后的完整代码
var canvas; var ctx; var w = 1000; var h = 700; var o1 = { x: 100, y: h/2, w: 100, h: 100, c: 0, a: 100, angle: 0, distance: 10, changeX: 0, changeY: 0 } document.onkeydown = function(e){keypress(e, o1)} setUpCanvas(); animationLoop(); function animationLoop(){ clear(); rect(o1); updateData(o1); bounce(o1); requestAnimationFrame(animationLoop) } function bounce(o){ if(o.x + o.w/2 > w){ o.x = w - o.w/2; o.changeX *= -1; } else if(o.x - o.w/2 < 0){ o.x = o.w/2; o.changeX *= -1; } if(o.y + o.h/2 > h){ o.y = h - o.h/2; o.changeY *= -1; } else if(o.y - o.h/2 < 0){ o.y = o.h/2; o.changeY *= -1; } } function updateData(o){ o.x += o.changeX; o.y += o.changeY; } function keypress(e,o){ if (e.key == "ArrowUp"){ o.angle = 270; o.distance= 80; forward(o); } if (e.key == "ArrowDown"){ o.angle = 90; o.distance= 20; forward(o); } } function forward(o){ var angleInRadians = o.angle * Math.PI / 180; o.changeY = o.distance * Math.sin(angleInRadians); } function rect(o){ var bufferx = o.x; var buffery = o.y o.x = o.x - o.w/2; o.y = o.y- o.h/2; ctx.beginPath(); ctx.moveTo(o.x,o.y); ctx.lineTo(o.x+o.w,o.y); ctx.lineTo(o.x+o.w,o.y+o.h); ctx.lineTo(o.x, o.y+o.h); ctx.lineTo(o.x,o.y); ctx.fillStyle = "hsla("+String (o.c)+",100%,50%,"+o.a+")"; ctx.fill(); o.x = bufferx; o.y = buffery; } function clear(){ ctx.clearRect(0, 0, w, h); } function randn(range){ var r = Math.random()*range-(range/2); return r } function rand(range){ var r = Math.random()*range return r } function setUpCanvas(){ canvas = document.querySelector("#myCanvas"); canvas.width = w; canvas.height = h; canvas.style.border = "10px solid black"; ctx = canvas.getContext("2d"); } console.log("Final Assignment")
内容的提问来源于stack exchange,提问作者user20670829
相关产品推荐
相关产品推荐

