根本原因是坐标未更新对象属性,如move(tank.x+dx,tank.y+dy)未赋值回tank.x/y;碰撞检测需用包围盒并统一坐标系;多线程乱序因共享状态未保护,应单循环+原子替换;控制台乱码因编码不匹配,需chcp 65001+utf8编码+软重置清屏。

坦克移动时位置没更新,draw() 总画在老地方
根本原因通常是把坐标当“值”传进函数,却没改对象本身的 x、y 属性。比如写 move(tank.x + dx, tank.y + dy) 却没赋值回 tank.x 和 tank.y,下次 draw(tank) 还用旧值。
实操建议:
- 所有位移操作必须显式更新对象属性:
tank.x += dx; tank.y += dy; - 避免在
draw()里临时算坐标——它只负责渲染,不负责逻辑 - 如果用了封装函数如
moveTank(tank, dx, dy),确保函数内部有tank.x += dx这类赋值,而不是只返回新坐标
isCollide() 总返回 false,但肉眼明显撞上了
常见于用矩形碰撞但没对齐坐标系:控制台绘图通常 y 轴向下,而数学惯性思维常默认 y 向上;或者忘了坦克有宽高,直接比 x == other.x && y == other.y。
实操建议:
- 统一用包围盒检测:
rect1.x rect2.x && ... - 确认所有坐标和尺寸单位一致(像素),且
width/height是坦克实际占位,不是贴图大小 - 调试时临时用
console.log打印双方x、y、width、height,别靠眼睛估
多线程一加就乱:子弹飞着飞着消失,或坦克卡住不动
控制台环境没有真正线程,所谓“多线程”其实是 setInterval 或 requestAnimationFrame 模拟的并发逻辑。问题出在共享状态没保护,比如两个定时器同时读写同一个 bullets 数组。
实操建议:
- 用单个主循环(如
requestAnimationFrame(gameLoop))统管更新+渲染,别开多个setInterval - 更新阶段先生成新状态(如新建
newBullets),再原子替换旧数组:bullets = newBullets; - 绝对不要在遍历
bullets时用splice()删除——改用filter()或标记后批量清理
Windows 控制台中文乱码、光标乱跳,clearScreen() 不生效
核心是编码和缓冲区刷新没对上。Node.js 默认 UTF-8,但 cmd.exe 默认 GBK;process.stdout.write('\x1B[2J') 清屏在部分终端不兼容。
实操建议:
- 启动脚本加
chcp 65001切换控制台为 UTF-8(或用execSync('chcp 65001 > nul')) - 清屏优先用
process.stdout.write('\x1Bc')(软重置),比\x1B[2J兼容性更好 - 输出中文前加
process.stdout.setEncoding('utf8'),并确保源文件存为 UTF-8 无 BOM
cursorTo() 和 clearScreen() 的调用时机稍错,整屏就错位。










