javascript - 平滑 'turning'脚本

标签 javascript html canvas radians

我正在使用 Javascript 制作 HTML5 Canvas 游戏。

我想让一个物体平滑地转向某个方向。

我将方向存储为变量,并使用弧度。代码的工作原理如下:

window.setInterval(loop,25);

var dir = 0;
var targetDir = Math.PI/2;

function loop() {
  dir += (targetDir - dir) / 5;
  document.getElementById('text').innerHTML = dir; //To display the direction
}
<p id='text'></p>

它在大多数情况下都有效,但如果方向和目标方向在相反的左侧/右侧,计算机将假设到达目标的最快方法是一路绕过去,如下所示: (Image)

有人知道我可以使用一种算法来使其正常工作吗?

最佳答案

希望有人能给出一个优雅的解决方案来回答,但目前还没有,所以这就是我的做法。

我一直觉得这个问题的解决方案很不优雅,也就是说,我不知道是否有更好的方法,我也没有努力寻找。下面的两个函数将返回从函数 Math.atan2(yDif, xDif) 派生的两个 Angular 之间的最短方向,该函数返回 -Math.PI 范围内的 Angular > 到 Math.PI

获取最短方向。

// returns true if shortest direction is clockwise else false
function isShortestDirClockwise(ang1, ang2){
    if (ang1 < 0) {
        if ( (ang2 < 0 && ang1 > ang2) || (ang2 >= 0 && ang1 + Math.PI < ang2) ) {
            return false;        
        }
    } else {
        if ( (ang2 > 0 && ang1 > ang2) || (ang2 <= 0 && ang1 - Math.PI < ang2) ) {
            return false;        
        }
    }
    return true;
}

获取最短 Angular

// returns the shortest angle neg angles are counterClockwise positive are clockwise
function getShortestAngle(ang1, ang2){
    var cw = true; // clockwise
    var ang;
    if (ang1 < 0) {
        if( (ang2 < 0 && ang1 > ang2) || (ang2 >= 0 && ang1 + Math.PI < ang2) ) {
            cw = false;        
        }
    } else {
        if ( (ang2 > 0 && ang1 > ang2) || (ang2 <= 0 && ang1 - Math.PI < ang2) ) {
            cw = false;        
        }
    }
    if (cw) {
        var ang = ang2 - ang1;
        if (ang < 0) {
            ang = ang2 + Math.PI * 2 - ang1;
        }
        return ang;
    }
    var ang = ang1 - ang2;
    if (ang < 0) {
        ang = ang1 + Math.PI * 2 - ang2;
    }   
    return -ang;
}

由于我讨厌使用这些函数,所以我更喜欢下面稍微复杂但更优雅的解决方案。这会找到一组 3 点的最短 Angular 。中心点,以及我希望找到之间 Angular 两点,它总是返回任何两条线之间的最短 Angular 。

 // Warning may return NAN if there is no solution (ie one or both points (p1,p2) are at center)
 // Also uses Math.hypot check browser compatibility if you wish to use this function or use Math.sqrt(v1.x * v1.x + v1.y * v1.y) instead
 function getAngleBetween(center, p1, p2){
     var d;
     var ang;
     // get vectors from center to both points
     var v1 = { x : p1.x - center.x, y : p1.y - center.y};
     var v2 = { x : p2.x - center.x, y : p2.y - center.y};
     // normalise both vectors
     d = Math.hypot(v1.x, v1.y);
     v1.x /= d;
     v1.y /= d;
     d = Math.hypot(v2.x, v2.y);
     v2.x /= d;
     v2.y /= d;
     // cross product gets the angle in range -Math.PI / 2 to Math.PI / 2
     ang = Math.asin(v1.x * v2.y - v1.y * v2.x);
     // use the cross product of the line perpendicular to the first to find the quadrant
     if(-v1.y * v2.y - v1.x * v2.x > 0){
         if(ang < 0){
            ang = -Math.PI - ang;
         }else{
            ang = Math.PI - ang;
         }
     }
     return ang;
 }

关于javascript - 平滑 'turning'脚本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37780814/

相关文章:

javascript - 我正在尝试使用 selenium-webdriver 截取元素的屏幕截图,但抛出了 UnsupportedOperationError?

JavaScript:从数字中获取第二位数字?

javascript - 为什么我的简单邮件 php 表单需要很长时间才能加载?

html - 从 chrome 的扩展内容脚本访问 iframe 内容

javascript - 响应式(Reactive)表单验证不起作用

javascript - 无法在页面右侧找到“滑出”选项卡

javascript - 哪个更好 : using onclick or find element that triggered the event for handling events in jQuery?

javascript - globalCompositeOperation 在背景上绘制白色

javascript - 使用 html5 和 javascript 在图像上制作网格

jquery - 图片网址 : data:image/png;base64 (KineticJS)