Как использовать формулу параболы в AS3 для запуска стрелки, которая всегда будет пересекать заданную точку - PullRequest
5 голосов
/ 11 мая 2011

Первое замечание: математически я совсем не настолько искусен.

Некоторое время назад я играл в игру на iPhone, где вы нажимаете точку, и из вашего замка стреляет стрела, которая всегда пересекаетТочка, которую вы нажали.Я хотел сделать похожую игру, думая, что это будет легко и быстро;затем я столкнулся с осознанием того, что математика для этого на самом деле находится за пределами моего уровня квалификации.

Я предполагаю, что они используют формулу параболы или что-то такое, что будет определять скорость и угол, необходимые при запуске стрелкичтобы стрелка всегда пересекала точку щелчка.

Я лишь смутно помню, как параболы работают в школе, и у меня нет шансов выработать какие-либо формулы.

Любая математическая помощь или идеи, которые могут быть прощереализовать было бы здорово.

Я хочу закончить с функцией в моем замке, например, так:

package
{
    import avian.framework.objects.AvElement;

    public class Castle extends AvElement
    {
        /**
         * Fires an arrow from this
         * @param ix The x intersection point
         * @param iy The y intersection point
         */
        public function fire(ix:Number, iy:Number):void
        {
            var ar:Arrow = new Arrow();

            ar.x = x;
            ar.y = y;

            // define angle and velocity based on ix, iy
            // ar.fireAngle = ??
            // ar.fireVelocity = ??

            parent.addChild(ar);
        }
    }
}

Обновление согласно вопросам в комментариях:

К стрелке не будет применено никаких сил, таких как ветер, трение и т. Д. Кроме того, начальная точка стрелки фиксируется на протяжении всей игры (в замке).

Вот примерИзображение для большей ясности: Arrow path

Чтобы быть как можно более четким:

  1. Стрелка всегда начинает свой путь с фиксированной точки (скажем:40, 120).
  2. Стрелка всегда должна пересекать заданную координату.
  3. Реальный путь - это то, чего я хотел бы достичь (очевидно, я могу просто стрелять прямо, чтобы перехватитьлюбая точка, но цель 1031 * состоит в том, чтобы стрелка сначала поднималась, а затем опускалась;проходя через желаемую координату в самой реалистичной точке своего пути).

Примечание: Чтобы избежать вопроса о наличии бесконечно возможных парабол, скорость стрелки может бытьисправлено - просто посмотрите на определение угла, под которым стрелка может оставаться.

Ответы [ 2 ]

8 голосов
/ 11 мая 2011

Траектория полета снаряда через гравитационное поле может быть описана применяя уравнения движения

Уравнения, которые я буду использовать:

1. v = u + at
2. s = ut + (at^2)/2

где

s = расстояние между начальной и конечной позициями
и = начальная скорость
v = конечная скорость
а = постоянное ускорение
t = время, необходимое для перехода из исходного состояния в конечное состояние

Ok. Чтобы оживить эту стрелку, мы рассчитаем ее новую скорость и положение в регулярные интервалы (каждый кадр) на основе его предыдущей скорости, положения и ускорение. Ускорение в этом случае полностью связано с гравитацией.

Позволяет упростить и измерить временные интервалы в кадрах, а не в секундах. Это дает нам t = 1 для приведенных выше уравнений, что позволяет нам переписать их как

1. v = u + a*1           => v = u + a
2. s = u*1 + (a*1^2)/2   => s = u + a/2

Теперь в направлении х ускорение, а = 0 (мы не берем учетная запись). В направлении у a = g ускорение силы тяжести. Если мы переписать эти уравнения для разрешенных для каждой оси мы получаем

для х:

1. vx = ux + 0        => vx = ux (no change so we'll ignore this)
2. sx = ux + 0/2      => sx = ux (convenient eh?)

для y:

1. vy = uy + g
2. sy = uy + g/2 

Итак, давайте подключим их к примеру сценария

public class Arrow extends Sprite
{
    //g is constant
    //it's actually closer to 10 but this is our world
    public static const g:Number = 2;

    //our arrow
    private var arrow:Shape;

    //start velocities
    private var ux:Number;
    private var uy:Number;

    public function Arrow()
    {
        arrow = new Shape();
        arrow.graphics.lineStyle( 1, 0 );
        arrow.graphics.lineTo( 30, 0 );
    }

    public function fire( vx:Number, vy:Number ):void
    {
        ux = vx;
        uy = vy;
        addChild( arrow );
        addEventListener( Event.ENTER_FRAME, fly );
    }

    private function fly( e:Event ):void
    {
        //lets use our equations
        var sx:Number = ux;       //distance moved in x dir

        var vy:Number = uy + g    //new velocity in y dir
        var sy:Number = uy + g/2  //distance moved in y dir

        //apply to arrow
        arrow.x += sx;
        arrow.y += sy;

        //save new y velocity
        uy = vy;

        //extra bonus rotation of arrow to point in the right direction
        arrow.rotation = Math.atan2( uy, ux ) * 180 / Math.PI;

    }

}
0 голосов
/ 11 мая 2011

Вы можете сделать это практически без математики:

import flash.display.Shape;
import flash.events.Event;

public class Arrow extends Shape
{
    private var xVelocity:Number;
    private var yVelocity:Number;

    public function Arrow(fireAngle:Number, fireVelocity:Number)
    {
        xVelocity = Math.cos(fireAngle) * fireVelocity;
        yVelocity = Math.sin(fireAngle) * fireVelocity;

        graphics.beginFill(0);
        graphics.drawCircle(0, 0, 5);
        graphics.endFill();

        addEventListener(Event.ENTER_FRAME, enterFrameHandler);
    }
    private function enterFrameHandler(ev:Event):void
    {
        x += xVelocity;
        y += yVelocity;
        yVelocity += 1;
    }
}
...