0

回転によって移動するプレーヤー スプライトがあり、その回転は常に変化していますが、ターゲットがその左または右にあり、前後の回転の 45 度以内にない場合も解決する必要があります。

私はこのコードを書きましたが、これはうまくいくと思いますが、片側を拾うだけで、反対側を少しだけ拾うようです。

        public void GrappleCheck(AsteroidSprite target)
    {
        float targetTragectory = (float)Math.Atan2(Position.Y - target.Position.Y, Position.X - target.Position.X);

        if (targetTragectory < 0)
            targetTragectory += (float)(Math.PI * 2);

        if (Rotation < 0)
            Rotation += (float)(Math.PI * 2);

        if ((targetTragectory > Rotation + (float)(MathHelper.PiOver4 / 2)) && (targetTragectory < Rotation + (float)(Math.PI - (MathHelper.PiOver4 / 2))))
        {
            target.Distance = Vector2.Distance(Position, target.Position);
            if (RightTarget != null)
            {
                if (RightTarget.Distance > target.Distance)
                {
                    RightTarget.isTarget = false;
                    RightTarget = target;
                    RightTarget.ColorTint = Color.Blue;
                    RightTarget.isTarget = true;
                }
            }
            else
            {
                RightTarget = target;
                RightTarget.ColorTint = Color.Blue;
                RightTarget.isTarget = true;
            }
        }
        else if ((targetTragectory < Rotation - (float)(MathHelper.PiOver4 / 2)) && (targetTragectory > Rotation - (float)(Math.PI - (MathHelper.PiOver4 / 2))))
        {
            target.Distance = Vector2.Distance(Position, target.Position);
            if (LeftTarget != null)
            {
                if (LeftTarget.Distance > target.Distance)
                {
                    LeftTarget.isTarget = false;
                    LeftTarget = target;
                    LeftTarget.ColorTint = Color.Red;
                    LeftTarget.isTarget = true;
                }
            }
            else
            {
                LeftTarget = target;
                LeftTarget.ColorTint = Color.Red;
                LeftTarget.isTarget = true;
            }
        }
        else
        {
            target.isTarget = false;
        }

        if (controlInput.IsHeld(Keys.X))
        {
            Speed = Speed;
        }
4

2 に答える 2

1

角度を操作するのは非常に煩わしい場合があります。角度を使用せずに問題を解決するいくつかの方法を次に示します。

まず、ターゲットへの方向と移動方向が必要です。

var targetDirection = target.Positon - Position;
// Update this to match the actual direction. The following line assumes that
// a rotation of 0 results in the right direction.
var movementDirection = new Vector2((float)Math.Cos(Rotation), (float)Math.Sin(Rotation));

解決したい最初の問題は、ターゲットが 45° の円錐内にあるかどうかを判断することです。次の式で実際の角度を計算できます。

var dot = Vector2.Dot(myDirection, targetDirection);
//if dot is negative, then target is behind me, so just use the absolute value
var cos = Math.Abs(dot) / myDirection.Length() / targetDirection.Length();
var angle = Math.Acos(cos);
if(angle < MathHelper.PiOver4 / 2) //45° opening angle
    ; // within cone
else
    ; // outside cone

2 番目の問題は、ターゲットが左側にあるか右側にあるかを判断することです。myDirectionこれには、直交し、左を指すベクトルを使用します。

//assuming that +x is the right axis and +y is the down axis
var normal = new Vector2(myDirection.Y, -myDirection.X);
dot = Vector2.Dot(normal, targetDirection);
if(dot > 0)
    ; // target is on the left side
else
    ; // target is on the right side

これにより、コードのクリーンアップが少し簡単になり、わかりやすくなることを願っています。読みやすくするために、一部のコードを別のメソッドで抽出することを検討する必要があります。

于 2013-02-10T15:56:15.633 に答える
0

さて、私はそれを解決しました。プレーヤーのローテーションは、0 から 2 x PI + または - にすることができます。

if (Rotation < 0)
    Rotation += (float)Math.PI * 2;

ターゲットへの回転は、atan2 の宣言方法とプレーヤーの位置に応じて、0-PI または 0 - 負の PI になります。

//This works out the difference from the targets rotation to the players rotation.

RotationDif = TargetRotation - PlayerRotation;

//If the difference is greater than PI then when we check to see if its is within
//the range 0-PI or 0-Negative PI it will be missed whilst still possibly being on 
//either side of the player, adding PI * 2 to the targets rotation basically spins
//it past the player so the Difference will be the shortest angle.

if(Math.Abs(RotationDif) > Math.PI)
   RotationDif = TargetRotation + (float)(Math.PI * 2) - PlayerRotation;

//Next we check to see if the target is left(negative) or
//the right(positive), the negative/positive assignment will depend
//on which way round you did the atan2 to get the target rotation.

if ((RotationDif > 0) && (RotationDif < (float)Math.PI))

    //Insert right target code here

else if ((RotationDif < 0) && (RotationDif > -(float)Math.PI))

    //Insert left target code here

else

    //Insert no target code here to cover all basis

それだけです。If (RotationDif > 0) などを別の方法で作成したので、前後の 45 度の角度は無視されます。

If ((RotationDif > (float)(Math.PI / 8) &&
    (RotationDif < (float)(Math.PI - (Math.PI / 8)))

反対側の場合は反対です。解決するのに2週間近くかかったので、これが他の誰かに役立つことを願っています:/

于 2013-02-12T22:35:54.520 に答える