制定出是否开启顺时针或逆时针从两个角度 [英] Work out whether to turn clockwise or anticlockwise from two angles

查看:194
本文介绍了制定出是否开启顺时针或逆时针从两个角度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

林做一个游戏的XNA。 我有敌人和球员。 人应该对球员逐渐转。他们应该制定出他们是否需要将顺时针或逆时针,两者中较短的。

Im making a game in XNA. I have enemies and player. The enemies should turn gradually towards the player. They should work out whether they need to turn clockwise or anticlockwise, whichever is shorter.

我的敌人目前面临的角度,它应该面向为弧度(敌人和玩家之间的线的角度),通过使用ATAN2,角

I got the angle the enemy is currently facing and the angle it should be facing (the angle of the line between the enemy and the player) as radians by using Atan2.

我得到一些怪异的行为虽然。比方说在下面的场景。敌人可能会转而一路走去错误的方向。

I get some weird behavior though. Lets say in the scenario below. the enemy might turn all the way around in the wrong direction.

我的code(下)越拉越长,我仍然有问题。这code是敌对阶级更新方法的一部分。 这必须是一个常见的​​问题,在游戏中需要克服。是否有处理这个问题某种方式?

My code (below) keeps getting longer and I'm still having issues. This code is part of the enemy classes Update method. This must be a common problem to overcome in games. Is there some way of dealing with this?

            //this bit is just in case enemy has rotated more than 360 degrees (gets set back to 0)
            if (Math.Abs(_blocklist[0]._floor.Revolutions) >= 2)
            {
                _blocklist[0]._floor.Rotation = 0.0f;
            }

            //enemy rotation in radians          
            float blockroat = _blocklist[0]._floor.Rotation;
            // vector to player - vector to enemy
            _vectToPlayer = playerpos - _blocklist[0].Centre
            angletoplayer = (float)(Math.Atan2(_vectToPlayer.Y, _vectToPlayer.X));
            diff = blockroat - angletoplayer;

            if (diff < -Math.PI)
            {
                diff += (float) Math.PI;
                diff = -diff;
            }
            else if (diff > Math.PI)
            {
                diff -= (float)Math.PI;
                diff = -diff;
            }

            // if enemy angle if off by a certain amount
            if (Math.Abs(diff) >_maxturn)
            {
                if (diff < 0)
                {
                    //turn clockwise
                    _blocklist[0]._floor.Rotation += _maxturn;
                }
                else
                {
                     //turn anti clockwise
                    _blocklist[0]._floor.Rotation -= _maxturn;
                }
            }


更新

最后我用这样的方法2 ..完美。此外,它是一个很大整洁比我的previous code


UPDATE

I ended up using method 2 like this.. Works perfectly. Also it is a lot neater than my previous code

            //enemy rotation in radians from farseer (red line)
            float brot = _blocklist[0]._floor.Rotation + ((float)Math.PI/2);
            //vector from enemy to player (blue line)
            Vector2 _vectToPlayer = playerpos - _blocklist[0].Centre;
            //cross product of 2d vectors
            cross = (_vectToPlayer.X * (float)Math.Sin(brot)) - ((float)Math.Cos(brot) * _vectToPlayer.Y);

            //tolerance for how closely enemy must point towards player
            if (Math.Abs(cross) > 5)
            {
                if (cross > 0)
                {
                    //turn anticlockwise
                    _blocklist[0]._floor.Rotation -= _npcstats.maxturnspeed;
                }
                else
                {
                    //turn clockwise
                    _blocklist[0]._floor.Rotation += _npcstats.maxturnspeed;
                } 
            }

我觉得我的previous code或多或少做完全相同的建议的方法1。 但我无法得到它的工作。我把这个下来farseers变幻莫测的坐标系+如何与自己的互动。

I think that my previous code was more or less doing exactly the suggested method 1. But I could not get it to work.. I put this down to the vagaries of farseers coordinate system + how it interacted with my own.

推荐答案

您使用的是我不熟悉的一个约定。在您的惯例,东面是0,北面是-π/ 2,西面是两个π和-π,南为π/ 2。所有角度是-π和π之间

Technique #1:

You are using a convention that I'm not familiar with. In your convention, east is 0, north is -π/2, west is both π and -π, and south is π/2. All angles are between -π and π.

通常朝东字符的角为零,北面是π/ 2,西面是π,而正南为3π/ 2。所有角度介于0和2π。

Normally the angle of a character facing east is zero, north is π/2, west is π, and due south is 3π/2. All angles are between 0 and 2π.

假设正常的惯例,而不是你的约定。首先,让你的红色和蓝色的矢量角度在正常惯例正确的;如何做到这一点是由你。

Let's assume the normal convention rather than your convention. Start by getting your red and blue vector angles correct in the normal convention; how you do that is up to you.

减去两个角度红色矢量的角度。现在,我们有这个家伙在面对正东的起源。

Subtract the angle of the red vector from both angles. Now we have the guy at the origin facing due east.

现在归新的蓝角;如果它小于0,加2π。如果它是大于2π较大,减去2π。做到这一点,直到它是一个介于0和2π。

Now normalize the new blue angle; if it is smaller than 0, add 2π. If it is larger than 2π, subtract 2π. Do that until it is between 0 and 2π.

现在我们有两个角度;新红矢量的角度为零而新蓝色矢量的角度是在0和2π。

Now we have two angles; the angle of the new red vector is zero and the angle of the new blue vector is between 0 and 2π.

如果新的蓝色矢量的角度小于π则字符在原点需要打开朝向其左侧。如果大于π然后右转。

If the angle of the new blue vector is less than π then the character at the origin needs to turn towards its left. If it is greater than π then turn right.

取非零点在你的蓝色和红色的载体,比如(BX,BY)(RX,RY)。现在计算 BX * RY - 由* RX 。如果是正数,向右转,如果是负的,向左转。如果它是零,那么他们要么直接朝向或者直接离开;在这种情况下,你必须搞清楚你在这种情况下,通过其他方式。 (这基本上是亚采的回答更直接地说。)

Take a non-zero point on your blue and red vectors, say (bx, by) and (rx, ry). Now compute bx * ry - by * rx. If it is positive, turn right, if it is negative, turn left. If it is zero then either they are facing directly towards or directly away; in that case you'll have to figure out which case you're in by some other means. (This is essentially Jacek's answer stated more directly.)

这篇关于制定出是否开启顺时针或逆时针从两个角度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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