p5.js中dist()函数无法计算近距离的问题排查
p5.js dist()函数计算距离异常问题排查与修复
问题描述
使用p5.js的dist()函数计算角色与可收集道具的距离时,出现以下异常:
- 角色完全覆盖道具时,距离始终不低于130;替换角色坐标为
mouseX/mouseY后,距离最低仅为90,无法趋近于0。 - 调整判断阈值(如120、140)也无法触发
collectable.isFound = true,新增道具后问题依旧。
相关代码片段:
distance = dist( collectable.x_pos, collectable.y_pos, gameChar_x, gameChar_y ); if (distance < 130) { collectable.isFound = true; }
问题根源
核心问题是道具的绘制坐标与距离计算坐标不匹配:
- 定义道具时,
collectable.y_pos = 310,但绘制道具时使用的是collectable.y_pos + 100(实际绘制y坐标为410)。 - 计算距离时仍使用原始的
collectable.y_pos,导致实际距离计算的是到310的位置,而非道具实际显示的410位置,自然无法趋近于0,也达不到collectable.size(40)的阈值。
修复方案
方案1:统一距离计算与绘制的坐标
将距离计算中的道具y坐标改为绘制时的实际坐标:
distance = dist(collectable.x_pos, collectable.y_pos + 100, mouseX, mouseY);
方案2:修正道具的初始坐标
直接将道具的y_pos设为绘制时的实际位置,避免偏移:
collectable = { x_pos: 400, y_pos: 410, // 原310 + 100 size: 40, isFound: false, };
同时修改绘制代码中的y坐标为collectable.y_pos:
ellipse(collectable.x_pos, collectable.y_pos, collectable.size); ellipse(collectable.x_pos, collectable.y_pos, collectable.size - 10); text("£", collectable.x_pos - 5, collectable.y_pos + 7);
额外优化:碰撞判断更精准
为了让视觉上的碰撞与逻辑判断一致,建议将判断阈值设为道具半径与角色(鼠标椭圆)半径之和:
- 道具半径:
collectable.size / 2(20) - 鼠标椭圆半径:10(绘制的是
ellipse(mouseX, mouseY, 20, 20)) - 阈值应为:
20 + 10 = 30
修改判断条件:
if (distance < (collectable.size / 2) + 10) { collectable.isFound = true; }
完整修正代码(采用方案2+优化)
var gameChar_x; var gameChar_y; var floorPos_y; var isLeft; var isRight; var isFalling; var isPlummeting; var distance; var collectable; function setup() { createCanvas(1024, 576); floorPos_y = (height * 3) / 4; gameChar_x = width / 2; gameChar_y = floorPos_y; isLeft = false; isRight = false; isFalling = false; isPlummeting = false; // 修正道具y_pos为实际绘制位置 collectable = { x_pos: 400, y_pos: 410, // 原310 + 100 size: 40, isFound: false, }; canyon = { x_pos: 200, width: 100, }; } function draw() { background(100, 155, 255); //fill the sky blue noStroke(); fill(0, 155, 0); rect(0, floorPos_y, width, height - floorPos_y); //draw some green ground //draw the canyon fill(175, 238, 238); rect(canyon.x_pos + 20, 432, canyon.width, 300); fill(100, 155, 255); rect(canyon.x_pos + 20, 432, canyon.width, 100); fill(210, 105, 30); rect(canyon.x_pos + 20, 432, canyon.width - 90, 300); fill(240, 128, 128); rect(canyon.x_pos + 110, 432, canyon.width - 90, 300); if (gameChar_x > canyon.x_pos + 20 && gameChar_x < canyon.x_pos + 100) { isPlummeting = true; } else { isPlummeting = false; } if ( (isPlummeting == true && gameChar_y >= floorPos_y) || gameChar_y > floorPos_y ) { gameChar_y += 5; } //COLLECTIBLE if (collectable.isFound == false) { fill(255, 215, 0); ellipse(collectable.x_pos, collectable.y_pos, collectable.size); fill(218, 165, 32); ellipse(collectable.x_pos, collectable.y_pos, collectable.size - 10); fill(255, 215, 0); text("£", collectable.x_pos - 5, collectable.y_pos + 7); textSize(collectable.size - 20); } // 修正距离计算与碰撞判断 ellipse(mouseX, mouseY, 20, 20); distance = dist(collectable.x_pos, collectable.y_pos, mouseX, mouseY); // 用半径之和作为阈值,判断更精准 if (distance < (collectable.size / 2) + 10) { collectable.isFound = true; } console.log(distance); }
内容的提问来源于stack exchange,提问作者Oluwaseun
相关产品推荐
相关产品推荐

