C #: объект выходит за пределы цели - PullRequest
1 голос
/ 14 марта 2011

У меня проблемы с диагностикой следующей проблемы.

Есть 2 объекта, кольцо и цель.Кольцо представляет корабль, а цель представляет пункт назначения.Когда пользователь щелкает в любом месте окна, цель помещается туда, куда вы щелкаете, и корабль затем перемещается в это место.Проблема, с которой я сталкиваюсь, заключается в том, что чем дальше движется корабль, тем больше скорость будет достигаться, тем самым превышая цель.Дальнейшее движение корабля приводит к более медленному замедлению.Я не уверен, где это происходит.Я предоставил код ниже:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace ArtificialDumb
{
    class PhysicsObject
    {
        public Vector2 Position;
        public Vector2 OldPosition;

        public float Mass;

        public Vector2 Acceleration;

        public float Drag = 0.01f;

        public PhysicsObject(float x, float y)
        {
            Position = OldPosition = new Vector2(x, y);
        }

        public PhysicsObject(Vector2 pos)
        {
            Position = OldPosition = pos;
        }

        public virtual void Update()
        {
            Vector2 velocity = Position - OldPosition;

            velocity *= (1 - Drag);

            OldPosition = Position;
            Position += velocity;

            Position += Acceleration;
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace ArtificialDumb
{
    class Ship : PhysicsObject
    {
        public float MaxThrust;

        public Vector2 Target;

        public Ship(Vector2 pos)
            : base(pos)
        {
            MaxThrust = 50f;
            Mass = 100;
        }

        public override void Update()
        {
            Vector2 diff = Target - Position;
            Vector2 Velocity = (Position - OldPosition);


            // Dark Magic. Do Not Touch.
            // This is the equation for projectile velocity. -ASR
            // Edited for correct float value -ASR
            // people keep touching! - AgH
            Vector2 thrust = diff - (Velocity * Velocity.Length() * 0.75f);

            thrust.Normalize();
            // todo: Account for when we don't need to use maximum thrusters
            thrust *= MaxThrust;

            Acceleration = thrust / Mass;
            base.Update();
        }
    }
}

Ответы [ 2 ]

2 голосов
/ 17 марта 2011

Это менее тривиально, чем кажется.Что делает это трудным, так это то, что вы должны заставить свой корабль оказаться в правильном положении со скоростью 0.

Если вы хотите сделать это правильно и не бояться математики, внедрите ПИД-регулятор .Это стандартный способ решения подобных проблем.В промышленности это часто используется для таких вещей, как автопилоты.

Однако есть более простой способ!

Если вы уже движетесь прямо к своей цели, вы можетеРассчитайте, где вы окажетесь, если начали замедляться.Предполагая, что ваше замедление постоянное:

endPos = Position + (Velocity * Velocity) / (2 * deceleration);

endPos - это то место, где вы окажетесь, если начнете торможение сейчас.Вы можете сравнить его с вашей целью, чтобы увидеть, находитесь ли вы в данный момент за пределами или за пределами.

Если вы знаете, что вам нужно затормозить, вы можете точно рассчитать, сколько вам нужно затормозить, чтобы достичь цели, переставивПриведенная выше формула:

deceleration  = (Velocity * Velocity) / (2 * (endPos - Position));

Замедление здесь - это «тяга», которая нужна вам, чтобы ваш корабль остановился там, где вы хотите.

Надеюсь, это поможет, пожалуйста, сообщите мне, еслиВы ничего не понимаете или не хотите объяснить, как я пришел к вышеприведенным формулам.

0 голосов
/ 16 марта 2011

Это общая проблема с физическими симуляциями.Что вы хотите сделать, это при каждом обновлении проверять путь от последней известной позиции до текущей позиции.Если на пути есть какая-либо геометрия, вы знаете, что должны были столкнуться.

В этот момент вы можете выбрать, как реагировать.Многие физические библиотеки, такие как Farseer , фактически перемещают объект обратно в точку столкновения, а затем позволяют реакции (отскок, вращение и т. Д.) Оттуда

...