2D平台游戏水平移动方块左侧碰撞玩家穿模Bug排查
2D平台游戏水平移动方块单侧碰撞失效问题
更新:我使用p5.js重写了最小可复现示例,核心逻辑如下:
let keyInput = [] let player let block function setup() { createCanvas(600, 600) player = new Player(0, height/2) block = new Block(200, height-100, 100, 1000) } function draw() { background(220); player.draw() block.draw() player.moveX() block.checkCollisionsX() player.moveY() block.checkCollisionsY() } function keyPressed() { keyInput[keyCode] = true; } function keyReleased() { keyInput[keyCode] = false; } function rectCollide(x1, y1, w1, h1, x2, y2, w2, h2) { return x1 + w1 > x2 && x1 < x2 + w2 && y1 + h1 > y2 && y1 < y2 + h2; } // 方块构造类 class Block { constructor(x, y, w, h) { this.x = x; this.y = y; this.w = w; this.h = h; this.movingSpeed = 3; this.start = 200 this.stop = 400 } draw() { fill(255) rect(this.x, this.y, this.w, this.h) this.x += this.movingSpeed; if (this.x > this.stop) { this.movingSpeed = -this.movingSpeed; } if (this.x < this.start) { this.movingSpeed = abs(this.movingSpeed); } } checkCollisionsX() { if (rectCollide(player.pos.x, player.pos.y, player.width, player.height, this.x, this.y, this.w, this.h)) { if (player.vel.x < 0) { // 玩家左移碰撞方块右侧 player.pos.x = this.x + this.w; } else { // 玩家右移碰撞方块左侧(该侧逻辑失效) player.pos.x = this.x - player.width; } player.vel.x = 0; } } checkCollisionsY() { if (rectCollide(player.pos.x, player.pos.y, player.width, player.height, this.x, this.y, this.w, this.h)) { if (player.vel.y < 0) { player.pos.y = this.y + this.h; player.vel.y *= -yRebound; // 非完全弹性碰撞,回弹系数不为-1 } else { //player.pos.x += movingSpeed; // 平台移动时将玩家同步固定在平台上 player.jumps = player.numJumps; player.pos.y = this.y - player.height; player.vel.y = 0; player.acc.y = 0; } } } } // 玩家构造类 class Player { constructor(x, y) { this.width = 50 this.height = 100 this.pos = new p5.Vector(x, y); this.vel = new p5.Vector(0, 0); this.acc = new p5.Vector(0, 0); this.accSpeed = 0.05; this.gravity = 0.5; this.maxVel = 10; this.jumpForce = 15; this.friction = 0.15; this.numJumps = 1; this.jumps = this.numJumps; this.isGrounded = false; this.canMove = true; this.dir = "DOWN" } draw() { fill(255, 0, 0) rect(this.pos.x, this.pos.y, this.width, this.height) } moveX() { // X轴移动逻辑 if (keyInput[LEFT_ARROW] && this.vel.x > -this.maxVel && this.canMove) { this.acc.x = -this.accSpeed; } else if (keyInput[RIGHT_ARROW] && this.vel.x < this.maxVel && this.canMove) { this.acc.x = this.accSpeed; } else if (abs(this.vel.x) > 0.2) { this.acc.x = (this.vel.x < 0) ? this.friction : -this.friction; } else { this.vel.x = 0; this.acc.x = 0; } this.vel.x += this.acc.x; // 速度累加加速度 this.pos.x += this.vel.x; // 位置累加速度 } moveY() { // Y轴移动逻辑 if (keyInput[UP_ARROW] && this.jumps > 0 && this.canMove) { this.jumps--; this.vel.y = -this.jumpForce; } this.acc.y += this.gravity; this.vel.y += this.acc.y; this.pos.y += this.vel.y; this.acc.y = 0; // 重置加速度 if (this.pos.y >= height - this.height) { this.pos.y = height-this.height this.jumps = this.numJumps; } } }
对应示例的HTML代码:
<!DOCTYPE html> <html lang="en"> <head> <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/addons/p5.sound.min.js"></script> <link rel="stylesheet" type="text/css" href="style.css"> <meta charset="utf-8" /> </head> <body> <main> </main> </body> </html>
我正在开发一款2D平台游戏,目前除水平移动方块的左侧碰撞外,其余所有方块的碰撞逻辑均运行正常。
水平移动方块的实现代码如下:
if (type.equals("moving-horizontal-2x1")) { image(img2x1, pos.x, pos.y, 200, 100); pos.x += movingSpeed; if (pos.x > stop) { movingSpeed = -movingSpeed; } if (pos.x < start) { movingSpeed = abs(movingSpeed); } }
玩家与方块碰撞时,除X轴方向的方块左侧外,其余各面碰撞均正常,异常效果如下图:
另有演示视频展示了玩家与移动方块碰撞时的异常表现。
从演示内容可以看到,玩家会被错误移位到方块另一侧。我不清楚该问题的产生原因,当前使用的碰撞检测/解算代码与其他静态方块的逻辑完全一致,仅单侧碰撞会失效。
当前X轴方向的碰撞检测代码如下:
if (rectCollide(player.pos.x, player.pos.y, player.width, player.height, pos.x, pos.y, width, height)) { if (player.vel.x < 0) { // 玩家向左移动,碰撞方块右侧 player.pos.x = pos.x + width; } else { // 玩家向右移动,碰撞方块左侧(该侧为故障侧) player.pos.x = pos.x - player.width; } player.vel.x = 0; }
我曾尝试在玩家碰撞方块左侧时调整玩家x坐标修复问题,例如执行player.pos.x += movingSpeed,但该方案并未生效。
我推测该Bug与移动方块的更新逻辑有关,这套碰撞检测/解算代码在所有其他静态方块上都能完美运行。
恳请各位提供排查思路与解决方案,感谢!
内容的提问来源于stack exchange,提问作者Scollier
相关产品推荐
相关产品推荐

