如何逐渐旋转一个物体以面对另一个转动最短距离

How to gradually rotate an object to face another turning the shortest distance(如何逐渐旋转一个物体以面对另一个转动最短距离)
本文介绍了如何逐渐旋转一个物体以面对另一个转动最短距离的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在尝试根据与直接面向目标的度数(或弧度,我更喜欢度数)不同来旋转精灵,问题是当目标到达特定位置时精灵决定旋转一个完整的 360 到其他方式,而不是做额外的 10 个.这张图片可能更好地解释了这个问题:

I'm currently trying to rotate a sprite depending on how many degrees(or rads, I prefer degrees) it differs from facing straight towards a target, the problem is when the target reaches a certain position the sprites decides to do rotate a full 360 to other way instead of doing the 10 extra. This picture probably explains the problem better:

蓝色方块 = 目标

红色方块 = 物体

绿线 = 它想要的旋转

Green line = rotation it wants

黑线 = 当前旋转

棕色箭头 = 它如何旋转来实现这一点

Brown arrow = how it rotates to achieve this

红色箭头 = 我希望它如何旋转.

Red arrow = how I want it to rotate.

请注意,案例 1 始终有效,具体取决于它的旋转方式,但案例 2 始终执行该旋转,无论它是在当前旋转的右侧"还是左侧".

Note that Case 1 always work, depending what way it rotates, but Case 2 it always does that rotation, no matter if it is to the "right" or "left" of the current rotation.

这是我用来旋转对象的代码.

This is the code I'm using to rotate the object.

    Vector2 distance = new Vector2(target.worldPos.X - this.worldPos.X, target.worldPos.Y - this.worldPos.Y);
    float wantRot = (float)Math.Atan2(distance.Y, distance.X);
    if (this.rotation < wantRot)
        this.rotation += MathHelper.ToRadians(45) * Time.deltaTime;
    if (this.rotation > wantRot)
        this.rotation -= MathHelper.ToRadians(45) * Time.deltaTime;

我想要实现的是让它根据红色箭头而不是棕色箭头旋转(在案例 2 中).

What i want to achieve is have it rotate (in Case 2) according to the red arrow instead of the brown one.

注意:我不是编程方面的专家,我只是在过去的一年中不时进行过编程(主要是简单的 2D 射击/射击类游戏),因此将不胜感激.我也是一名学习编程的学生.

NOTE: I'm not an expert at programming, I've only done it from time to time for the past year(Mainly simple 2D Shooter/shoot'em up kind of games), so in depth explanation would be appreciated. I'm also a student learning programming.

PS:标题的建议也将不胜感激,因为我完全不知道该放什么.

PS: Suggestions for Title would also be appreciated as I had absolutely no idea what to put there.

推荐答案

你的问题是,目标可能在 5 角,对象可能面向 355 度(例如).根据你的测试,5小于355,所以逆时针走.

Your problem is that the target could be at angle 5, and the object could be facing 355 degrees (for example). According to your test, 5 is less than 355, so go anticlockwise.

你应该做的是测试目标是在你左边180度以内,还是在你右边180度以内,然后相应地移动.

What you should do is test whether the target is within 180 degrees to your left, or within 180 degrees to your right, then move accordingly.

棘手的部分是让检查在 360 <-> 0 周围环绕".看起来你的情况还剩下 0 度,所以当wantRot 位于 0 度的一侧时,硬测试是在里面.

The tricky part is getting the check to 'wrap' around 360 <-> 0. It looks like 0 degrees is left in your case, so the hard test is for when the wantRot is on the side that has 0 degrees within it.

如下图所示画一个圆圈,然后将您的对象放在我们所面对的左侧.您会看到必须分别检查 2 个阴影区域.

To visualise draw a circle as below, then place your object on the left of where we're facing. You'll see that you have to check the 2 shaded areas separately.

分别检查所有案例.

注意:下面的代码在我的脑海中,未经测试.您需要将度数更改为弧度.

Note: Code below is in my head and untested. You'll need to change degrees to radians.

int MoveDir = 0;
var BehindMe = this.rotation - 180;
if (BehindMe < 0)
    BehindMe += 360;

if (wantRot != this.rotation)
{
    if (wantRot == BehindMe)
        MoveDir = 1; // or randomly choose
    else if ((wantRot > BehindMe && wantRot < this.rotation) ||
             (this.rotation < 180 && (wantRot > BehindMe ||
                                      wantRot < this.rotation)))
        MoveDir = -1;
    else if ((wantRot < BehindMe && wantRot > this.rotation) ||
             (this.rotation > 180 && (wantRot < BehindMe ||
                                      wantRot > this.rotation))
        MoveDir= 1;

    this.rotation += MoveDir * MathHelper.ToRadians(45) * Time.deltaTime;
}

<小时>

方法二

看图片,你可能会发现你可以只检查物体是否在右边,如果不是,就假设它在左边(因为只要当前角度小于 180 度,检查它在对的很简单).如果当前角度超过 180 度,则颠倒这个概念 - 检查它是否在左侧,如果不是则假设在右侧.如下所示:


Method 2

From looking at the image, you may realise that you could just check whether the object on the right, then if not, assume it's on the left (since as long as the current angle is less than 180 degrees checking its on the right is easy). If the current angle is more than 180 degrees, then reverse the concept - check whether it's on the left and if not assume right. Something like below:

int MoveDir = 0;
var BehindMe = this.rotation - 180;
if (BehindMe < 0)
    BehindMe += 360;

if (wantRot != this.rotation)
{
    if (this.rotation <= 180)
    {
        if (wantRot > this.rotation && wanrRot < BehindMe)
            MoveDir = 1;
        else
            MoveDir = -1;
    }
    else
    {
        if (wantRot < this.rotation && wanrRot > BehindMe)
            MoveDir = -1;
        else
            MoveDir = 1;
    }

    this.rotation += MoveDir * MathHelper.ToRadians(45) * Time.deltaTime;
}

这篇关于如何逐渐旋转一个物体以面对另一个转动最短距离的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

DispatcherQueue null when trying to update Ui property in ViewModel(尝试更新ViewModel中的Ui属性时DispatcherQueue为空)
Drawing over all windows on multiple monitors(在多个监视器上绘制所有窗口)
Programmatically show the desktop(以编程方式显示桌面)
c# Generic Setlt;Tgt; implementation to access objects by type(按类型访问对象的C#泛型集实现)
InvalidOperationException When using Context Injection in ASP.Net Core(在ASP.NET核心中使用上下文注入时发生InvalidOperationException)
LINQ many-to-many relationship, how to write a correct WHERE clause?(LINQ多对多关系,如何写一个正确的WHERE子句?)