HTML开发贪吃蛇游戏收集浆果后蛇身出现异常偏移如何解决
贪吃蛇身体偏移问题修复方案
核心问题根因
你遇到的偏移累加问题来自两个底层逻辑错误:
- 坐标基准不统一:蛇头放在
.game-background相对父容器定位,新增的身体节点直接插入到body下用绝对定位,offset()取的是相对于文档的全局坐标,和蛇头的相对定位坐标基准不一致,每新增一个身体就会叠加一层父容器的偏移量。 - 位置更新顺序错误:你先更新身体坐标、再更新蛇头位置,导致身体永远用的是蛇头上一次移动的旧坐标,加上多方向偏移的计算逻辑错误,移动次数越多偏移越明显。
具体修改步骤
1. 统一元素容器基准
修改addSnake函数,把新增的身体节点插入到游戏背景容器内,不要插在全局body上:
addSnake = function (snakes) { if (numOfSnakes < 5) { // 把原来的body改成游戏背景容器 var parent = background[0]; var newBodyPart = document.createElement("div"); newBodyPart.className = "game-player" + numOfSnakes; parent.appendChild(newBodyPart); snakes.push("game-player" + numOfSnakes); numOfSnakes++; } };
2. 调整位置更新顺序+修正偏移计算
修改按键逻辑,先更新蛇头位置,再基于蛇头的最新坐标更新身体位置,同时删掉冗余的updatePos变量,修正多方向的偏移逻辑:
$(document).keyup(function (e) { var key = e.keyCode || e.which; const keys = { UP: 38, DOWN: 40, LEFT: 37, RIGHT: 39, }; let moveOffset = 24; // 20px宽度+2px左右边框,刚好无缝衔接 // 先更新蛇头位置 if (key === keys.UP && verticalNum > 0 && !String(verticalNum).includes("e")) { verticalNum -= speed; verticalNum = Math.max(verticalNum, 0); $(".game-player").css("top", verticalNum); // 再更新身体,向上移动时身体依次排在蛇头下方 for (var i = 0; i < snakesArray.length; i++) { $("." + snakesArray[i]).css({ top: verticalNum + (i+1)*moveOffset, left: horizontalNum }); } } else if (key === keys.DOWN && verticalNum < 475.8) { verticalNum += speed; verticalNum = Math.min(verticalNum, 475.8); $(".game-player").css("top", verticalNum); // 向下移动时身体依次排在蛇头上方 for (var i = 0; i < snakesArray.length; i++) { $("." + snakesArray[i]).css({ top: verticalNum - (i+1)*moveOffset, left: horizontalNum }); } } else if (key === keys.LEFT && horizontalNum > 0 && !String(horizontalNum).includes("e")) { horizontalNum -= speed; horizontalNum = Math.max(horizontalNum, 0); $(".game-player").css("left", horizontalNum); // 向左移动时身体依次排在蛇头右侧 for (var i = 0; i < snakesArray.length; i++) { $("." + snakesArray[i]).css({ left: horizontalNum + (i+1)*moveOffset, top: verticalNum }); } } else if (key === keys.RIGHT && horizontalNum < 475.8) { horizontalNum += speed; horizontalNum = Math.min(horizontalNum, 475.8); $(".game-player").css("left", horizontalNum); // 向右移动时身体依次排在蛇头左侧 for (var i = 0; i < snakesArray.length; i++) { $("." + snakesArray[i]).css({ left: horizontalNum - (i+1)*moveOffset, top: verticalNum }); } } // 碰撞检测放在所有位置更新完成后执行 WObject.isTouching($(".game-player"), $(".game-food")); });
3. 修复新增身体的初始定位
修改updateSnakeCSS函数,基于当前蛇头的坐标直接设置新身体的位置,不要用offset计算:
updateSnakeCSS = function (snakes) { if (snakes.length <= 0) return; let targetClass = snakes[snakes.length - 1]; $("." + targetClass).css({ position: "absolute", left: horizontalNum, top: verticalNum, border: "2px outset black", width: player.width(), height: player.height(), "background-color": "red" }); };
修改完后就不会出现偏移累加的问题,身体会严格跟随蛇头移动,最多5个身体的限制也能正常生效。
内容的提问来源于stack exchange,提问作者Ryan's World
相关产品推荐
相关产品推荐

