【发布时间】:2019-04-03 01:56:32
【问题描述】:
我正在制作一个基于极坐标的人工智能导航系统。目的是将演员移动到一个位置,同时远离其路径上可能存在的障碍。
代码大部分时间都运行良好,但经过测试,我发现:当玩家、障碍物和演员都在 X 或 Y 方向或对角线完全对齐时,演员会卡在障碍物中。当玩家“拥抱”一堵墙时,这一点最为明显,因为演员的运动矢量被墙剪裁,使它们对齐。
单击 sn-p 中的按钮以查看我在说什么。
有没有办法防止这种情况发生?
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
let playerX = 100;
let playerY = 200;
let obstacleX = 200;
let obstacleY = 200;
let actorX = 300;
let actorY = 201;
function loop() {
// Wall clipping
if (actorX > 490) {
actorX = 490;
} else if (actorX < 10) {
actorX = 10;
}
if (actorY > 490) {
actorY = 490;
} else if (actorY < 10) {
actorY = 10;
}
// Vector between player and actor
let vectorPlayerX = playerX - actorX;
let vectorPlayerY = playerY - actorY;
// Vector between obstacle and actor
let vectorObstacleX = obstacleX - actorX;
let vectorObstacleY = obstacleY - actorY;
// Where to move, defaults to player's position
const anglePlayer = Math.atan2(vectorPlayerY, vectorPlayerX);
let moveAngle = anglePlayer;
// If near obstacle, adjust course and try to avoid it
if (Math.sqrt(vectorObstacleX * vectorObstacleX + vectorObstacleY * vectorObstacleY) < 50) {
const angleObstacle = Math.atan2(vectorObstacleY, vectorObstacleX);
moveAngle += anglePlayer - angleObstacle;
}
// Move the vector to desired location
actorX += Math.cos(moveAngle);
actorY += Math.sin(moveAngle);
//Drawing
ctx.clearRect(0, 0, 500, 500);
ctx.beginPath();
ctx.fillStyle = "gray";
ctx.arc(actorX, actorY, 10, 0, Math.PI * 2, true);
ctx.fill();
ctx.beginPath();
ctx.fillStyle = "orange";
ctx.arc(obstacleX, obstacleY, 10, 0, Math.PI * 2, true);
ctx.fill();
ctx.beginPath();
ctx.fillStyle = "blue";
ctx.arc(playerX, playerY, 10, 0, Math.PI * 2, true);
ctx.fill();
requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
function nonAligned() {
playerX = 100;
playerY = 200;
obstacleX = 200;
obstacleY = 200;
actorX = 300;
actorY = 201;
}
function alignedY() {
playerX = 100;
playerY = 490;
obstacleX = 200;
obstacleY = 490;
actorX = 300;
actorY = 490;
}
function alignedBoth() {
playerX = 200;
playerY = 200;
obstacleX = 300;
obstacleY = 300;
actorX = 400;
actorY = 400;
}
#options {
position: fixed;
top: 5px;
left: 5px;
}
<!DOCTYPE html>
<html>
<body>
<canvas id="canvas" width="500" height="500"></canvas>
<div id="options">
<button onclick="nonAligned()">Spawn non-aligned</button>
<button onclick="alignedY()">Spawn Y aligned</button>
<button onclick="alignedBoth()">Spawn diagonally aligned</button>
</div>
</body>
</html>
【问题讨论】:
-
角度是讨厌。如果可以,请始终使用向量。
-
@meowgoesthedog 我曾经通过获取演员和玩家之间的幅度来做到这一点,然后将其移向玩家并远离障碍物(如果足够近)。可能效率更高,因为它不使用 Math.atan2、cos 和 sin。我遇到了问题,因为演员的速度会因为障碍物的负力而减慢。
-
如果一个问题可以在极坐标中解决,那么它也可以在笛卡尔坐标中解决(如果不是更容易的话);使用笛卡尔的主要优点是您不必处理 +- 180 度的坐标奇点(即矢量数学是旋转不变的)。发布您拥有的基于矢量的原始代码。
-
嘿!我只是在此处发布此内容,因为它很酷,并且由于您正在研究 AI 导航,因此您应该知道它的存在。虚幻引擎有 unreal.js。您可以使用 Unreal 和它的 AI 系统,以及它的所有其他强大功能,只需使用 javascript:github.com/ncsoft/Unreal.js
标签: javascript algorithm math artificial-intelligence path-finding