平滑的“翻转”脚本 [英] Smooth 'turning' script

查看:255
本文介绍了平滑的“翻转”脚本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Javascript制作HTML5 Canvas游戏。

I am making an HTML5 Canvas game using Javascript.

我想让对象顺利转向某个方向。

I want to make an object turn smoothly to a certain direction.

我将方向存储为变量和使用弧度。代码的工作方式如下:

I am storing the direction as a variable, and using radians. The code works like this:

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>

大多数时候,但是如果方向和目标方向在相反的左/右侧,则计算机将假定到达目标的最快方式是到达所有方式,如下:
(图片)

It will work most of the time, but if the direction and target direction are on opposite left/right sides, the computer will assume the fastest way to get to the target is to to all the way around, like this: (Image)

有人知道算法我可以使它工作正常吗?

Does anyone know an algorithm I can use to make it work correctly?

推荐答案

希望有人会回答一个优雅的解决方案,我如何做到。

Was hoping someone would answer with an elegant solution, nothing yet so here is how I do it.

我一直觉得解决这个问题非常不起眼,说,我不知道有没有更好的方式,也没有努力找到一个。下面是两个函数将返回从函数 Math.atan2(yDif,xDif)导出的两个角度之间的最短方向,它返回范围内的一个角度 - Math.PI Math.PI

I have always found the solution to this problem very inelegant, that said, I do not know if there is a better way, nor have i endeavored to find one. Below are two functions that will return the shortest direction between two angles that derived from the function Math.atan2(yDif, xDif) which returns an angle in the range -Math.PI to Math.PI

取得最短方向。 / p>

Get shortest direction.

// 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;
}

取得最短角度

// 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个点找到最短的角度。中心点和两个点,我希望找到之间的角度,它总是返回任意两条线之间的最短角度。

As I loath using these functions I much prefer the slightly more complex yet more elegant solution below. This finds the shortest angle in terms of a set of 3 points. the center point, and the two points that I wish to find the angle between and it always returns the shortest angle between any two lines.

 // 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;
 }

这篇关于平滑的“翻转”脚本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆