P5.js画布数组目标点移动物体的代码优化及高速度适配问题
解答
1. 代码优化方案
原有代码存在多处可优化的点,调整后整洁度和鲁棒性都会大幅提升:
- 移除冗余的
number_is_larger、number_is_smaller包装函数,这类简单判断不需要单独封装,徒增代码量 - 禁止直接修改
targets数组内存储的原始路径点:原有代码直接把position指向targets里的向量,移动时直接修改原向量的x/y值,会破坏A*寻路返回的原始路径数据,后续如果需要复用路径会直接出错 - 去掉拆分x/y轴的重复条件判断:原有代码为了判断x、y的移动方向写了8个条件分支,逻辑冗余还容易写错,用p5自带的p5.Vector向量方法可以用几行代码实现相同逻辑
- 修正斜向移动速度不准的bug:原有代码x、y轴同时按speed值移动,斜向移动时实际速度是设定speed的√2倍,根本不是恒定速度
- 移除无用全局变量,比如代码里声明了但从来没调用过的
count变量
2. 大speed值到达判定失效的修复方案
失效原因是原有逻辑逐轴判断坐标大小,当speed取值较大时,单帧移动会直接跨过目标点的坐标阈值,原有判断逻辑识别不到“跨过目标”的情况,就会导致角色在目标点附近来回跳动永远无法触发到达判定。
修复逻辑非常简单:每帧计算当前位置到下一个目标点的直线距离,如果距离小于等于当前speed值加允许误差范围,就直接把当前位置吸附到目标点,判定该点到达,切换到下一个路径点。这个逻辑不管speed取多大,都不会出现冲过点漏判的情况,天然支持任意speed取值,误差范围可以自由设置。
优化后完整代码
let targets; let targetIndex = 0; let position; const speed = 3; // 可任意修改数值,不会出现到达判定失效问题 const arrivalThreshold = 1; // 到达判定误差范围1px function setup() { createCanvas(400, 400); targets = [ createVector(0, 0), createVector(50, 50), createVector(0, 0), createVector(0, 50), createVector(200, 200) ]; // 单独存储当前位置副本,不修改原始路径点数据 position = targets[0].copy(); } function draw() { background(220); moveCharacter(); drawCharacter(); } function drawCharacter() { strokeWeight(10); point(position.x, position.y); } function moveCharacter() { // 所有路径点走完就停止移动 if (targetIndex >= targets.length - 1) return; const currentTarget = targets[targetIndex + 1]; // 计算当前位置指向目标点的方向向量 const toTarget = p5.Vector.sub(currentTarget, position); // 计算当前位置到目标点的直线距离 const distance = toTarget.mag(); // 距离小于等于步长+到达阈值,直接吸附到目标点,切换下一个路径点 if (distance <= speed + arrivalThreshold) { position.set(currentTarget); targetIndex++; return; } // 归一化方向向量乘speed,得到恒定速度的移动步长,斜向移动速度也完全准确 toTarget.normalize().mult(speed); position.add(toTarget); }
对应的HTML引入部分和原有代码一致:
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
补充说明:你之前觉得lerp无法实现恒定速度是用法问题,上面用向量归一化的移动方式,是严格的恒定速度,不管路径是水平、垂直还是斜向,移动速度都完全等于你设定的speed值,比逐轴判断的逻辑简单很多,也不容易出边界bug。
内容的提问来源于stack exchange,提问作者Aaron
相关产品推荐
相关产品推荐

