如何阻止Canvas游戏角色双跳?长按W键角色会飞离画布
解决Canvas角色双跳与长按飞离问题
要实现落地后才能跳跃、防止长按W飞离画布,需要从地面状态判断和按键触发控制两个方面修改代码:
关键改动点
- 给
Player类添加isGrounded属性,标记角色是否处于地面 - 在
update方法中实时更新地面状态 - 用按键状态对象代替直接监听
keydown的持续触发,避免重复跳跃 - 只有当角色在地面时,才允许触发跳跃动作
修改后的完整代码
/** @type {HTMLCanvasElement}*/ const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); const canvasWidth = canvas.width = window.innerWidth const canvasHeight = canvas.height = window.innerHeight // 记录按键状态,避免keydown持续触发重复跳跃 const keys = { w: false }; const playerImage = new Image(); playerImage.src = 'images/spriteRunRight.png' const platformImage = new Image(); platformImage.src = 'images/platform.png' class Player { constructor(){ this.x = 100 this.y = 540 this.velocityX = 0 this.velocityY = 0 this.speed = 10 this.gravity = 0.5 this.width = 130 this.height = 160 this.spriteW = 341 this.spriteH = 400 this.frameX = 0 this.frameY = 0 this.image = playerImage // 新增:标记角色是否在地面 this.isGrounded = true; } draw(){ ctx.drawImage(playerImage, this.frameX * this.spriteW, this.frameY * this.spriteH , this.spriteW, this.spriteH, this.x, this.y, this.width, this.height) } update(){ this.draw() this.y += this.velocityY this.x += this.velocityX // 更新地面状态:当角色底部接触画布底部时,标记为在地面 this.isGrounded = (this.y + this.height >= canvas.height); if(this.y + this.height + this.velocityY <= canvas.height){ this.velocityY += this.gravity } else { this.velocityY = 0; // 落地时重置y坐标,避免角色陷入地面 this.y = canvas.height - this.height; } } } const player = new Player() // 监听按键按下:只标记按键状态为true addEventListener('keydown', ({keyCode}) => { switch(keyCode){ case 87: // W键 if(!keys.w){ keys.w = true; // 只有在地面时才允许跳跃 if(player.isGrounded){ player.velocityY -= 20; player.isGrounded = false; // 跳跃后立即标记为非地面状态 } } break; } }) // 监听按键松开:重置按键状态 addEventListener('keyup', ({keyCode}) => { switch(keyCode){ case 87: keys.w = false; break; } }) // 游戏主循环(必须添加,否则角色状态不会实时更新) function animate(){ // 清空画布,避免帧残留 ctx.clearRect(0, 0, canvas.width, canvas.height); player.update(); requestAnimationFrame(animate); } animate();
代码解释
- 按键状态对象
keys:解决长按W时keydown持续触发的问题,只有当W键从松开变为按下时,才会触发一次跳跃判断。 isGrounded属性:在update方法中实时检查角色是否接触地面,只有该状态为true时,才允许执行跳跃。- 落地坐标修正:当角色落地时,强制把
y设为canvas.height - this.height,避免因为重力计算导致角色陷入地面。 - 添加游戏主循环
animate:原代码缺少主循环,角色的update方法不会被持续调用,这也是之前逻辑可能失效的原因之一。
内容的提问来源于stack exchange,提问作者confusedPro
相关产品推荐
相关产品推荐

